Разговорное распознавание цифры с пользовательским логарифмическим слоем спектрограммы и глубокое обучение

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

Данные

Клонируйте или загрузите Свободный разговорный набор данных цифры (FSDD), доступный в https://github.com/Jakobovski/free-spoken-digit-dataset. FSDD является открытым набором данных, что означает, что это может расти в зависимости от времени. Этот пример использует версию, фиксировавшую 12 августа 2020, который состоит из 3 000 записей на английском языке цифр 0 через 9 полученных от шести докладчиков. На каждой цифре говорит 50 раз каждый динамик. Данные производятся на уровне 8 000 Гц.

Используйте audioDatastore управлять доступом к данным. Установите location свойство к местоположению папки записей FSDD на вашем компьютере. Этот пример использует основную папку, возвращенную tempdir MATLAB команда.

pathToRecordingsFolder = fullfile(tempdir,'free-spoken-digit-dataset','recordings');
location = pathToRecordingsFolder;
ads = audioDatastore(location);

Функция помощника helpergenLabels создает категориальный массив меток из файлов FSDD. Исходный код для helpergenLabels перечислен в приложении. Перечислите классы и количество примеров в каждом классе.

ads.Labels = helpergenLabels(ads);
summary(ads.Labels)
     0      300 
     1      300 
     2      300 
     3      300 
     4      300 
     5      300 
     6      300 
     7      300 
     8      300 
     9      300 

Извлеките четыре звуковых файла, соответствующие различным цифрам. Используйте stft построить их спектрограммы в децибелах. Различия в структуре форманты произнесения являются заметными в спектрограмме. Это делает спектрограмму разумным представлением сигнала для обучения отличить цифры в глубокой сети.

adsSample = subset(ads,[1,301,601,901]);
SampleRate = 8000;
for i = 1:4
    [audioSamples,info] = read(adsSample); 
    subplot(2,2,i)
    stft(audioSamples,SampleRate,'FrequencyRange','onesided');
    title('Digit: '+string(info.Label))
end

Разделите FSDD в наборы обучающих данных и наборы тестов при поддержании равных пропорций метки в каждом подмножестве. Для восстанавливаемых результатов, набор генератор случайных чисел к его значению по умолчанию. Восемьдесят процентов, или 2 400 записей, используются для обучения. Остающиеся 600 записей, 20% общего количества, протянуты для тестирования.

rng default;
ads = shuffle(ads);
[adsTrain,adsTest] = splitEachLabel(ads,0.8);

Подтвердите, что и наборы обучающих данных и наборы тестов содержат правильные пропорции каждого класса.

disp(countEachLabel(adsTrain))
    Label    Count
    _____    _____

      0       240 
      1       240 
      2       240 
      3       240 
      4       240 
      5       240 
      6       240 
      7       240 
      8       240 
      9       240 
disp(countEachLabel(adsTest))
    Label    Count
    _____    _____

      0       60  
      1       60  
      2       60  
      3       60  
      4       60  
      5       60  
      6       60  
      7       60  
      8       60  
      9       60  

Записи в FSDD не имеют универсальной длины в выборках. Чтобы использовать спектрограмму в качестве представления сигнала в глубокой сети, универсальная входная длина требуется. Анализ аудиозаписей в этой версии FSDD указывает, что общая продолжительность 8 192 выборок является соответствующей, чтобы гарантировать, что никакая разговорная цифра не отключена. Записи, больше, чем 8 192 выборки в длине, являются усеченными к 8 192 выборкам, в то время как записи меньше чем с 8 192 выборками симметрично дополнены к длине 8 192. Функция помощника helperReadSPData обрезает или заполняет данные к 8 192 выборкам и нормирует каждую запись на ее максимальное значение. Исходный код для helperReadSPData перечислен в приложении. Эта функция помощника применяется к каждой записи при помощи datastore преобразования в сочетании с audioDatastore.

transTrain = transform(adsTrain,@(x,info)helperReadSPData(x,info),'IncludeInfo',true);
transTest = transform(adsTest,@(x,info)helperReadSPData(x,info),'IncludeInfo',true);

Задайте пользовательский логарифмический слой спектрограммы

Когда любая обработка сигналов сделана вне сети как предварительно обрабатывающие шаги, существует больший шанс, что сетевые предсказания сделаны с различными настройками предварительной обработки, чем используемые в сетевом обучении. Это может оказать значительное влияние на производительность сети, обычно ведущую к более плохой эффективности, чем ожидалось. При размещении спектрограммы или любых других расчетов предварительной обработки в сети, когда слой дает вам автономную модель и упрощает конвейер для развертывания. Это позволяет вам эффективно обучать, развертывать, или совместно использовать свою сеть со всеми необходимыми включенными операциями обработки сигналов. В этом примере главная операция обработки сигналов является расчетом спектрограммы. Способность вычислить спектрограмму в сети полезна и для вывода и для когда пространство памяти устройства недостаточно, чтобы сохранить спектрограммы. Вычисление спектрограммы в сети только требует выделения достаточной памяти для текущего пакета спектрограмм. Однако нужно отметить, что это не оптимальный выбор в терминах учебной скорости. Если у вас есть достаточная память, учебное время значительно уменьшается путем предварительного вычисления всех спектрограмм и хранения тех результатов. Затем чтобы обучить сеть, считайте спектрограмму "изображения" из устройства хранения данных вместо необработанного аудио и введите спектрограммы непосредственно в сети. Обратите внимание на то, что, в то время как это заканчивается в самое быстрое учебное время, способность выполнить обработку сигналов в сети все еще имеет значительные преимущества по причинам, ранее процитированным.

