Этот пример демонстрирует генерацию кода для определения ключевых слов с помощью сети Bidirectional Long Short-Term Memory (BiLSTM) и редукции данных mel frequency cepstral (MFCC). MATLAB ® Coder™ с поддержкой глубокого обучения позволяет создавать автономный исполняемый файл (.exe). Связь между файлом MATLAB ® (.mlx) и сгенерированным исполняемым файлом происходит по асинхронному протоколу UDP. Входящий речевой сигнал отображается с помощью timescope
. Маска отображается в виде синего прямоугольника, окружающего пятнистые образцы ключевого слова YES. Для получения дополнительной информации о редукции данных MFCC и нейронной сети для глубокого обучения обучении, посетите Keyword Spotting in Noise Using MFCC и LSTM Networks.
MATLAB ® Coder для пакета поддержки глубокого обучения
Процессор Intel Xeon с поддержкой Intel Advanced Vector Extensions 2 (Intel AVX2)
Intel Math Kernel Library для глубоких нейронных сетей (MKL-DNN)
Переменные окружения для Intel MKL-DNN
Для поддерживаемых версий библиотек и для получения информации о настройке переменных окружения смотрите Необходимые условия для глубокого обучения с MATLAB Coder (MATLAB Coder).
Частота дискретизации предварительно обученной сети 16
кГц. Установите длину окна равной 512
выборки, с длиной перекрытия 384
выборки и длина скачка, заданная как различие между длиной окна и перекрытия. Задайте скорость оценки маски. Маска генерируется один раз для каждого numHopsPerUpdate
аудио систем координат.
fs = 16e3; windowLength = 512; overlapLength = 384; hopLength = windowLength - overlapLength; numHopsPerUpdate = 16; maskLength = hopLength*numHopsPerUpdate;
Создайте audioFeatureExtractor
объект для выполнения редукции данных MFCC.
afe = audioFeatureExtractor('SampleRate',fs, ... 'Window',hann(windowLength,'periodic'), ... 'OverlapLength',overlapLength, ... 'mfcc',true, ... 'mfccDelta',true, ... 'mfccDeltaDelta',true);
Загрузите и загрузите предварительно обученную сеть, а также среднее (M
) и стандартное отклонение (S
) векторы, используемые для стандартизации функций.
url = 'http://ssd.mathworks.com/supportfiles/audio/KeywordSpotting.zip'; downloadNetFolder = './'; netFolder = fullfile(downloadNetFolder,'KeywordSpotting'); if ~exist(netFolder,'dir') disp('Downloading pretrained network and audio files (4 files - 7 MB) ...') unzip(url,downloadNetFolder) end load(fullfile(netFolder,'KWSNet.mat'),"KWSNet","M","S");
Функции generateMATLABFunction
на audioFeatureExtractor
объект, чтобы создать функцию редукции данных. Вы будете использовать эту функцию в цикле обработки.
generateMATLABFunction(afe,'generateKeywordFeatures','IsStreaming',true);
Задайте средство чтения Аудио устройства, которое может считывать аудио с микрофона. Установите длину системы координат равной длине скачка. Это позволяет вам вычислять новый набор функций для каждого нового аудио системы координат из микрофона.
frameLength = hopLength; adr = audioDeviceReader('SampleRate',fs, ... 'SamplesPerFrame',frameLength);
Создайте Time Scope, чтобы визуализировать речевые сигналы и предполагаемую маску.
scope = timescope('SampleRate',fs, ... 'TimeSpanSource','property', ... 'TimeSpan',5, ... 'TimeSpanOverrunAction','Scroll', ... 'BufferLength',fs*5*2, ... 'ShowLegend',true, ... 'ChannelNames',{'Speech','Keyword Mask'}, ... 'YLimits',[-1.2 1.2], ... 'Title','Keyword Spotting');
Инициализируйте буфер для аудио данных, буфер для вычисляемых функций и буфер для построения графика входа аудио и выхода маски речи.
dataBuff = dsp.AsyncBuffer(windowLength); featureBuff = dsp.AsyncBuffer(numHopsPerUpdate); plotBuff = dsp.AsyncBuffer(numHopsPerUpdate*windowLength);
Выполните определение ключевого слова на речи, полученной от микрофона. Чтобы запустить цикл бесконечно, установите timeLimit
на Inf
. Чтобы остановить симуляцию, закройте scope
.
timeLimit = 20; show(scope); tic while toc < timeLimit && isVisible(scope) data = adr(); write(dataBuff,data); write(plotBuff,data); frame = read(dataBuff,windowLength,overlapLength); features = generateKeywordFeatures(frame,fs); write(featureBuff,features.'); if featureBuff.NumUnreadSamples == numHopsPerUpdate featureMatrix = read(featureBuff); featureMatrix(~isfinite(featureMatrix)) = 0; featureMatrix = (featureMatrix - M)./S; [keywordNet, v] = classifyAndUpdateState(KWSNet,featureMatrix.'); v = double(v) - 1; v = repmat(v,hopLength,1); v = v(:); v = mode(v); predictedMask = repmat(v,numHopsPerUpdate*hopLength,1); data = read(plotBuff); scope([data,predictedMask]); drawnow limitrate; end end release(adr) hide(scope)
The helperKeywordSpotting
вспомогательная функция инкапсулирует процесс захвата аудио, редукции данных и сетевого предсказания, продемонстрированный ранее. Чтобы сделать редукцию данных совместимой с генерацией кода, редукция данных обрабатывается сгенерированным generateKeywordFeatures
функция. Чтобы сделать сеть совместимой с генерацией кода, вспомогательная функция использует coder.loadDeepLearningNetwork
(MATLAB Coder) (MATLAB ® Coder) для загрузки сети.
Вспомогательная функция использует dsp.UDPSender
Системный объект для отправки входных данных вместе с выходом, предсказанной сетью, в MATLAB ®. Скрипт MATLAB ® использует dsp.UDPReceiver
Системный объект для приема входных данных вместе с выходной маской, предсказанной сетью, выполняемой в поддерживающей функции.
Создайте объект строения генерации кода, чтобы сгенерировать исполняемый файл. Задайте целевой язык как C++.
cfg = coder.config('exe'); cfg.TargetLang = 'C++';
Создайте объект строения для генерации кода глубокого обучения с библиотекой MKL-DNN. Присоедините объект строения глубокого обучения к объекту строения генерации кода.
dlcfg = coder.DeepLearningConfig('mkldnn');
cfg.DeepLearningConfig = dlcfg;
Сгенерируйте основной файл C++, необходимый для создания независимого исполняемого файла.
cfg.GenerateExampleMain = 'GenerateCodeAndCompile';
Сгенерируйте helperKeywordSpotting
, вспомогательную функцию, которая инкапсулирует процессы захвата, редукции данных и сетевого предсказания.
codegen helperKeywordSpotting -config cfg -report
Warning: C++ Compiler produced warnings. See the build log for further details. Code generation successful (with warnings): View report
В этом разделе вы генерируете все необходимые файлы зависимостей и помещаете их в одну папку. В процессе сборки MATLAB ® Coder генерирует buildInfo.mat
, файл, который содержит информацию о зависимостях компиляции и времени выполнения для независимого исполняемого файла.
Установите имя проекта равным helperKeywordSpotting
.
projName = 'helperKeywordSpotting'; packageName = [projName,'Package']; if ispc exeName = [projName,'.exe']; else exeName = projName; end
Загрузка buildinfo.mat
и использовать packNGo
(MATLAB Coder) для создания .zip
пакет.
load(['codegen',filesep,'exe',filesep,projName,filesep,'buildInfo.mat']); packNGo(buildInfo,'fileName',[packageName,'.zip'],'minimalHeaders',false);
Разархивируйте пакет и поместите исполняемый файл в разархивированную директорию.
unzip([packageName,'.zip'],packageName); copyfile(exeName, packageName,'f');
Чтобы вызвать независимый исполняемый файл, которая зависит от библиотеки динамических ссылок MKL-DNN, добавьте путь к расположению библиотеки MKL-DNN к переменному окружению PATH
.
setenv('PATH',[getenv('INTEL_MKLDNN'),filesep,'lib',pathsep,getenv('PATH')]);
Запустите сгенерированный исполняемый файл.
if ispc system(['start cmd /k "title ',packageName,' && cd ',packageName,' && ',exeName]); else cd(packageName); system(['./',exeName,' &']); cd ..; end
Создайте dsp.UDPReceiver
Системный объект для приема речевых данных и предсказанной речевой маски от независимого исполняемого файла. Каждый пакет UDP, полученный от исполняемого файла, состоит из maskLength
замаскировать выборки и речевые выборки. Максимальная длина сообщения для dsp.UDPReceiver
объект 65507
байты. Вычислите buffer size, чтобы вместить максимальное количество пакетов UDP.
sizeOfFloatInBytes = 4; speechDataLength = maskLength; numElementsPerUDPPacket = maskLength + speechDataLength; maxUDPMessageLength = floor(65507/sizeOfFloatInBytes); samplesPerPacket = 1 + numElementsPerUDPPacket; numPackets = floor(maxUDPMessageLength/samplesPerPacket); bufferSize = numPackets*samplesPerPacket*sizeOfFloatInBytes; UDPReceive = dsp.UDPReceiver('LocalIPPort',20000, ... 'MessageDataType','single', ... 'MaximumMessageLength',samplesPerPacket, ... 'ReceiveBufferSize',bufferSize);
Чтобы запустить ключевое слово spotting бессрочно, установите timelimit
на Inf
. Чтобы остановить симуляцию, закройте scope
.
tic; timelimit = 20; show(scope); while toc < timelimit && isVisible(scope) data = UDPReceive(); if ~isempty(data) plotMask = data(1:maskLength); plotAudio = data(maskLength+1 : maskLength+speechDataLength); scope([plotAudio,plotMask]); end drawnow limitrate; end hide(scope);
Отпустите системные объекты и отключите независимый исполняемый файл.
release(UDPReceive); release(scope); if ispc system(['taskkill /F /FI "WindowTitle eq ',projName,'* " /T']); else system(['killall ',exeName]); end
SUCCESS: The process with PID 22904 (child process of PID 4956) has been terminated. SUCCESS: The process with PID 11260 (child process of PID 4956) has been terminated. SUCCESS: The process with PID 4956 (child process of PID 12964) has been terminated.
Аналогичный рабочий процесс включает использование файла MEX вместо независимого исполняемого файла. Выполните профилирование MEX, чтобы измерить время расчета для рабочего процесса.
Создайте объект строения генерации кода, чтобы сгенерировать MEX-функцию. Задайте целевой язык как C++.
cfg = coder.config('mex'); cfg.TargetLang = 'C++';
Создайте объект строения для генерации кода глубокого обучения с библиотекой MKL-DNN. Присоедините объект строения глубокого обучения к объекту строения генерации кода.
dlcfg = coder.DeepLearningConfig('mkldnn');
cfg.DeepLearningConfig = dlcfg;
Вызовите codegen, чтобы сгенерировать MEX-функцию для profileKeywordSpotting
.
inputAudioFrame = ones(hopLength,1,'single'); codegen profileKeywordSpotting -config cfg -args {inputAudioFrame} -report
Code generation successful: View report
Измерьте время выполнения кода MATLAB ®.
x = pinknoise(hopLength,1,'single'); numPredictCalls = 100; totalNumCalls = numPredictCalls*numHopsPerUpdate; exeTimeStart = tic; for call = 1:totalNumCalls [outputMask,inputData,plotFlag] = profileKeywordSpotting(x); end exeTime = toc(exeTimeStart); fprintf('MATLAB execution time per %d ms of audio = %0.4f ms\n',int32(1000*numHopsPerUpdate*hopLength/fs),(exeTime/numPredictCalls)*1000);
MATLAB execution time per 128 ms of audio = 22.4670 ms
Измерьте время выполнения MEX-функции.
exeTimeMexStart = tic; for call = 1:totalNumCalls [outputMask,inputData,plotFlag] = profileKeywordSpotting_mex(x); end exeTimeMex = toc(exeTimeMexStart); fprintf('MEX execution time per %d ms of audio = %0.4f ms\n',int32(1000*numHopsPerUpdate*hopLength/fs),(exeTimeMex/numPredictCalls)*1000);
MEX execution time per 128 ms of audio = 6.3982 ms
Сравните общее время выполнения независимого исполняемого файла подхода с MEX-функцией подходом. Этот тест эффективности выполняется на компьютере с использованием графического процессора NVIDIA Quadro P620 (версия 26) и процессора Intel (R) Xeon (R) W-2133 с тактовой частотой 3,60 ГГц.
PerformanceGain = exeTime/exeTimeMex
PerformanceGain = 3.5115