Идентификация динамика Используя пользовательский слой SincNet и глубокое обучение

В этом примере вы обучаете три сверточных нейронных сети (CNNs) выполнять верификацию динамика и затем сравнивать эффективность архитектур. Архитектуры трех CNNs являются всем эквивалентом за исключением первого сверточного слоя в каждом:

  1. В первой архитектуре первый сверточный слой является "стандартным" сверточным слоем, реализованное использование convolution2dLayer.

  2. Во второй архитектуре первый сверточный слой является постоянным sinc filterbank, реализованное использование пользовательского слоя.

  3. В третьей архитектуре первый сверточный слой является обучаемым sinc filterbank, реализованное использование пользовательского слоя. Эта архитектура упоминается как SincNet [1].

[1] показывает, что заменяющий стандартный сверточный слой на filterbank слой приводит к более быстрой учебной сходимости и более высокой точности. [1] также показывает что, делая параметры набора фильтров learnable выражениями дополнительное увеличение производительности.

Введение

Идентификация динамика является видной областью исследования со множеством приложений включая судебную экспертизу и биометрическую аутентификацию. Много идентификационных систем динамика зависят от предварительно вычисленных функций, таких как i-векторы или MFCCs, которые затем поданы в машинное обучение или нейронные сети для глубокого обучения для классификации. Другие речевые системы глубокого обучения обходят этап извлечения признаков и кормят звуковым сигналом непосредственно сеть. В таких комплексных системах сеть непосредственно изучает низкоуровневые характеристики звукового сигнала.

В этом примере вы сначала обучаете традиционный сквозной идентификационный CNN динамика. Изученные фильтры имеют тенденцию иметь случайные формы, которые не соответствуют перцепционному доказательству или знанию того, как человеческое ухо работает, особенно в сценариях, где сумма обучающих данных ограничивается [1]. Вы затем заменяете первый сверточный слой в сети с пользовательским sinc filterbank слой, который вводит структуру и ограничения на основе перцепционного доказательства. Наконец, вы обучаете архитектуру SincNet, которая добавляет обучаемость в sinc filterbank параметры.

Три архитектуры нейронной сети, исследуемые в примере, получены в итоге можно следующим образом:

  1. Стандартная Сверточная нейронная сеть - входная форма волны непосредственно соединяется со случайным образом инициализированным сверточным слоем, который пытается изучить функции и характеристики получения от необработанных аудио систем координат.

  2. ConstantSincLayer - К входной форме волны применяют операцию свертки с набором фиксированной ширины sinc функции (полосовые фильтры), равномерно распределенные по шкале mel.

  3. 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

Задайте слои

Стандартный 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 применяет операцию свертки к входным кадрам с банком полосовых фильтров. Пропускная способность и начальные частоты фильтров 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