В обучении глубоких сетей часто выгодно использовать логарифм представления сигнала, потому что логарифм действует как компрессор динамического диапазона, повышая значения представления, которые имеют маленькие величины (амплитуды), но все еще несут важную информацию. В этом примере логарифмическая спектрограмма выполняет лучше, чем спектрограмма. Соответственно, этот пример создает пользовательский логарифмический слой спектрограммы и вставляет его в сеть после входного слоя. Относитесь, чтобы Задать Пользовательские Слои Глубокого обучения (Deep Learning Toolbox) для получения дополнительной информации о том, как создать пользовательский слой.

Объявите параметры и создайте функцию конструктора

logSpectrogramLayer слой без настраиваемых параметров, поэтому только non-learnable свойства необходимы. Здесь единственные необходимые свойства - необходимые для расчета спектрограммы. Объявите их в properties раздел. В predict слоя функция, dlarray- поддерживаемое кратковременное преобразование Фурье функционирует dlstft используется для расчета спектрограмма. Для получения дополнительной информации о dlstft и эти параметры, обратитесь к dlstft документация. Создайте функцию, которая создает слой и инициализирует свойства слоя. Задайте любые переменные, требуемые создать слой как входные параметры к функции конструктора.

classdef logSpectrogramLayer < nnet.layer.Layer    
    properties
        % (Optional) Layer properties.
        % Spectral window
        Window
        % Number of overlapped smaples
        OverlapLength
        % Number of DFT points
        FFTLength
        % Signal Length
        SignalLength
    end

    method
        function layer = logSpectrogramLayer(sigLength,NVargs)
            arguments
                sigLength {mustBeNumeric}
                NVargs.Window {mustBeFloat,mustBeNonempty,mustBeFinite,mustBeReal,mustBeVector}= hann(128,'periodic')
                NVargs.OverlapLength {mustBeNumeric} = 96
                NVargs.FFTLength {mustBeNumeric} = 128
                NVargs.Name string = "logspec"
            end
            layer.Type = 'logSpectrogram';
            layer.Name =  NVargs.Name;
            layer.SignalLength = sigLength;
            layer.Window = NVargs.Window;
            layer.OverlapLength = NVargs.OverlapLength;
            layer.FFTLength = NVargs.FFTLength;
        end

        ...
     end

Предскажите функцию

Как ранее упомянуто, пользовательский слой использует dlstft получить STFT и затем вычисляет логарифм величины в квадрате STFT, чтобы получить логарифмические спектрограммы. Можно также удалить log функционируйте, если вы желаете или добавляете какую-либо другую dlarray-поддерживаемую функцию, чтобы настроить выход. Можно скопировать logSpectrogramLayer.m к различной папке, если вы хотите экспериментировать с различными выходными параметрами от предсказать функции. Рекомендуется сохранить пользовательский слой под другим именем, чтобы предотвратить любые конфликты с версией, используемой в этом примере.

        function Z = predict(layer, X)
            % Forward input data through the layer at prediction time and
            % output the result.
            %
            % Inputs:
            %         layer - Layer to forward propagate through
            %         X     - Input data, specified as a 1-by-1-by-C-by-N 
            %                 dlarray, where N is the mini-batch size.
            % Outputs:
            %         Z     - Output of layer forward function returned as 
            %                 an sz(1)-by-sz(2)-by-sz(3)-by-N dlarray,
            %                 where sz is the layer output size and N is
            %                 the mini-batch size.
            
            % Use dlstft to compute short-time Fourier transform.
            % Specify the data format as SSCB to match the output of 
            % imageInputLayer.            
         
            X = squeeze(X);                      
            [YR,YI] = dlstft(X,'Window',layer.Window,...
                'FFTLength',layer.FFTLength,'OverlapLength',layer.OverlapLength,...
                'DataFormat','TBC');
            
            % This code is needed to handle the fact that 2D convolutional
            % DAG networks expect SSCB
            YR = permute(YR,[1 4 2 3]);
            YI = permute(YI,[1 4 2 3]);
            
            
            % Take the logarithmic squared magnitude of short-time Fourier
            % transform.
            Z = log(YR.^2 + YI.^2);

        end

Поскольку logSpectrogramLayer использует ту же прямую передачу для обучения и предсказания (вывод), только predict функция необходима и никакой forward функция требуется. Кроме того, потому что predict функционируйте использует dlstft, который поддерживает dlarray, дифференцирование в обратном распространении может быть сделано автоматически. Это означает, что вы не должны писать backward функция. Это - значительное преимущество в письменной форме пользовательский слой, который поддерживает dlarray. Для списка функций та поддержка dlarray объекты, см. Список Функций с Поддержкой dlarray (Deep Learning Toolbox).

