В этом примере вы обучаете три сверточных нейронных сети (CNNs) выполнять верификацию динамика и затем сравнивать эффективность архитектур. Архитектуры трех CNNs являются всем эквивалентом за исключением первого сверточного слоя в каждом:
В первой архитектуре первый сверточный слой является "стандартным" сверточным слоем, реализованное использование convolution2dLayer
.
Во второй архитектуре первый сверточный слой является постоянным sinc filterbank, реализованное использование пользовательского слоя.
В третьей архитектуре первый сверточный слой является обучаемым sinc filterbank, реализованное использование пользовательского слоя. Эта архитектура упоминается как SincNet [1].
[1] показывает, что заменяющий стандартный сверточный слой на filterbank слой приводит к более быстрой учебной сходимости и более высокой точности. [1] также показывает что, делая параметры набора фильтров learnable выражениями дополнительное увеличение производительности.
Идентификация динамика является видной областью исследования со множеством приложений включая судебную экспертизу и биометрическую аутентификацию. Много идентификационных систем динамика зависят от предварительно вычисленных функций, таких как i-векторы или MFCCs, которые затем поданы в машинное обучение или нейронные сети для глубокого обучения для классификации. Другие речевые системы глубокого обучения обходят этап извлечения признаков и кормят звуковым сигналом непосредственно сеть. В таких комплексных системах сеть непосредственно изучает низкоуровневые характеристики звукового сигнала.
В этом примере вы сначала обучаете традиционный сквозной идентификационный CNN динамика. Изученные фильтры имеют тенденцию иметь случайные формы, которые не соответствуют перцепционному доказательству или знанию того, как человеческое ухо работает, особенно в сценариях, где сумма обучающих данных ограничивается [1]. Вы затем заменяете первый сверточный слой в сети с пользовательским sinc filterbank слой, который вводит структуру и ограничения на основе перцепционного доказательства. Наконец, вы обучаете архитектуру SincNet, которая добавляет обучаемость в sinc filterbank параметры.
Три архитектуры нейронной сети, исследуемые в примере, получены в итоге можно следующим образом:
Стандартная Сверточная нейронная сеть - входная форма волны непосредственно соединяется со случайным образом инициализированным сверточным слоем, который пытается изучить функции и характеристики получения от необработанных аудио систем координат.
ConstantSincLayer - К входной форме волны применяют операцию свертки с набором фиксированной ширины sinc функции (полосовые фильтры), равномерно распределенные по шкале mel.
SincNetLayer - К входной форме волны применяют операцию свертки с набором функций sinc, параметры которых изучены сетью. В архитектуре SincNet сеть настраивает параметры функций sinc в то время как обучение.
Этот пример задает и обучает эти три нейронных сети, предложенные выше, и оценивает их эффективность на Наборе данных LibriSpeech [2].
В этом примере вы используете подмножество Набора данных LibriSpeech [2]. Набор данных LibriSpeech является большим корпусом английской речи чтения, произведенной на уровне 16 кГц. Данные выведены из аудиокниг, считанных из проекта LibriVox.
downloadDatasetFolder = tempdir; filename = "train-clean-100.tar.gz"; url = "http://www.openSLR.org/resources/12/" + filename; datasetFolder = fullfile(downloadDatasetFolder,"LibriSpeech","train-clean-100"); if ~isfolder(datasetFolder) gunzip(url,downloadDatasetFolder); unzippedFile = fullfile(downloadDatasetFolder,filename); untar(unzippedFile{1}(1:end-3),downloadDatasetFolder); end
Создайте audioDatastore
возразите, чтобы получить доступ к аудиоданным LibriSpeech.
ADS = audioDatastore(datasetFolder,'IncludeSubfolders',1);
Извлеките марку докладчика из пути к файлу.
ADS.Labels = extractBetween(ADS.Files,fullfile(datasetFolder,filesep),filesep);
Полный dev-train-100
набор данных составляет приблизительно 6 Гбайт данных. Чтобы обучить сеть с данными от всего 251 докладчика, установите reduceDataset
к false
. Чтобы запустить этот пример быстро с данными всего от шести докладчиков, установите reduceDataset
к true
.
reducedDataSet = false; if reducedDataSet индексы = cellfun ((c) str2double (c) <50, ADS.Labels); %#ok ADS = подмножество (ADS, индексы); end ADS = splitEachLabel (ADS, 0.1);
Разделите звуковые файлы в обучение и тестовые данные. 80% звуковых файлов присвоены набору обучающих данных, и 20% присвоены набору тестов.
[ADSTrain,ADSTest] = splitEachLabel(ADS,0.8);
Постройте один из звуковых файлов и слушайте его.
[audioIn,dsInfo] = read(ADSTrain); Fs = dsInfo.SampleRate; sound(audioIn,Fs) t = (1/Fs)*(0:length(audioIn)-1); plot(t,audioIn) title("Audio Sample") xlabel("Time (s)") ylabel("Amplitude") grid on
Сбросьте учебный datastore.
reset(ADSTrain)
CNNs ожидают, что входные параметры будут иметь сопоставимые размерности. Вы предварительно обработаете аудио путем удаления областей тишины и затем повредите остающуюся речь в системы координат на 200 мс с перекрытием на 40 мс.
Установите параметры для предварительной обработки.
frameDuration = 200e-3; overlapDuration = 40e-3; frameLength = floor(Fs*frameDuration); overlapLength = round(Fs*overlapDuration);
Используйте функцию поддержки, preprocessAudioData, чтобы предварительно обработать обучение и тестовые данные. XTrain
и XTest
содержите обучение и протестируйте речевые системы координат, соответственно. YTrain
и YTest
содержите обучение и протестируйте метки, соответственно.
[XTrain,YTrain] = preprocessAudioData(ADSTrain,frameLength,overlapLength,Fs);
Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 6).
[XTest,YTest] = preprocessAudioData(ADSTest,frameLength,overlapLength,Fs);
Стандартный CNN вдохновлен архитектурой нейронной сети в [1].
numFilters = 80; filterLength = 251; numSpeakers = numel(unique(ADS.Labels)); layers = [ imageInputLayer([1 frameLength 1]) % First convolutional layer convolution2dLayer([1 filterLength],numFilters) batchNormalizationLayer leakyReluLayer(0.2) maxPooling2dLayer([1 3]) % This layer is followed by 2 convolutional layers convolution2dLayer([1 5],60) batchNormalizationLayer leakyReluLayer(0.2) maxPooling2dLayer([1 3]) convolution2dLayer([1 5],60) batchNormalizationLayer leakyReluLayer(0.2) maxPooling2dLayer([1 3]) % This is followed by 3 fully-connected layers fullyConnectedLayer(256) batchNormalizationLayer leakyReluLayer(0.2) fullyConnectedLayer(256) batchNormalizationLayer leakyReluLayer(0.2) fullyConnectedLayer(256) batchNormalizationLayer leakyReluLayer(0.2) fullyConnectedLayer(numSpeakers) softmaxLayer classificationLayer];
Анализируйте слои нейронной сети с помощью analyzeNetwork
функция
analyzeNetwork(layers)
Обучите нейронную сеть в течение 15 эпох с помощью adam
оптимизация. Переставьте обучающие данные перед каждой эпохой. Опции обучения для нейронной сети установлены с помощью trainingOptions
. Используйте тестовые данные в качестве данных о валидации, чтобы наблюдать, как производительность сети улучшается, в то время как обучение прогрессирует.
numEpochs = 15; miniBatchSize = 128; validationFrequency = floor(numel(YTrain)/miniBatchSize); options = trainingOptions("adam", ... "Shuffle","every-epoch", ... "MiniBatchSize",miniBatchSize, ... "Plots","training-progress", ... "Verbose",false,"MaxEpochs",numEpochs, ... "ValidationData",{XTest,categorical(YTest)}, ... "ValidationFrequency",validationFrequency);
Чтобы обучить сеть, вызовите trainNetwork
.
[convNet,convNetInfo] = trainNetwork(XTrain,YTrain,layers,options);
Постройте частотную характеристику величины девяти фильтров, усвоенных из стандартной сети CNN. Форма этих фильтров не интуитивна и не соответствует перцепционному знанию. Следующий раздел исследует эффект использования ограниченных форм фильтра.
F = squeeze(convNet.Layers(2,1).Weights); H = zeros(size(F)); Freq = zeros(size(F)); for ii = 1:size(F,2) [h,f] = freqz(F(:,ii),1,251,Fs); H(:,ii) = abs(h); Freq(:,ii) = f; end idx = linspace(1,size(F,2),9); idx = round(idx); figure for jj = 1:9 subplot(3,3,jj) plot(Freq(:,idx(jj)),H(:,idx(jj))) sgtitle("Frequency Response of Learned Standard CNN Filters") xlabel("Frequency (Hz)") end
В этом разделе вы заменяете первый сверточный слой в стандартном CNN с постоянным sinc filterbank слой. Постоянный sinc filterbank слой применяет операцию свертки к входным кадрам с банком фиксированных полосовых фильтров. Полосовые фильтры являются линейной комбинацией двух sinc, просачивается временной интервал. Частоты полосовых фильтров расположены с интервалами линейно по шкале mel.
Реализация для постоянного sinc filterbank слой может быть найдена в constantSincLayer.m
файл (присоединенный к этому примеру). Задайте параметры для ConstantSincLayer
. Используйте 80 фильтров и длину фильтра 251.
numFilters = 80;
filterLength = 251;
numChannels = 1;
name = 'constant_sinc';
Измените первый сверточный слой от стандартного CNN до ConstantSincLayer
и сохраните другие слои неизменными.
cSL = constantSincLayer(numFilters,filterLength,Fs,numChannels,name)
cSL = constantSincLayer with properties: Name: 'constant_sinc' NumFilters: 80 SampleRate: 16000 FilterLength: 251 NumChannels: [] Filters: [1×251×1×80 single] MinimumFrequency: 50 MinimumBandwidth: 50 StartFrequencies: [1×80 double] Bandwidths: [1×80 double] Show all properties
layers(2) = cSL;
Обучите сеть с помощью trainNetwork
функция. Используйте те же опции обучения, заданные ранее.
[constSincNet,constSincInfo] = trainNetwork(XTrain,YTrain,layers,options);
plotNFilters
метод строит частотную характеристику величины n
фильтры с равномерно распределенными индексами фильтра. Постройте частотную характеристику величины девять, просачивается ConstantSincLayer
.
figure n = 9; plotNFilters(constSincNet.Layers(2),n)
В этом разделе вы используете обучаемый слой SincNet в качестве первого сверточного слоя в вашей сети. Слой SincNet применяет операцию свертки к входным кадрам с банком полосовых фильтров. Полоса пропускания и начальные частоты фильтров SincNet инициализируются как равномерно распределенные в шкале mel. Слой SincNet пытается изучить лучшие параметры для этих полосовых фильтров в среде нейронной сети.
Реализация для слоя SincNet filterbank слой может быть найдена в sincNetLayer.m
файл (присоединенный к этому примеру). Задайте параметры для SincNetLayer
. Используйте 80 фильтров и длину фильтра 251.
numFilters = 80;
filterLength = 251;
numChannels = 1;
name = 'sinc';
Замените ConstantSincLayer
от предыдущей сети с SincNetLayer
. Этот новый слой имеет два настраиваемых параметра: FilterFrequencies
и FilterBandwidths
.
sNL = sincNetLayer(numFilters,filterLength,Fs,numChannels,name)
sNL = sincNetLayer with properties: Name: 'sinc' NumFilters: 80 SampleRate: 16000 FilterLength: 251 NumChannels: [] Window: [1×251 double] TimeStamps: [1×251 double] MinimumFrequency: 50 MinimumBandwidth: 50 Learnable Parameters FilterFrequencies: [1×80 double] FilterBandwidths: [1×80 double] Show all properties
layers(2) = sNL;
Обучите сеть с помощью trainNetwork
функция. Используйте те же опции обучения, заданные ранее.
[sincNet,sincNetInfo] = trainNetwork(XTrain,YTrain,layers,options);
Используйте plotNFilters
метод SincNetLayer
визуализировать частотную характеристику величины девяти фильтров с равномерно распределенными индексами, изученными SincNet.
figure plotNFilters(sincNet.Layers(2),9)
Таблица суммирует точность системы координат для всех трех нейронных сетей.
NetworkType = {'Standard CNN','Constant Sinc Layer','SincNet Layer'}'; Accuracy = [convNetInfo.FinalValidationAccuracy;constSincInfo.FinalValidationAccuracy;sincNetInfo.FinalValidationAccuracy]; resultsSummary = table(NetworkType,Accuracy)
resultsSummary=3×2 table
NetworkType Accuracy
_______________________ ________
{'Standard CNN' } 72.97
{'Constant Sinc Layer'} 74.902
{'SincNet Layer' } 78.062
Постройте точность на наборе тестов против номера эпохи, чтобы видеть, как хорошо сети учатся как количество увеличения эпох. SincNet превосходит по характеристикам ConstantSincLayer
сеть, особенно во время ранних стадий обучения. Это показывает, что обновление параметров полосовых фильтров в среде нейронной сети приводит к более быстрой сходимости. Это поведение только наблюдается, когда набор данных достаточно большой, таким образом, это не может быть замечено когда reduceDataSet
установлен в true
.
epoch = linspace(0,numEpochs,numel(sincNetInfo.ValidationAccuracy(~isnan(sincNetInfo.ValidationAccuracy)))); epoch = [epoch,numEpochs]; sinc_valAcc = [sincNetInfo.ValidationAccuracy(~isnan(sincNetInfo.ValidationAccuracy)),... sincNetInfo.FinalValidationAccuracy]; const_sinc_valAcc = [constSincInfo.ValidationAccuracy(~isnan(constSincInfo.ValidationAccuracy)),... constSincInfo.FinalValidationAccuracy]; conv_valAcc = [convNetInfo.ValidationAccuracy(~isnan(convNetInfo.ValidationAccuracy)),... convNetInfo.FinalValidationAccuracy]; figure plot(epoch,sinc_valAcc,'-*','MarkerSize',4) hold on plot(epoch,const_sinc_valAcc,'-*','MarkerSize',4) plot(epoch,conv_valAcc,'-*','MarkerSize',4) ylabel('Frame-Level Accuracy (Test Set)') xlabel('Epoch') xlim([0 numEpochs+0.3]) title('Frame-Level Accuracy Versus Epoch') legend("sincNet","constantSincLayer","conv2dLayer","Location","southeast") grid on
На рисунке выше, точность последнего кадра несколько отличается от точности системы координат, которая вычисляется в последней итерации. В то время как обучение, слои нормализации партии. выполняют нормализацию по мини-пакетам. Однако в конце обучения, слои нормализации партии. нормируют по целым обучающим данным, который приводит к небольшому изменению в эффективности.
function [X,Y] = preprocessAudioData(ADS,SL,OL,Fs) if ~isempty(ver('parallel')) pool = gcp; numPar = numpartitions(ADS,pool); else numPar = 1; end parfor ii = 1:numPar X = zeros(1,SL,1,0); Y = zeros(0); subADS = partition(ADS,numPar,ii); while hasdata(subADS) [audioIn,dsInfo] = read(subADS); speechIdx = detectSpeech(audioIn,Fs); numChunks = size(speechIdx,1); audioData = zeros(1,SL,1,0); for chunk = 1:numChunks % Remove trail end audio audio_chunk = audioIn(speechIdx(chunk,1):speechIdx(chunk,2)); audio_chunk = buffer(audio_chunk,SL,OL); q = size(audio_chunk,2); % Split audio into 200 ms chunks audio_chunk = reshape(audio_chunk,1,SL,1,q); % Concatenate with existing audio audioData = cat(4,audioData,audio_chunk); end audioLabel = str2double(dsInfo.Label{1}); % Generate labels for training and testing by replecating matrix audioLabelsTrain = repmat(audioLabel,1,size(audioData,4)); % Add data points for current speaker to existing data X = cat(4,X,audioData); Y = cat(2,Y,audioLabelsTrain); end XC{ii} = X; YC{ii} = Y; end X = cat(4,XC{:}); Y = cat(2,YC{:}); Y = categorical(Y); end
[1] М. Раванелли и И. Бенхио, "Распознавание динамика от Необработанной Формы волны с SincNet", 2 018 Семинаров по Технологии Разговорного языка IEEE (SLT), Афины, Греция, 2018, стр 1021-1028, doi: 10.1109/SLT.2018.8639585.
[2] В. Панаетов, Г. Чен, Д. Пови и С. Худэнпур, "Librispeech: корпус ASR на основе аудиокниг общественного достояния", 2 015 Международных конференций IEEE по вопросам Акустики, Речи и Обработки сигналов (ICASSP), Брисбена, QLD, 2015, стр 5206-5210, doi: 10.1109/ICASSP.2015.7178964