主要内容

树莓派上噪声代码生成中的关键字发现

这个例子演示了在树莓派™上使用双向长短期记忆(BiLSTM)网络和mel频率倒谱系数(MFCC)特征提取进行关键字发现的代码生成。具有深度学习支持的MATLAB®Coder™可以在树莓派上生成独立的金宝app可执行文件(.elf)。MATLAB®(.mlx)文件和生成的可执行文件之间的通信发生在异步用户数据报协议(UDP)上。输入语音信号使用timescope.掩码显示为围绕关键字YES的标记实例的蓝色矩形。更多关于MFCC特征提取和深度学习网络训练的细节,请访问基于MFCC和LSTM网络的噪声关键字发现(音频工具箱)

例子要求

  • MATLAB®Coder接口的深度学习支持包金宝app

  • ARM处理器,支持NEON扩展金宝app

  • ARM计算库版本20.02.1(在目标ARM硬件上)

  • 编译器和库的环境变量

有关受支金宝app持的库版本以及有关设置环境变量的信息,请参见用MATLAB编码器进行深度学习的先决条件(MATLAB编码器)

预训练网络关键字发现使用MATLAB®和流式音频从麦克风

预训练网络的采样率为16kHz。设置窗口长度为512样本,重叠长度为384和跳长定义为窗口长度和重叠长度之差。定义掩码估计的速率。掩码每生成一次numHopsPerUpdate音频帧。

Fs = 16e3;windowLength = 512;overlapLength = 384;hopLength = windowLength - overlapLength;numHopsPerUpdate = 16;maskLength = hopLength * numHopsPerUpdate;

创建一个audioFeatureExtractor(音频工具箱)对象执行MFCC特征提取。

afe = audioFeatureExtractor(“SampleRate”fs,...“窗口”损害(windowLength“周期”),...“OverlapLength”overlapLength,...“mfcc”,真的,...“mfccDelta”,真的,...“mfccDeltaDelta”,真正的);

下载并加载预训练的网络,以及()和标准差(年代)用于特征标准化的向量。

url =“http://ssd.mathworks.com/金宝appsupportfiles/audio/KeywordSpotting.zip”;downloadNetFolder =“。/”;netFolder = fullfile(下载netFolder,“KeywordSpotting”);如果~存在(netFolder“dir”) disp (“下载预先训练好的网络和音频文件(4个文件- 7 MB)…”解压缩(url, downloadNetFolder)结束负载(fullfile (netFolder“KWSNet.mat”),“KWSNet”“M”“S”);

调用generateMATLABFunction(音频工具箱)audioFeatureExtractor(音频工具箱)对象创建特征提取函数。

generateMATLABFunction (afe“generateKeywordFeatures”“IsStreaming”,真正的);

定义一个音频设备阅读器(音频工具箱)系统对象™从麦克风读取音频。将帧长度设置为跳长。这使得从麦克风接收到的每一个新的音频帧都可以计算一组新的特征。

framength = hopLength;adr = audioDeviceReader(“SampleRate”fs,...“SamplesPerFrame”frameLength,“OutputDataType”“单一”);

创建一个时间范围(DSP系统工具箱)可视化语音信号和估计的掩码。

Scope = timescope(“SampleRate”fs,...“TimeSpanSource”“属性”...“时间间隔”5,...“TimeSpanOverrunAction”“滚动”...“BufferLength”fs * 5 * 2,...“ShowLegend”,真的,...“ChannelNames”, {“演讲”“关键词面具”},...“YLimits”(-1.2 - 1.2),...“标题”关键字定位的);

初始化一个用于音频数据的缓冲区,一个用于计算特征的缓冲区,以及一个用于绘制输入音频和输出语音掩码的缓冲区。

dataBuff = dsp.AsyncBuffer(windowLength);featureBuff = dsp.AsyncBuffer(numHopsPerUpdate);plotBuff = dsp.AsyncBuffer(numHopsPerUpdate*windowLength);

对从麦克风接收到的语音执行关键字识别。要无限地运行循环,请设置期限.若要停止模拟,请关闭范围