Архитектура Глубокой сверточной нейронной сети (DCNN)

Можно использовать пользовательский слой таким же образом в качестве любого другого слоя в Deep Learning Toolbox. Создайте маленький DCNN как массив слоя, который включает пользовательский слой logSpectrogramLayer. Используйте сверточный и слои нормализации партии. и проредите карты функции с помощью макс. слоев объединения. Чтобы принять меры против сверхподбора кривой, добавьте небольшое количество уволенного к входу последнего полносвязного слоя.

sigLength = 8192;
dropoutProb = 0.2;
numF = 12;
layers = [
    imageInputLayer([sigLength 1])
    
    logSpectrogramLayer(sigLength,'Window',hamming(1280),'FFTLength',1280,...
        'OverlapLength',900)
    
    convolution2dLayer(5,numF,'Padding','same')
    batchNormalizationLayer
    reluLayer

    maxPooling2dLayer(3,'Stride',2,'Padding','same')

    convolution2dLayer(3,2*numF,'Padding','same')
    batchNormalizationLayer
    reluLayer

    maxPooling2dLayer(3,'Stride',2,'Padding','same')

    convolution2dLayer(3,4*numF,'Padding','same')
    batchNormalizationLayer
    reluLayer

    maxPooling2dLayer(3,'Stride',2,'Padding','same')

    convolution2dLayer(3,4*numF,'Padding','same')
    batchNormalizationLayer
    reluLayer
    convolution2dLayer(3,4*numF,'Padding','same')
    batchNormalizationLayer
    reluLayer

    maxPooling2dLayer(2)

    dropoutLayer(dropoutProb)
    fullyConnectedLayer(numel(categories(ads.Labels)))
    softmaxLayer
    classificationLayer('Classes',categories(ads.Labels));
    ];

Установите гиперпараметры использовать в обучении сети. Используйте мини-пакетный размер 50 и скорость обучения 1e-4. Задайте оптимизацию Адама. Установите UsePrefetch к true позволять асинхронной упреждающей выборке и постановке в очередь данных оптимизировать производительность обучения. Фоновая диспетчеризация данных и использование графического процессора, чтобы обучить сеть требуют Parallel Computing Toolbox™.

UsePrefetch = true;
опции = trainingOptions ('adam', ...
    'InitialLearnRate', 1e-4, ...
    'MaxEpochs',30, ...
    'MiniBatchSize',50, ...
    'Shuffle','every-epoch', ...
    'DispatchInBackground', UsePrefetch,...
    'Plots','training-progress',...
    "Verbose"ложь;

Обучите сеть.

[trainedNet,trainInfo] = trainNetwork(transTrain,layers,options);

Используйте обучивший сеть, чтобы предсказать метки цифры для набора тестов. Вычислите точность предсказания.

[YPred,probs] = classify(trainedNet,transTest);
cnnAccuracy = sum(YPred==adsTest.Labels)/numel(YPred)*100
cnnAccuracy = 97

Обобщите эффективность обучившего сеть на наборе тестов с графиком беспорядка. Отобразите точность и отзыв для каждого класса при помощи сводных данных строки и столбца. Таблица в нижней части графика беспорядка показывает значения точности. Таблица справа от графика беспорядка показывает значения отзыва.

figure('Units','normalized','Position',[0.2 0.2 0.5 0.5]);
ccDCNN = confusionchart(adsTest.Labels,YPred);
ccDCNN.Title = 'Confusion Chart for DCNN';
ccDCNN.ColumnSummary = 'column-normalized';
ccDCNN.RowSummary = 'row-normalized';

Сводные данные

Этот пример показал, как создать пользовательский слой спектрограммы с помощью dlstft. Используя функциональность, которая поддерживает dlarray, пример продемонстрировал, как встроить операции обработки сигналов в сети способом, которая поддерживает обратную связь и использование графических процессоров.

Приложение: Функции помощника

function Labels = helpergenLabels(ads)
% This function is only for use in the "Spoken Digit Recognition with
% Custom Log Spectrogram Layer and Deep Learning" example. It may change or
% be removed in a future release.

tmp = cell(numel(ads.Files),1);
expression = "[0-9]+_";
for nf = 1:numel(ads.Files)
    idx = regexp(ads.Files{nf},expression);
    tmp{nf} = ads.Files{nf}(idx);
end
Labels = categorical(tmp);
end
function [out,info] = helperReadSPData(x,info)
% This function is only for use in the "Spoken Digit Recognition with
% Custom Log Spectrogram Layer and Deep Learning" example. It may change or
% be removed in a future release.

N = numel(x);
if N > 8192
    x = x(1:8192);
elseif N < 8192
    pad = 8192-N;
    prepad = floor(pad/2);
    postpad = ceil(pad/2);
    x = [zeros(prepad,1) ; x ; zeros(postpad,1)];
end
x = x./max(abs(x));
out = {x./max(abs(x)),info.Label};
end