Определение ключевых слов в генерации кода шума с Intel MKL-DNN

Этот пример демонстрирует генерацию кода для определения ключевых слов с помощью сети 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).

Предварительно обученная сеть определение ключевых слов с помощью MATLAB и Передачи потокового аудио из микрофона

Частота дискретизации предварительно обученной сети 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, чтобы измерить время расчета для рабочего процесса.

Создайте объект строения генерации кода, чтобы сгенерировать 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