显示(范围);timeLimit = 20;抽搐toc < timeLimit && isVisible(scope) data = adr();写(dataBuff、数据);写(plotBuff、数据);frame = read(dataBuff,windowLength,overlapLength);features = generateKeywordFeatures(帧,fs);写(featureBuff特性。');如果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 =模态(V);v = repmat(v,numHopsPerUpdate * hopLength,1); data = read(plotBuff); scope([data,v]); drawnowlimitrate结束结束隐藏(范围)

helperKeywordSpottingRaspi金宝app支持函数封装了前面演示的特征提取和网络预测过程。为了使特征提取与代码生成兼容,特征提取由生成的代码处理generateKeywordFeatures函数。为了使网络与代码生成兼容,支持函数使用金宝appcoder.loadDeepLearningNetwork(MATLAB编码器)函数加载网络。

支持函数金宝app使用adsp。UDPReceiver(DSP系统工具箱)系统对象接收从MATLAB®捕获的音频,并使用dsp。UDPSender(DSP系统工具箱)系统对象将输入语音信号连同网络预测的估计掩码一起发送到MATLAB®。类似地,MATLAB®实时脚本使用dsp。UDPSender(DSP系统工具箱)对象将捕获的语音信号发送到运行在树莓派上的可执行文件dsp。UDPReceiver(DSP系统工具箱)系统对象接收来自树莓派的语音信号和估计掩码。

在树莓派上生成可执行文件

取代hostIPAddress你的机器地址。树莓派将输入的语音信号和估计的掩码发送到指定的IP地址。

hostIPAddress =编码器。常数(“172.18.230.30”);

创建代码生成配置对象以生成可执行程序。将目标语言指定为c++。

CFG = code .config(exe”);cfg。TargetLang =“c++”

使用树莓派上的ARM计算库创建用于深度学习代码生成的配置对象。指定树莓派的架构,并将深度学习配置对象挂载到代码生成配置对象上。

DLCFG =编码器。DeepLearningConfig (“arm-compute”);dlcfg。ArmArchitecture =v7的;dlcfg。ArmComputeVersion =“20.02.1”;cfg。DeepLearningConfig = dlcfg;

使用树莓派支持包功能,金宝appraspi,以创建与树莓派的连接。在下面的代码中,替换:

  • raspiname树莓派的名字

  • π用你的用户名

  • 密码用你的密码

R =树皮(“raspiname”“π”“密码”);

创建一个coder.hardware(MATLAB编码器)对象,并将其附加到代码生成配置对象。

Hw = code .hardware(“树莓π”);cfg。硬件= hw;

指定树莓派上的构建文件夹。

buildDir =“~ / remoteBuildDir”;cfg.Hardware.BuildDir = buildDir;

生成生成独立可执行文件所需的c++主文件。

cfg。GenerateExampleMain =“GenerateCodeAndCompile”

生成的c++代码helperKeywordSpottingRaspi在树莓派上

codegen配置cfghelperKeywordSpottingRaspiarg游戏{hostIPAddress}报告
部署代码。这可能需要几分钟。警告:函数“helperKeywordSpottingRaspi”不会因为无限循环而终止。警告在==> helperKeywordSpottingRaspi行:78列:1代码生成成功(有警告):查看报告

使用部署的代码执行关键字发现

创建一个命令来打开helperKeywordSpottingRaspi应用在树莓派上。使用系统将命令发送到树莓派。

applicationName =“helperKeywordSpottingRaspi”;applicationDirPaths = raspi.utils.getRemoteBuildDirectory(“applicationName”applicationName);targetDirPath = applicationDirPaths{1}.directory;exeName = strcat(applicationName,“.elf”);命令= [“cd”targetDirPath,”;。/”exeName,' &> 1 &'];系统(r,命令);

创建一个dsp。UDPSender(DSP系统工具箱)系统对象发送音频捕获在MATLAB®树莓派。更新targetIPAddress你的树莓派树莓派接收从相同端口捕获的音频dsp。UDPReceiver(DSP系统工具箱)系统对象。

targetIPAddress =“172.18.231.92”;UDPSend = dsp。UDPSender (“RemoteIPPort”, 26000,“RemoteIPAddress”, targetIPAddress);

创建一个dsp。UDPReceiver(DSP系统工具箱)系统对象,从树莓派接收语音数据和预测的语音掩码。从树莓派接收到的每个UDP报文由maskLength掩码和语音样本。的最大消息长度dsp。UDPReceiver(DSP系统工具箱)对象是65507字节。计算缓冲区大小,以容纳UDP数据包的最大数量。

sizeOfFloatInBytes = 4;speechDataLength = maskLength;numElementsPerUDPPacket = maskLength + speechDataLength;maxUDPMessageLength = floor(65507/sizeOfFloatInBytes);numPackets = floor(maxUDPMessageLength/numElementsPerUDPPacket);bufferSize = numPackets*numElementsPerUDPPacket*sizeOfFloatInBytes;UDPReceive = dsp。UDPReceiver (“LocalIPPort”, 21000,...“MessageDataType”“单身”...“MaximumMessageLength”1 + numElementsPerUDPPacket,...“下面的”bufferSize);

只要时间范围是开放的,或者直到达到时间限制,就会发现关键字。如果要在时间限制之前停止带电检测,请关闭时间范围。

抽搐;显示(范围);时间限制= 20;toc < timelimit && isVisible(scope) x = adr();UDPSend (x);data = UDPReceive();如果~isempty(data) mask = data(1:maskLength);dataForPlot = data(maskLength + 1: numElementsPerUDPPacket);范围([dataForPlot、面具]);结束drawnowlimitrate结束

释放系统对象并终止独立可执行文件。

hide(scope) release(UDPSend) release(UDPReceive) release(scope) release(adr) stopExecutable(codertarget.raspi.raspberrypi,exeName)

使用可选PIL函数工作流评估执行时间

为了评估树莓派上独立可执行文件所花费的执行时间,使用PIL(处理器在循环)工作流。要执行PIL分析,为支持函数生成PIL函数金宝appprofileKeywordSpotting.的profileKeywordSpotting等于helperKeywordSpottingRaspi,只是前者返回语音和预测的语音掩码,而后者使用UDP发送相同的参数。UDP调用所花费的时间小于1ms,相对于总体执行时间来说是相对较小的。

创建一个代码生成配置对象来生成PIL函数。

CFG = code .config(“自由”“是”,真正的);cfg。VerificationMode =“公益诉讼”

设置ARM计算库和架构。

DLCFG =编码器。DeepLearningConfig (“arm-compute”);cfg。DeepLearningConfig = dlcfg;cfg.DeepLearningConfig.ArmArchitecture =v7的;cfg.DeepLearningConfig.ArmComputeVersion =“20.02.1”

设置与目标硬件的连接。

如果(~ (“r”“var”)) r = raspi(“raspiname”“π”“密码”);结束Hw = code .hardware(“树莓π”);cfg。硬件= hw;

设置构建目录和目标语言。

buildDir =“~ / remoteBuildDir”;cfg.Hardware.BuildDir = buildDir;cfg。TargetLang =“c++”

启用概要分析并生成PIL代码。一个名为profileKeywordSpotting_pil在当前文件夹中生成。

cfg。CodeExecutionProfiling = true;codegen配置cfgprofileKeywordSpottingarg游戏{pinknoise (hopLength 1 '单')}报告
部署代码。这可能需要几分钟。生成精灵的位置:/home/ Pi / remotebuilddir /MATLAB_ws/R2022a/W/Ex/ExampleManager/ sporwall . bdoc22a。j1844576/deeplearning_shared-ex18742368/codegen/lib/profileKeywordSpotting/pil Code generation successful:查看报告

评估树莓派的执行时间

多次调用生成的PIL函数以获得平均执行时间。

numPredictCalls = 10;totalCalls = numHopsPerUpdate * numPredictCalls;x = pinknoise(hopLength,1,“单一”);k = 1:totalCalls [maskReceived,inputSignal,plotFlag] = profileKeywordSpotting_pil(x);结束
###启动应用程序:codegen\lib\profileKeywordSpotting\pil\profileKeywordSpotting结束执行:clear profileKeywordSpotting_pil ###启动应用程序profilekeywordspot .elf…可以查看执行概要数据。打开模拟数据检查器。终止后可用的执行概要报告。

终止PIL执行。

清晰的profileKeywordSpotting_pil
###主机应用程序产生以下标准输出(stdout)和标准错误(stderr)消息:

生成执行概要报告以评估执行时间。

executionProfile = getCoderExecutionProfile(“profileKeywordSpotting”);报告(executionProfile,...“单位”“秒”...“ScaleFactor”“1 e 03”...“NumericFormat”' % 0.4 f '
ans = 'W:\Ex\ExampleManager\ sporwall . bdoc22a .j1844576\deeplearning_shared-ex18742368\codegen\lib\profileKeywordSpotting\html\orphan \ExecutionProfiling_d43d66431b443d29.html'

从生成的报告中绘制每一帧的执行时间。

由于初始化开销,第一帧的处理花费了大约20毫秒。时间图中每16帧的峰值(numHopsPerUpdate)对应于每16帧调用一次的计算密集型预测函数。最大执行时间约为30毫秒,低于实时流的128毫秒预算。性能是在树莓派4 Model B Rev 1.1上测量的。