exponenta event banner

Ключевое слово Spotting in Noise Code Generation с помощью Intel MKL-DNN

В этом примере демонстрируется создание кода для определения ключевых слов с использованием сети двунаправленной долговременной памяти (BiLSTM) и извлечения функции частотного кепстрального коэффициента (MFCC). MATLAB ® Coder™ с поддержкой глубокого обучения позволяет создавать автономные исполняемые файлы (.exe). Связь между файлом MATLAB ® (.mlx) и созданным исполняемым файлом осуществляется по асинхронному протоколу пользовательских дейтаграмм (UDP). Входящий речевой сигнал отображается с помощью timescope. Маска отображается синим прямоугольником вокруг пятнистых экземпляров ключевого слова YES. Для получения более подробной информации об извлечении функций MFCC и обучении работе с сетью глубокого обучения посетите раздел Ключевые слова - определение шума с использованием сетей MFCC и LSTM.

Примерные требования

  • Интерфейс кодера MATLAB ® для пакета поддержки глубокого обучения

  • Процессор Intel Xeon с поддержкой Intel Advanced Vector Extensions 2 (Intel AVX2)

  • Библиотека Intel Math Kernel Library для глубоких нейронных сетей (MKL-DNN)

  • Переменные среды для Intel MKL-DNN

Поддерживаемые версии библиотек и сведения о настройке переменных среды см. в разделе Предварительные условия для глубокого обучения с помощью кодера MATLAB (MATLAB Coder).

Предварительно обученные сетевые ключевые слова Spotting с использованием 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);

Создайте временную область для визуализации речевых сигналов и оценочной маски.

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)

helperKeywordSpotting поддерживающая функция инкапсулирует процесс захвата звука, извлечения признаков и предсказания сети, продемонстрированный ранее. Для обеспечения совместимости извлечения признака с генерацией кода извлечение признака обрабатывается сгенерированным generateKeywordFeatures функция. Чтобы сделать сеть совместимой с генерацией кода, функция поддержки использует coder.loadDeepLearningNetwork (Кодер MATLAB) (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) для производства .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 байт. Вычислите размер буфера для размещения максимального количества пакетов 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;

Вызов кодегена для генерации функции 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