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

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

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

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

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

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

Введение

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

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

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

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

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

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

Задайте слои

Стандартный 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

Постоянный Sinc Filterbank

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