Этот пример показывает, как обучить модель глубокого обучения, которая обнаруживает наличие речевых команд в аудио. Пример использует набор данных речевых команд [1], чтобы обучить сверточную нейронную сеть распознавать данный набор команд.
Чтобы обучить сеть с нуля, необходимо сначала загрузить набор данных. Если вы не хотите загружать набор данных или обучать сеть, то можно загрузить предварительно обученную сеть, предоставленную этим примером, и выполнить следующие два раздела примера: Распознавать команды с предварительно обученной сетью и Обнаруживать команды с использованием передачи потокового аудио из микрофона.
Прежде чем подробно войти в процесс обучения, вы будете использовать предварительно обученную сеть распознавания речи для идентификации речевых команд.
Загрузите предварительно обученную сеть.
load('commandNet.mat')
Сеть обучена распознавать следующие речевые команды:
«да»
«нет»
вверх
«вниз»
«слева»
правильно
«on»
«off»
Стоп
«перейти»
Загрузите короткий речевой сигнал, где человек говорит «стоп».
[x,fs] = audioread('stop_command.flac');
Послушайте команду.
sound(x,fs)
Предварительно обученная сеть принимает спектрограммы на основе слуха в качестве входов. Сначала вы преобразуете форму речевого сигнала в спектрограмму на основе слуха.
Используйте функцию extractAuditoryFeature для вычисления слуховой спектрограммы. Подробные сведения о редукции данных будут рассмотрены позже в примере.
auditorySpect = helperExtractAuditoryFeatures(x,fs);
Классифицируйте команду на основе ее слуховой спектрограммы.
command = classify(trainedNet,auditorySpect)
command =
categorical
stop
Сеть обучена классифицировать слова, не принадлежащие этому набору, как «неизвестные».
Теперь вы классифицируете слово («play»), которое не было включено в список команд для идентификации.
Загрузите речевой сигнал и прослушайте его.
x = audioread('play_command.flac');
sound(x,fs)
Вычислите слуховую спектрограмму.
auditorySpect = helperExtractAuditoryFeatures(x,fs);
Классифицируйте сигнал.
command = classify(trainedNet,auditorySpect)
command =
categorical
unknown
Сеть обучена классифицировать фоновый шум как «фон».
Создайте сигнал на одну секунду, состоящий из случайного шума.
x = pinknoise(16e3);
Вычислите слуховую спектрограмму.
auditorySpect = helperExtractAuditoryFeatures(x,fs);
Классифицируйте фоновый шум.
command = classify(trainedNet,auditorySpect)
command =
categorical
background
Протестируйте предварительно обученную сеть обнаружения команд на передаче потокового аудио с микрофона. Попробуйте сказать одну из команд, например, да, нет, или остановить. Затем попробуйте сказать одно из неизвестных слов, таких как Марвин, Шейла, кровать, дом, кошка, птица или любое число от нуля до девяти.
Укажите частоту классификации в Гц и создайте аудио устройство считыватель, который может считать аудио с вашего микрофона.
classificationRate = 20; adr = audioDeviceReader('SampleRate',fs,'SamplesPerFrame',floor(fs/classificationRate));
Инициализируйте буфер для аудио. Извлеките классификационные метки сети. Инициализируйте буферы в полсекунды для меток и классификационных вероятностей передачи потокового аудио. Используйте эти буферы, чтобы сравнить результаты классификации за более длительный период времени и по этому сборке 'agreement' over когда команда обнаружена. Задайте пороги для логики принятия решений.
audioBuffer = dsp.AsyncBuffer(fs);
labels = trainedNet.Layers(end).Classes;
YBuffer(1:classificationRate/2) = categorical("background");
probBuffer = zeros([numel(labels),classificationRate/2]);
countThreshold = ceil(classificationRate*0.2);
probThreshold = 0.7;
Создайте рисунок и обнаружите команды, пока существует созданный рисунок. Чтобы запустить цикл бесконечно, установите timeLimit на Inf. Чтобы остановить живое обнаружение, просто закройте рисунок.
h = figure('Units','normalized','Position',[0.2 0.1 0.6 0.8]); timeLimit = 20; tic while ishandle(h) && toc < timeLimit % Extract audio samples from the audio device and add the samples to % the buffer. x = adr(); write(audioBuffer,x); y = read(audioBuffer,fs,fs-adr.SamplesPerFrame); spec = helperExtractAuditoryFeatures(y,fs); % Classify the current spectrogram, save the label to the label buffer, % and save the predicted probabilities to the probability buffer. [YPredicted,probs] = classify(trainedNet,spec,'ExecutionEnvironment','cpu'); YBuffer = [YBuffer(2:end),YPredicted]; probBuffer = [probBuffer(:,2:end),probs(:)]; % Plot the current waveform and spectrogram. subplot(2,1,1) plot(y) axis tight ylim([-1,1]) subplot(2,1,2) pcolor(spec') caxis([-4 2.6445]) shading flat % Now do the actual command detection by performing a very simple % thresholding operation. Declare a detection and display it in the % figure title if all of the following hold: 1) The most common label % is not background. 2) At least countThreshold of the latest frame % labels agree. 3) The maximum probability of the predicted label is at % least probThreshold. Otherwise, do not declare a detection. [YMode,count] = mode(YBuffer); maxProb = max(probBuffer(labels == YMode,:)); subplot(2,1,1) if YMode == "background" || count < countThreshold || maxProb < probThreshold title(" ") else title(string(YMode),'FontSize',20) end drawnow end


Этот пример использует набор данных Google Speech Commands Dataset [1]. Загрузите набор данных и распакуйте загруженный файл. Установите PathToDatabase в местоположение данных.
url = 'https://ssd.mathworks.com/supportfiles/audio/google_speech.zip'; downloadFolder = tempdir; dataFolder = fullfile(downloadFolder,'google_speech'); if ~exist(dataFolder,'dir') disp('Downloading data set (1.4 GB) ...') unzip(url,downloadFolder) end
Создайте audioDatastore (Audio Toolbox), который указывает на обучающий набор данных.
ads = audioDatastore(fullfile(dataFolder, 'train'), ... 'IncludeSubfolders',true, ... 'FileExtensions','.wav', ... 'LabelSource','foldernames')
ads =
audioDatastore with properties:
Files: {
' ...\AppData\Local\Temp\google_speech\train\bed\00176480_nohash_0.wav';
' ...\AppData\Local\Temp\google_speech\train\bed\004ae714_nohash_0.wav';
' ...\AppData\Local\Temp\google_speech\train\bed\004ae714_nohash_1.wav'
... and 51085 more
}
Folders: {
'C:\Users\jibrahim\AppData\Local\Temp\google_speech\train'
}
Labels: [bed; bed; bed ... and 51085 more categorical]
AlternateFileSystemRoots: {}
OutputDataType: 'double'
SupportedOutputFormats: ["wav" "flac" "ogg" "mp4" "m4a"]
DefaultOutputFormat: "wav"
Задайте слова, которые вы хотите, чтобы ваша модель распознавала как команды. Пометьте все слова, которые не являются командами, как unknown. Маркировка слов, которые не являются командами, как unknown создает группу слов, которая аппроксимирует распределение всех слов, кроме команд. Сеть использует эту группу, чтобы узнать различие между командами и всеми другими словами.
Чтобы уменьшить классовый дисбаланс между известными и неизвестными словами и ускорить обработку, включите только часть неизвестных слов в набор обучающих данных.
Использование subset (Audio Toolbox), чтобы создать datastore, которое содержит только команды и подмножество неизвестных слов. Подсчитайте количество примеров, принадлежащих каждой категории.
commands = categorical(["yes","no","up","down","left","right","on","off","stop","go"]); isCommand = ismember(ads.Labels,commands); isUnknown = ~isCommand; includeFraction = 0.2; mask = rand(numel(ads.Labels),1) < includeFraction; isUnknown = isUnknown & mask; ads.Labels(isUnknown) = categorical("unknown"); adsTrain = subset(ads,isCommand|isUnknown); countEachLabel(adsTrain)
ans =
11×2 table
Label Count
_______ _____
down 1842
go 1861
left 1839
no 1853
off 1839
on 1864
right 1852
stop 1885
unknown 6483
up 1843
yes 1860
Создайте audioDatastore (Audio Toolbox), который указывает на набор данных валидации. Выполните те же шаги, которые используются для создания обучающего datastore.
ads = audioDatastore(fullfile(dataFolder, 'validation'), ... 'IncludeSubfolders',true, ... 'FileExtensions','.wav', ... 'LabelSource','foldernames') isCommand = ismember(ads.Labels,commands); isUnknown = ~isCommand; includeFraction = 0.2; mask = rand(numel(ads.Labels),1) < includeFraction; isUnknown = isUnknown & mask; ads.Labels(isUnknown) = categorical("unknown"); adsValidation = subset(ads,isCommand|isUnknown); countEachLabel(adsValidation)
ads =
audioDatastore with properties:
Files: {
' ...\AppData\Local\Temp\google_speech\validation\bed\026290a7_nohash_0.wav';
' ...\AppData\Local\Temp\google_speech\validation\bed\060cd039_nohash_0.wav';
' ...\AppData\Local\Temp\google_speech\validation\bed\060cd039_nohash_1.wav'
... and 6795 more
}
Folders: {
'C:\Users\jibrahim\AppData\Local\Temp\google_speech\validation'
}
Labels: [bed; bed; bed ... and 6795 more categorical]
AlternateFileSystemRoots: {}
OutputDataType: 'double'
SupportedOutputFormats: ["wav" "flac" "ogg" "mp4" "m4a"]
DefaultOutputFormat: "wav"
ans =
11×2 table
Label Count
_______ _____
down 264
go 260
left 247
no 270
off 256
on 257
right 256
stop 246
unknown 850
up 260
yes 261
Чтобы обучить сеть со набором данных в целом и достичь максимально возможной точности, установите reduceDataset на false. Чтобы запустить этот пример быстро, установите reduceDataset на true.
reduceDataset = false; if reduceDataset numUniqueLabels = numel(unique(adsTrain.Labels)); % Reduce the dataset by a factor of 20 adsTrain = splitEachLabel(adsTrain,round(numel(adsTrain.Files) / numUniqueLabels / 20)); adsValidation = splitEachLabel(adsValidation,round(numel(adsValidation.Files) / numUniqueLabels / 20)); end
Чтобы подготовить данные для эффективного обучения сверточной нейронной сети, преобразуйте формы речи в спектрограммы на основе слуха.
Задайте параметры редукции данных. segmentDuration - длительность каждого речевого клипа (в секундах). frameDuration - длительность каждой системы координат для вычисления спектра. hopDuration - временной шаг между каждым спектром. numBands количество фильтров в слуховой спектрограмме.
Создайте audioFeatureExtractor (Audio Toolbox) для выполнения редукции данных.
fs = 16e3; % Known sample rate of the data set. segmentDuration = 1; frameDuration = 0.025; hopDuration = 0.010; segmentSamples = round(segmentDuration*fs); frameSamples = round(frameDuration*fs); hopSamples = round(hopDuration*fs); overlapSamples = frameSamples - hopSamples; FFTLength = 512; numBands = 50; afe = audioFeatureExtractor( ... 'SampleRate',fs, ... 'FFTLength',FFTLength, ... 'Window',hann(frameSamples,'periodic'), ... 'OverlapLength',overlapSamples, ... 'barkSpectrum',true); setExtractorParams(afe,'barkSpectrum','NumBands',numBands,'WindowNormalization',false);
Считайте файл из набора данных. Настройка сверточной нейронной сети требует, чтобы вход был допустимым размером. Некоторые файлы в наборе данных имеют длину менее 1 секунды. Примените заполнение нуля к передней и задней частотам аудиосигнала так, чтобы он имел длину segmentSamples.
x = read(adsTrain); numSamples = size(x,1); numToPadFront = floor( (segmentSamples - numSamples)/2 ); numToPadBack = ceil( (segmentSamples - numSamples)/2 ); xPadded = [zeros(numToPadFront,1,'like',x);x;zeros(numToPadBack,1,'like',x)];
Чтобы извлечь аудио функции, вызовите extract. Выходные выходы - спектр Корка со временем между строками.
features = extract(afe,xPadded); [numHops,numFeatures] = size(features)
numHops =
98
numFeatures =
50
В этом примере вы постпроцессируете слуховую спектрограмму путем применения логарифма. Взятие журнала малых чисел может привести к ошибке округления.
Чтобы ускорить обработку, можно распределить редукцию данных между несколькими работниками с помощью parfor.
Во-первых, определите количество разделов для набора данных. Если у вас нет Parallel Computing Toolbox™, используйте один раздел.
if ~isempty(ver('parallel')) && ~reduceDataset pool = gcp; numPar = numpartitions(adsTrain,pool); else numPar = 1; end
Для каждого раздела считайте из datastore, обнулите сигнал и затем извлеките функции.
parfor ii = 1:numPar subds = partition(adsTrain,numPar,ii); XTrain = zeros(numHops,numBands,1,numel(subds.Files)); for idx = 1:numel(subds.Files) x = read(subds); xPadded = [zeros(floor((segmentSamples-size(x,1))/2),1);x;zeros(ceil((segmentSamples-size(x,1))/2),1)]; XTrain(:,:,:,idx) = extract(afe,xPadded); end XTrainC{ii} = XTrain; end
Преобразуйте выход в 4-мерный массив со слуховыми спектрограммами по четвертой размерности.
XTrain = cat(4,XTrainC{:});
[numHops,numBands,numChannels,numSpec] = size(XTrain)
numHops =
98
numBands =
50
numChannels =
1
numSpec =
25021
Масштабируйте функции по степени окна, а затем берите журнал. Чтобы получить данные с более плавным распределением, примите логарифм спектрограмм с помощью небольшого смещения.
epsil = 1e-6; XTrain = log10(XTrain + epsil);
Выполните шаги редукции данных, описанные выше, к набору валидации.
if ~isempty(ver('parallel')) pool = gcp; numPar = numpartitions(adsValidation,pool); else numPar = 1; end parfor ii = 1:numPar subds = partition(adsValidation,numPar,ii); XValidation = zeros(numHops,numBands,1,numel(subds.Files)); for idx = 1:numel(subds.Files) x = read(subds); xPadded = [zeros(floor((segmentSamples-size(x,1))/2),1);x;zeros(ceil((segmentSamples-size(x,1))/2),1)]; XValidation(:,:,:,idx) = extract(afe,xPadded); end XValidationC{ii} = XValidation; end XValidation = cat(4,XValidationC{:}); XValidation = log10(XValidation + epsil);
Изолируйте метки train и валидации. Удалите пустые категории.
YTrain = removecats(adsTrain.Labels); YValidation = removecats(adsValidation.Labels);
Постройте графики форм волны и слуховых спектрограмм нескольких обучающих выборок. Воспроизведение соответствующих аудиоклипов.
specMin = min(XTrain,[],'all'); specMax = max(XTrain,[],'all'); idx = randperm(numel(adsTrain.Files),3); figure('Units','normalized','Position',[0.2 0.2 0.6 0.6]); for i = 1:3 [x,fs] = audioread(adsTrain.Files{idx(i)}); subplot(2,3,i) plot(x) axis tight title(string(adsTrain.Labels(idx(i)))) subplot(2,3,i+3) spect = (XTrain(:,:,1,idx(i))'); pcolor(spect) caxis([specMin specMax]) shading flat sound(x,fs) pause(2) end

Сеть должна быть способна не только распознавать различные разговорные слова, но и обнаруживать, содержит ли вход тишину или фоновый шум.
Используйте аудио файлов в _background_ папку для создания выборок односекундных клипов фонового шума. Создайте равное количество фоновых клипов из каждого файла фонового шума. Можно также создать собственные записи фонового шума и добавить их в _background_ папку. Перед вычислением спектрограмм функция пересматривает каждый аудиоклип с фактором, выбранным из логарифмического распределения в области значений, заданной volumeRange.
adsBkg = audioDatastore(fullfile(dataFolder, 'background')) numBkgClips = 4000; if reduceDataset numBkgClips = numBkgClips/20; end volumeRange = log10([1e-4,1]); numBkgFiles = numel(adsBkg.Files); numClipsPerFile = histcounts(1:numBkgClips,linspace(1,numBkgClips,numBkgFiles+1)); Xbkg = zeros(size(XTrain,1),size(XTrain,2),1,numBkgClips,'single'); bkgAll = readall(adsBkg); ind = 1; for count = 1:numBkgFiles bkg = bkgAll{count}; idxStart = randi(numel(bkg)-fs,numClipsPerFile(count),1); idxEnd = idxStart+fs-1; gain = 10.^((volumeRange(2)-volumeRange(1))*rand(numClipsPerFile(count),1) + volumeRange(1)); for j = 1:numClipsPerFile(count) x = bkg(idxStart(j):idxEnd(j))*gain(j); x = max(min(x,1),-1); Xbkg(:,:,:,ind) = extract(afe,x); if mod(ind,1000)==0 disp("Processed " + string(ind) + " background clips out of " + string(numBkgClips)) end ind = ind + 1; end end Xbkg = log10(Xbkg + epsil);
adsBkg =
audioDatastore with properties:
Files: {
' ...\AppData\Local\Temp\google_speech\background\doing_the_dishes.wav';
' ...\AppData\Local\Temp\google_speech\background\dude_miaowing.wav';
' ...\AppData\Local\Temp\google_speech\background\exercise_bike.wav'
... and 3 more
}
Folders: {
'C:\Users\jibrahim\AppData\Local\Temp\google_speech\background'
}
AlternateFileSystemRoots: {}
OutputDataType: 'double'
Labels: {}
SupportedOutputFormats: ["wav" "flac" "ogg" "mp4" "m4a"]
DefaultOutputFormat: "wav"
Processed 1000 background clips out of 4000
Processed 2000 background clips out of 4000
Processed 3000 background clips out of 4000
Processed 4000 background clips out of 4000
Разделите спектрограммы фонового шума между наборами для обучения, валидации и тестирования. Потому что _background_noise_ папка содержит только около пяти с половиной минут фонового шума, фоновые выборки в различных наборах данных сильно коррелируют. Чтобы увеличить изменение фонового шума, можно создать собственные файлы фона и добавить их в папку. Чтобы повысить робастность сети до шума, можно также попробовать смешать фоновый шум в речевые файлы.
numTrainBkg = floor(0.85*numBkgClips); numValidationBkg = floor(0.15*numBkgClips); XTrain(:,:,:,end+1:end+numTrainBkg) = Xbkg(:,:,:,1:numTrainBkg); YTrain(end+1:end+numTrainBkg) = "background"; XValidation(:,:,:,end+1:end+numValidationBkg) = Xbkg(:,:,:,numTrainBkg+1:end); YValidation(end+1:end+numValidationBkg) = "background";
Постройте график распределения различных меток классов в наборах обучения и валидации.
figure('Units','normalized','Position',[0.2 0.2 0.5 0.5]) subplot(2,1,1) histogram(YTrain) title("Training Label Distribution") subplot(2,1,2) histogram(YValidation) title("Validation Label Distribution")

Создайте простую сетевую архитектуру как массив слоев. Используйте сверточные и пакетные слои нормализации и понижающее отображение карты признаков «пространственно» (то есть по времени и частоте) с помощью максимальных слоев объединения. Добавьте конечный слой максимального объединения, который объединяет входную карту функций глобально с течением времени. Это обеспечивает (приблизительную) инвариацию преобразования времени в вход спектрограммах, позволяя сети выполнять ту же классификацию независимо от точного положения речи во времени. Глобальное объединение также значительно уменьшает количество параметров в конечном полносвязном слое. Чтобы уменьшить возможность запоминания сетью специфических функций обучающих данных, добавьте небольшое количество отсева на вход к последнему полностью подключенному слою.
Сеть небольшая, так как она имеет всего пять сверточных слоев с небольшим количеством фильтров. numF управляет количеством фильтров в сверточных слоях. Чтобы увеличить точность сети, попробуйте увеличить глубину сети, добавив одинаковые блоки сверточных, нормализации партии . и слоев ReLU. Можно также попробовать увеличить количество сверточных фильтров путем увеличения numF.
Используйте взвешенные потери классификации перекрестной энтропии. weightedClassificationLayer(classWeights) создает пользовательский слой классификации, который вычисляет потери перекрестной энтропии с наблюдениями, взвешенными по classWeights. Задайте веса классов в том же порядке, в котором появляются классы categories(YTrain). Чтобы задать каждому классу равный общий вес при потере, используйте веса классов, которые обратно пропорциональны количеству примеров обучения в каждом классе. При использовании оптимизатора Адама для обучения сети алгоритм настройки не зависит от общей нормализации весов классов.
classWeights = 1./countcats(YTrain);
classWeights = classWeights'/mean(classWeights);
numClasses = numel(categories(YTrain));
timePoolSize = ceil(numHops/8);
dropoutProb = 0.2;
numF = 12;
layers = [
imageInputLayer([numHops numBands])
convolution2dLayer(3,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([timePoolSize,1])
dropoutLayer(dropoutProb)
fullyConnectedLayer(numClasses)
softmaxLayer
weightedClassificationLayer(classWeights)];
Задайте опции обучения. Используйте оптимизатор Adam с мини-пакетом размером 128. Обучите 25 эпох и уменьшите скорость обучения в 10 раз после 20 эпох.
miniBatchSize = 128; validationFrequency = floor(numel(YTrain)/miniBatchSize); options = trainingOptions('adam', ... 'InitialLearnRate',3e-4, ... 'MaxEpochs',25, ... 'MiniBatchSize',miniBatchSize, ... 'Shuffle','every-epoch', ... 'Plots','training-progress', ... 'Verbose',false, ... 'ValidationData',{XValidation,YValidation}, ... 'ValidationFrequency',validationFrequency, ... 'LearnRateSchedule','piecewise', ... 'LearnRateDropFactor',0.1, ... 'LearnRateDropPeriod',20);
Обучите сеть. Если у вас нет графический процессор, то обучение сети может занять время.
trainedNet = trainNetwork(XTrain,YTrain,layers,options);

Вычислите окончательную точность сети на набор обучающих данных (без увеличения данных) и наборе валидации. Сеть очень точна на этом наборе данных. Однако обучение, валидация и тестовые данные все имеют аналогичные распределения, которые не обязательно отражают реальные окружения. Это ограничение особенно относится к unknown категория, которая содержит высказывания лишь небольшого числа слов.
if reduceDataset load('commandNet.mat','trainedNet'); end YValPred = classify(trainedNet,XValidation); validationError = mean(YValPred ~= YValidation); YTrainPred = classify(trainedNet,XTrain); trainError = mean(YTrainPred ~= YTrain); disp("Training error: " + trainError*100 + "%") disp("Validation error: " + validationError*100 + "%")
Training error: 1.907% Validation error: 5.5376%
Постройте график матрицы неточностей. Отображение точности и отзыва для каждого класса с помощью сводных данных по столбцам и строкам. Отсортируйте классы матрицы неточностей. Самая большая путаница между неизвестными словами и командами, вверх и назад, вниз и нет, и идти и нет.
figure('Units','normalized','Position',[0.2 0.2 0.5 0.5]); cm = confusionchart(YValidation,YValPred); cm.Title = 'Confusion Matrix for Validation Data'; cm.ColumnSummary = 'column-normalized'; cm.RowSummary = 'row-normalized'; sortClasses(cm, [commands,"unknown","background"])

При работе с приложениями с ограниченными аппаратными ресурсами, такими как мобильные приложения, учитывайте ограничения на доступную память и вычислительные ресурсы. Вычислите общий размер сети в килобайтах и протестируйте ее скорость предсказания при использовании центральный процессор. Время предсказания является временем для классификации одного входного изображения. Если вы вводите несколько изображений в сеть, они могут быть классифицированы одновременно, что приводит к более короткому времени предсказания на изображение. Однако при классификации передачи потокового аудио наиболее актуальным является время предсказания с одним изображением.
info = whos('trainedNet'); disp("Network size: " + info.bytes/1024 + " kB") for i = 1:100 x = randn([numHops,numBands]); tic [YPredicted,probs] = classify(trainedNet,x,"ExecutionEnvironment",'cpu'); time(i) = toc; end disp("Single-image prediction time on CPU: " + mean(time(11:end))*1000 + " ms")
Network size: 286.7402 kB Single-image prediction time on CPU: 2.5119 ms
[1] Warden P. «Speech Commands: A public dataset for single-word speech recognition», 2017. Доступно из https://storage.googleapis.com/download.tensorflow.org/data/speech_commands_v0.01.tar.gz. Копирайт Google 2017. Набор данных Speech Commands лицензирован по лицензии Creative Commons Attribution 4.0, доступной здесь: https://creativecommons.org/licenses/by/4.0/legalcode.
[1] Warden P. «Speech Commands: A public dataset for single-word speech recognition», 2017. Доступно из http://download.tensorflow.org/data/speech_commands_v0.01.tar.gz. Копирайт Google 2017. Набор данных Speech Commands лицензирован по лицензии Creative Commons Attribution 4.0, доступной здесь: https://creativecommons.org/licenses/by/4.0/legalcode.
analyzeNetwork | classify | trainNetwork