В этом примере показано, как развернуть извлечение признаков и сверточную нейронную сеть (CNN) для речевого распознавания команды к Raspberry Pi™. Чтобы сгенерировать извлечение признаков и сетевой код, вы используете MATLAB Coder, Пакет поддержки MATLAB для Оборудования Raspberry Pi и Библиотеку ARM® Compute. В этом примере сгенерированный код является исполняемым файлом на вашем Raspberry Pi, который вызван скриптом MATLAB, который отображает предсказанную речевую команду наряду с и слуховой спектрограммой сигнала. Взаимодействие между скриптом MATLAB и исполняемым файлом на вашем Raspberry Pi обработано с помощью пользовательского дейтаграммного протокола (UDP). Для получения дополнительной информации о предварительной обработке аудио и сетевом обучении, смотрите Распознание речевых команд с использованием глубокого обучения.
Процессор ARM, который поддерживает расширение NEON
ARM Вычисляет версию 19.05 Библиотеки (на целевом оборудовании ARM)
Переменные окружения для компиляторов и библиотек
Для поддерживаемых версий библиотек и для получения информации о подготовке переменных окружения, смотрите Необходимые условия для Глубокого обучения для MATLAB Coder (MATLAB Coder).
Используйте те же параметры для трубопровода извлечения признаков и классификации, как разработано в Распознании речевых команд с использованием глубокого обучения.
Задайте ту же частоту дискретизации, сеть была обучена на (16 кГц). Задайте уровень классификации и количество входа аудиосэмплов на систему координат. Вход функции к сети является спектрограммой Коры, которая соответствует 1 секунде аудиоданных. Спектрограмма Коры вычисляется для 25 MS Windows с транзитными участками на 10 мс. Вычислите количество отдельных спектров в каждой спектрограмме.
fs = 16000; classificationRate = 20; samplesPerCapture = fs/classificationRate; segmentDuration = 1; segmentSamples = round(segmentDuration*fs); frameDuration = 0.025; frameSamples = round(frameDuration*fs); hopDuration = 0.010; hopSamples = round(hopDuration*fs); numSpectrumPerSpectrogram = floor((segmentSamples-frameSamples)/hopSamples) + 1;
Создайте audioFeatureExtractor
возразите, чтобы извлечь спектрограммы Коры с 50 полосами без нормализации окна. Вычислите число элементов в каждой спектрограмме.
afe = audioFeatureExtractor( ... 'SampleRate',fs, ... 'FFTLength',512, ... 'Window',hann(frameSamples,'periodic'), ... 'OverlapLength',frameSamples - hopSamples, ... 'barkSpectrum',true); numBands = 50; setExtractorParams(afe,'barkSpectrum','NumBands',numBands,'WindowNormalization',false); numElementsPerSpectrogram = numSpectrumPerSpectrogram*numBands;
Загрузите предварительно обученный CNN и метки.
load('commandNet.mat') labels = trainedNet.Layers(end).Classes; NumLabels = numel(labels); BackGroundIdx = find(labels == 'background');
Задайте буферы и пороги решения, чтобы отправить предсказания сети процесса.
probBuffer = single(zeros([NumLabels,classificationRate/2])); YBuffer = single(NumLabels * ones(1, classificationRate/2)); countThreshold = ceil(classificationRate*0.2); probThreshold = single(0.7);
Создайте audioDeviceReader
возразите, чтобы считать аудио из вашего устройства. Создайте dsp.AsyncBuffer
возразите, чтобы буферизовать аудио во фрагменты.
adr = audioDeviceReader('SampleRate',fs,'SamplesPerFrame',samplesPerCapture,'OutputDataType','single'); audioBuffer = dsp.AsyncBuffer(fs);
Создайте dsp.MatrixViewer
возразите и timescope
объект отобразить результаты.
matrixViewer = dsp.MatrixViewer("ColorBarLabel","Power per band (dB/Band)",... "XLabel","Frames",... "YLabel","Bark Bands", ... "Position",[400 100 600 250], ... "ColorLimits",[-4 2.6445], ... "AxisOrigin","Lower left corner", ... "Name","Speech Command Recognition using Deep Learning"); timeScope = timescope("SampleRate",fs, ... "YLimits",[-1 1], ... "Position",[400 380 600 250], ... "Name","Speech Command Recognition Using Deep Learning", ... "TimeSpanSource","Property", ... "TimeSpan",1, ... "BufferLength",fs, ... "YLabel","Amplitude", ... "ShowGrid",true);
Покажите осциллограф времени и матричное средство просмотра. Обнаружьте команды, пока и осциллограф времени и матричное средство просмотра открыты или пока ограничение по времени не достигнуто. Чтобы остановить живое обнаружение перед, ограничение по времени достигнуто, закройте окно scope времени или матричное окно средства просмотра.
show(timeScope) show(matrixViewer) timeLimit = 10; tic while isVisible(timeScope) && isVisible(matrixViewer) && toc < timeLimit % Capture audio x = adr(); write(audioBuffer,x); y = read(audioBuffer,fs,fs-samplesPerCapture); % Compute auditory features features = extract(afe,y); auditoryFeatures = log10(features + 1e-6); % Perform prediction probs = predict(trainedNet, auditoryFeatures); [~, YPredicted] = max(probs); % Perform statistical post processing YBuffer = [YBuffer(2:end),YPredicted]; probBuffer = [probBuffer(:,2:end),probs(:)]; [YModeIdx, count] = mode(YBuffer); maxProb = max(probBuffer(YModeIdx,:)); if YModeIdx == single(BackGroundIdx) || single(count) < countThreshold || maxProb < probThreshold speechCommandIdx = BackGroundIdx; else speechCommandIdx = YModeIdx; end % Update plots matrixViewer(auditoryFeatures'); timeScope(x); if (speechCommandIdx == BackGroundIdx) timeScope.Title = ' '; else timeScope.Title = char(labels(speechCommandIdx)); end drawnow limitrate end
Скройте осциллографы.
hide(matrixViewer) hide(timeScope)
Чтобы создать функцию, чтобы выполнить извлечение признаков, совместимое с генерацией кода, вызовите generateMATLABFunction
на audioFeatureExtractor
объект. generateMATLABFunction
объектная функция создает автономную функцию, которая выполняет эквивалентное извлечение признаков и совместима с генерацией кода.
generateMATLABFunction(afe,'extractSpeechFeatures')
HelperSpeechCommandRecognitionRasPi
поддерживание функции инкапсулирует извлечение признаков и сетевой процесс предсказания, продемонстрированный ранее. Так, чтобы извлечение признаков было совместимо с генерацией кода, извлечение признаков обработано сгенерированным extractSpeechFeatures
функция. Так, чтобы сеть была совместима с генерацией кода, функция поддержки использует coder.loadDeepLearningNetwork
(MATLAB Coder) функция, чтобы загрузить сеть. Функция поддержки использует dsp.UDPReceiver
системный объект, чтобы отправить слуховую спектрограмму и индекс, соответствующий предсказанной речевой команде от Raspberry Pi до MATLAB. Функция поддержки использует dsp.UDPReceiver
системный объект, чтобы получить аудио, записанное вашим микрофоном в MATLAB.
Замените hostIPAddress
с адресом вашей машины. Ваш Raspberry Pi отправляет слуховые спектрограммы и предсказанную речевую команду к этому IP-адресу.
hostIPAddress = coder.Constant('172.18.230.30');
Создайте объект настройки генерации кода сгенерировать исполняемую программу. Задайте выходной язык как C++.
cfg = coder.config('exe'); cfg.TargetLang = 'C++';
Создайте объект настройки для генерации кода глубокого обучения с ARM, вычисляют библиотеку, которая находится на вашем Raspberry Pi. Задайте архитектуру Raspberry Pi и присоедините объект настройки глубокого обучения к объекту настройки генерации кода.
dlcfg = coder.DeepLearningConfig('arm-compute'); dlcfg.ArmArchitecture = 'armv7'; dlcfg.ArmComputeVersion = '19.05'; cfg.DeepLearningConfig = dlcfg;
Используйте функцию Пакета поддержки Raspberry Pi, raspi
, создать связь с вашим Raspberry Pi. В следующем коде, замене:
raspiname
с именем вашего Raspberry Pi
пи с вашим именем пользователя
password
с вашим паролем
r = raspi('raspiname','pi','password');
Создайте coder.hardware
Объект (MATLAB Coder) для Raspberry Pi и присоединения это к объекту настройки генерации кода.
hw = coder.hardware('Raspberry Pi');
cfg.Hardware = hw;
Задайте папку сборки на Raspberry Pi.
buildDir = '~/remoteBuildDir';
cfg.Hardware.BuildDir = buildDir;
Используйте автоматический сгенерированный C++ основной файл для генерации независимого исполняемого файла.
cfg.GenerateExampleMain = 'GenerateCodeAndCompile';
Вызовите codegen
(MATLAB Coder), чтобы сгенерировать Код С++ и исполняемый файл на вашем Raspberry Pi. По умолчанию имя приложения Raspberry Pi совпадает с функцией MATLAB.
codegen -config cfg HelperSpeechCommandRecognitionRasPi -args {hostIPAddress} -report -v
Deploying code. This may take a few minutes. ### Compiling function(s) HelperSpeechCommandRecognitionRasPi ... ------------------------------------------------------------------------ Location of the generated elf : /home/pi/remoteBuildDir/MATLAB_ws/R2021b/C/ExampleMatlab/ExampleManager/sporwal.Bdoc21b.j1648568/deeplearning_shared-ex00376115 ### Using toolchain: GNU GCC Embedded Linux ### 'C:\ExampleMatlab\ExampleManager\sporwal.Bdoc21b.j1648568\deeplearning_shared-ex00376115\codegen\exe\HelperSpeechCommandRecognitionRasPi\HelperSpeechCommandRecognitionRasPi_rtw.mk' is up to date ### Building 'HelperSpeechCommandRecognitionRasPi': make -f HelperSpeechCommandRecognitionRasPi_rtw.mk all ------------------------------------------------------------------------ ### Generating compilation report ... Warning: Function 'HelperSpeechCommandRecognitionRasPi' does not terminate due to an infinite loop. Warning in ==> HelperSpeechCommandRecognitionRasPi Line: 86 Column: 1 Code generation successful (with warnings): View report
Создайте команду, чтобы открыть HelperSpeechCommandRasPi
application on Raspberry Pi
Использование системы
отправить команду в ваш Raspberry Pi.
applicationName = 'HelperSpeechCommandRecognitionRasPi'; applicationDirPaths = raspi.utils.getRemoteBuildDirectory('applicationName',applicationName); targetDirPath = applicationDirPaths{1}.directory; exeName = strcat(applicationName,'.elf'); command = ['cd ' targetDirPath '; ./' exeName ' &> 1 &']; system(r,command);
Создайте dsp.UDPReceiver
системный объект, чтобы отправить аудио, записанное в MATLAB к вашему Raspberry Pi. Обновите targetIPAddress
для вашего Raspberry Pi. Raspberry Pi получает записанное аудио от того же порта с помощью dsp.UDPReceiver
системный объект.
targetIPAddress = '172.18.228.24'; UDPSend = dsp.UDPSender('RemoteIPPort',26000,'RemoteIPAddress',targetIPAddress);
Создайте dsp.UDPReceiver
системный объект, чтобы получить слуховые функции и предсказанную речевую команду индексирует от вашего Raspberry Pi. Каждый пакет UDP, полученный от Raspberry Pi, состоит из слуховых функций в порядке развертывания по столбцам, сопровождаемом предсказанным речевым индексом команды. Максимальная длина сообщения для dsp.UDPReceiver
объект составляет 65 507 байтов. Вычислите buffer size, чтобы вместить максимальное количество пакетов UDP.
sizeOfFloatInBytes = 4; maxUDPMessageLength = floor(65507/sizeOfFloatInBytes); samplesPerPacket = 1 + numElementsPerSpectrogram; numPackets = floor(maxUDPMessageLength/samplesPerPacket); bufferSize = numPackets*samplesPerPacket*sizeOfFloatInBytes; UDPReceive = dsp.UDPReceiver("LocalIPPort",21000, ... "MessageDataType","single", ... "MaximumMessageLength",samplesPerPacket, ... "ReceiveBufferSize",bufferSize);
Уменьшайте инициализацию наверху путем передачи кадра нулей к исполняемому файлу, работающему Raspberry Pi.
UDPSend(zeros(samplesPerCapture,1,"single"));
Обнаружьте команды, пока и осциллограф времени и матричное средство просмотра открыты или пока ограничение по времени не достигнуто. Чтобы остановить живое обнаружение перед, ограничение по времени достигнуто, закройте осциллограф времени или матричное окно средства просмотра.
show(timeScope) show(matrixViewer) timeLimit = 20; tic while isVisible(timeScope) && isVisible(matrixViewer) && toc < timeLimit % Capture audio and send that to RasPi x = adr(); UDPSend(x); % Receive data packet from RasPi udpRec = UDPReceive(); if ~isempty(udpRec) % Extract predicted index, the last sample of received UDP packet speechCommandIdx = udpRec(end); % Extract auditory spectrogram spec = reshape(udpRec(1:numElementsPerSpectrogram), [numBands, numSpectrumPerSpectrogram]); % Display time domain signal and auditory spectrogram timeScope(x) matrixViewer(spec) if speechCommandIdx == BackGroundIdx timeScope.Title = ' '; else timeScope.Title = char(labels(speechCommandIdx)); end drawnow limitrate end end hide(matrixViewer) hide(timeScope)
Чтобы остановить исполняемый файл на вашем Raspberry Pi, используйте stopExecutable
. Выпустите объекты UDP.
stopExecutable(codertarget.raspi.raspberrypi,exeName) release(UDPSend) release(UDPReceive)
Можно измерить время выполнения, взятое Raspberry Pi с помощью PIL (процессор в цикле) рабочий процесс. ProfileSpeechCommandRecognitionRaspi
поддерживание функции является эквивалентом функции HelperSpeechCommandRecognitionRaspi, за исключением того, что первый возвращает речевой индекс команды и слуховую спектрограмму, в то время как последний отправляет те же параметры с помощью UDP. Время, потраченное вызовами UDP, меньше 1 мс, который относительно мал по сравнению с полным временем выполнения.
Создайте объект настройки PIL.
cfg = coder.config('lib','ecoder',true); cfg.VerificationMode = 'PIL';
Установите ARM, вычисляют библиотеку и архитектуру.
dlcfg = coder.DeepLearningConfig('arm-compute'); cfg.DeepLearningConfig = dlcfg ; cfg.DeepLearningConfig.ArmArchitecture = 'armv7'; cfg.DeepLearningConfig.ArmComputeVersion = '19.05';
Настройте связь со своим целевым компьютером.
if (~exist('r','var')) r = raspi('raspiname','pi','password'); end hw = coder.hardware('Raspberry Pi'); cfg.Hardware = hw;
Установите каталог сборки и выходной язык.
buildDir = '~/remoteBuildDir'; cfg.Hardware.BuildDir = buildDir; cfg.TargetLang = 'C++';
Позвольте профилировать и затем сгенерируйте код PIL. Файл MEX под названием ProfileSpeechCommandRecognition_pil
сгенерирован в вашей текущей папке.
cfg.CodeExecutionProfiling = true; codegen -config cfg ProfileSpeechCommandRecognitionRaspi -args {rand(samplesPerCapture, 1, 'single')} -report -v
Deploying code. This may take a few minutes. ### Compiling function(s) ProfileSpeechCommandRecognitionRaspi ... ### Connectivity configuration for function 'ProfileSpeechCommandRecognitionRaspi': 'Raspberry Pi' ### Using toolchain: GNU GCC Embedded Linux ### Creating 'C:\ExampleMatlab\ExampleManager\sporwal.Bdoc21b.j1648568\deeplearning_shared-ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\coderassumptions\lib\ProfileSpeechCommandRecognitionRaspi_ca.mk' ... ### Building 'ProfileSpeechCommandRecognitionRaspi_ca': make -f ProfileSpeechCommandRecognitionRaspi_ca.mk all ### Using toolchain: GNU GCC Embedded Linux ### Creating 'C:\ExampleMatlab\ExampleManager\sporwal.Bdoc21b.j1648568\deeplearning_shared-ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\pil\ProfileSpeechCommandRecognitionRaspi_rtw.mk' ... ### Building 'ProfileSpeechCommandRecognitionRaspi': make -f ProfileSpeechCommandRecognitionRaspi_rtw.mk all Location of the generated elf : /home/pi/remoteBuildDir/MATLAB_ws/R2021b/C/ExampleMatlab/ExampleManager/sporwal.Bdoc21b.j1648568/deeplearning_shared-ex00376115/codegen/lib/ProfileSpeechCommandRecognitionRaspi/pil ------------------------------------------------------------------------ ### Using toolchain: GNU GCC Embedded Linux ### 'C:\ExampleMatlab\ExampleManager\sporwal.Bdoc21b.j1648568\deeplearning_shared-ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\ProfileSpeechCommandRecognitionRaspi_rtw.mk' is up to date ### Building 'ProfileSpeechCommandRecognitionRaspi': make -f ProfileSpeechCommandRecognitionRaspi_rtw.mk all ------------------------------------------------------------------------ ### Generating compilation report ... Code generation successful: View report
Вызовите сгенерированную функцию PIL многократно, чтобы получить среднее время выполнения.
testDur = 50e-3; numCalls = 100; for k = 1:numCalls x = pinknoise(fs*testDur,'single'); [speechCommandIdx, auditoryFeatures] = ProfileSpeechCommandRecognitionRaspi_pil(x); end
### Starting application: 'codegen\lib\ProfileSpeechCommandRecognitionRaspi\pil\ProfileSpeechCommandRecognitionRaspi.elf' To terminate execution: clear ProfileSpeechCommandRecognitionRaspi_pil ### Launching application ProfileSpeechCommandRecognitionRaspi.elf... Execution profiling data is available for viewing. Open Simulation Data Inspector. Execution profiling report available after termination.
Отключите выполнение PIL.
clear ProfileSpeechCommandRecognitionRaspi_pil
### Host application produced the following standard output (stdout) and standard error (stderr) messages: Execution profiling report: report(getCoderExecutionProfile('ProfileSpeechCommandRecognitionRaspi'))
Сгенерируйте профиль выполнения, сообщают, чтобы оценить время выполнения.
executionProfile = getCoderExecutionProfile('ProfileSpeechCommandRecognitionRaspi'); report(executionProfile, ... 'Units','Seconds', ... 'ScaleFactor','1e-03', ... 'NumericFormat','%0.4f')
ans = 'C:\ExampleMatlab\ExampleManager\sporwal.Bdoc21b.j1648568\deeplearning_shared-ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\html\orphaned\ExecutionProfiling_4f9ceee464b795df.html'
Максимальное время выполнения потрачено ProfileSpeechCommandRecognitionRaspi
функция является почти дважды средним временем выполнения. Можно заметить, что время выполнения максимально для первого вызова функции PIL, и это происходит из-за инициализации, происходящей в первом вызове. Среднее время выполнения составляет приблизительно 20 мс, который является ниже бюджета на 50 мс (аудио время получения). Уровень измерен на версии Модели B Raspberry Pi 4 1.1.