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