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

Этот пример демонстрирует генерацию кода для определения ключевого слова с помощью сети Bidirectional Long Short-Term Memory (BiLSTM) и извлечения признаков частоты mel cepstral коэффициента (MFCC). MATLAB® Coder™ с Поддержкой Глубокого обучения включает генерацию независимого исполняемого файла (.exe) файл. Связь между MATLAB® (.mlx) файл и сгенерированным исполняемым файлом происходит по асинхронному Пользовательскому дейтаграммному протоколу (UDP). Входящий речевой сигнал отображен с помощью timescope. Маска показывается синим прямоугольником, окружающим определенные экземпляры ключевого слова, YES. Для получения дополнительной информации об извлечении признаков MFCC и обучении нейронной сети для глубокого обучения, посетите Определение Ключевого слова в Шуме Используя MFCC и Сети LSTM.

Требования в качестве примера

  • MATLAB® Coder Interface для пакета поддержки глубокого обучения

  • Процессор Intel® Xeon® с поддержкой Intel Усовершенствованные Векторные Расширения 2 (Intel AVX2)

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

  • Переменные окружения для Intel MKL-DNN

Для поддерживаемых версий библиотек и для получения информации о подготовке переменных окружения, смотрите Необходимые условия для Глубокого обучения для MATLAB Coder (MATLAB Coder).

Определение ключевого слова предварительно обученной сети Используя MATLAB и передачу потокового аудио от микрофона

Частотой дискретизации предварительно обученной сети является 16 kHz. Установите длину окна на 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)

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

codegen helperKeywordSpotting -config cfg -report
Warning: Function 'helperKeywordSpotting' does not terminate due to an infinite loop.

Warning in ==> helperKeywordSpotting Line: 73 Column: 1
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);

Чтобы запустить ключевое слово, определяющее неопределенно, установите 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 4644 (child process of PID 21188) has been terminated. 
SUCCESS: The process with PID 20052 (child process of PID 21188) has been terminated. 
SUCCESS: The process with PID 21188 (child process of PID 22940) 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 = 24.9238 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 = 5.2710 ms

Сравните общее время выполнения подхода независимого исполняемого файла с подходом MEX-функции. Этот тест производительности сделан на машине с помощью NVIDIA Quadro® P620 (Версия 26) графический процессор и Xeon W-2133 CPU Intel, достигающий 3,60 ГГц.

PerformanceGain = exeTime/exeTimeMex
PerformanceGain = 4.7285