В этом примере вы обучаете три сверточные нейронные сети (CNNs) для выполнения верификации динамика и затем сравниваете производительности архитектур. Архитектуры всех трех CNN эквивалентны, за исключением первого сверточного слоя в каждом:
В первой архитектуре первый сверточный слой является «стандартным» сверточным слоем, реализованным с помощью convolution2dLayer.
Во второй архитектуре первый сверточный слой представляет собой постоянную группу фильтров синуса, реализованную с использованием пользовательского слоя.
В третьей архитектуре первый сверточный слой является обучаемым sinc filterbank, реализованным с использованием пользовательского слоя. Эта архитектура упоминается как SincNet [1].
[1] показывает, что замена стандартного сверточного слоя слоем набора фильтров приводит к более быстрой сходимости обучения и более высокой точности. [1] также показывает, что обеспечение возможности изучения параметров банка фильтров приводит к дополнительному повышению эффективности.
Идентификация спикера является заметной исследовательской областью с различными приложениями, включая криминалистику и биометрическую аутентификацию. Многие системы идентификации диктора зависят от предварительно вычисленных функций, таких как i-векторы или MFCC, которые затем подаются в машинное обучение или нейронные сети для глубокого обучения для классификации. Другие речевые системы глубокого обучения обходят стадию редукции данных и подают аудиосигнал непосредственно в сеть. В таких сквозных системах сеть непосредственно изучает характеристики низкоуровневого аудиосигнала.
В этом примере вы сначала обучите традиционную сквозную идентификацию говорящего CNN. Полученные фильтры, как правило, имеют случайные формы, которые не соответствуют перцептивным доказательствам или знаниям о том, как работает человеческое ухо, особенно в сценариях, где объем обучающих данных ограничен [1]. Затем вы заменяете первый сверточный слой в сети пользовательским слоем sinc filterbank, который вводит структуру и ограничения, основанные на перцептивных доказательствах. Наконец, вы обучаете архитектуру SincNet, которая добавляет возможности обучения в параметры sinc filterbank.
Три архитектуры нейронных сетей, исследованные в примере, суммируются следующим образом:
Стандартная сверточная нейронная сеть - вход сигнал непосредственно соединяется с случайным образом инициализированным сверточным слоем, который пытается узнать функции и захватить характеристики из необработанного аудио систем координат.
ConstantSincLayer - форма входа волны свернута с набором функций sinc фиксированной ширины (полосно-пропускающие фильтры), равномерно разнесенных по шкале меля.
SincNetLayer - форма волны входа свернута с набором функций sinc, параметры которых выучены сетью. В архитектуре SincNet сеть настраивает параметры функции sinc во время обучения.
Этот пример определяет и обучает три нейронные сети, предложенные выше, и оценивает их эффективность на LibriSpeech Dataset [2].
В этом примере вы используете подмножество набора данных LibriSpeech Dataset [2]. LibriSpeech Dataset является большим корпусом считанной английской речи, выбранной с частотой 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);
Используйте вспомогательную функцию, precrocessAudioData ,для предварительной обработки обучающих и тестовых данных. XTrain и XTest содержат train и тестовые речевые системы координат, соответственно. YTrain и YTest содержат train и тестовые метки, соответственно.
[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 свертывает входные кадры с набором фиксированных полосно-пропускающих фильтров. Полосовые фильтры являются линейной комбинацией двух фильтров синуса во временном интервале. Частоты полосно-пропускающих фильтров разнесены линейно по шкале меля.
Реализация для слоя набора фильтров постоянного синуса может быть найдена в 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);

The plotNFilters метод строит графики частотной характеристики n фильтры с одинаково разнесенными индексами фильтров. Постройте график величины частотной характеристики девяти фильтров в ConstantSincLayer.
figure n = 9; plotNFilters(constSincNet.Layers(2),n)

В этом разделе вы используете обучаемый слой SincNet в качестве первого сверточного слоя в сети. Слой SincNet свертывает входные кадры с помощью банка полосно-пропускающих фильтров. Шумовая полоса и начальные частоты фильтров SincNet инициализируются с равными интервалами в шкале mel. Слой SincNet пытается узнать лучшие параметры для этих полосно-пропускающих фильтров в рамках нейронной сети.
Реализация для слоя фильтра слоя SincNet представлена в 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] M. Ravanelli and Y. Bengio, «Steaker Recognition from Raw Waveform with SincNet», 2018 семинар по технологии разговорного языка IEEE (SLT), Афины, Греция, 2018, стр. 1021-1028, doi: 10 .11.11.09/SLLTT.2018.18.8.8.
[2] В. Панаетов, Г. Чен, Д. Пови и С. Худэнпур, «Librispeech: корпус ASR на основе аудиокниг общественного достояния», Международная конференция IEEE 2015 года по вопросам Акустики, Речи и Сигнала, Обрабатывающего (ICASSP), Брисбена, QLD, 2015, стр 5206-5210, doi: 10.1109/ICASSP.2015.7178964