主要内容

与定制日志谱图层和深度学习的口语数字识别

这个例子展示了如何使用深度卷积神经网络(CNN)和自定义对数谱图层对语音数字进行分类。自定义层使用dlstft.函数以支持自动反向传播的方式计算短时傅里叶变换。万博1manbetx

数据

克隆或下载自由语音数字数据集(FSDD),可在https://github.com/Jakobovski/free-spoken-digit-dataset.FSDD是一个打开的数据集,这意味着它可以随着时间的推移而增长。此示例使用8月12日在2020年8月12日提交的版本,该版本由六位扬声器中获取的数字0到9中的3000个录制组成。每个扬声器都会使用每个数字50次。数据以8000 Hz采样。

使用音频数据存储管理数据访问。设定位置属性设置为计算机上FSDD recordings文件夹的位置。本例使用MATLAB的tempdir指挥部。

pathtorecordingsfolder = fullfile(tempdir,'自由发言 -  DataSet',“录音”);位置= PathtoreCordingsFolder;广告= audiodatastore(位置);

辅助函数助手标签从FSDD文件创建标签的分类数组。的源代码助手标签列在附录中。列出类和每个类的例子数量。

Ads.Labels = HelpergenLabels(广告);摘要(Ads.Labels)
1 300 2 300 3 300 4 300 5 300 6 300 7 300 8 300 9 300

提取四个音频文件对应不同的数字。使用stft用分贝来绘制它们的声谱图。在声谱图上可以看出发音的共振峰结构的差异。这使得谱图成为学习在深度网络中区分数字的合理信号表示。

adsSample=子集(ads[1301601901]);采样器=8000;i = 1:4 [audiosamples,信息] =读取(adssample);子图(2,2,i)stft(audiosamples,sampleate,'频率范围','片面');标题(的数字:+字符串(info.Label))结束

将FSDD拆分为培训和测试集,同时在每个子集中维护相同的标签比例。对于可重复的结果,将随机数生成器设置为其默认值。百分之八十或2400张录音用于培训。剩下的600次录音,占总量的20%,被扣除进行测试。

RNG.违约; ads=洗牌(ads)[adsTrain,adsTest]=拆分标签(ads,0.8);

确认培训和测试集都包含每个课程的正确比例。

disp (countEachLabel (adsTrain))
标签计数uuuuuuuuuuuuuuuuuu0 240 1 240 2 240 3 240 4 240 5 240 6 240 7 240 8 240 9 240
DISP(CONSECHANCELABEL(ADSTEST))
标签计数_____ _____ 0 60 1 60 2 60 3 60 4 60 5 60 6 60 7 60 8 60 9 60

FSDD中的记录在样本中没有相同的长度。为了在深度网络中使用谱图作为信号表示,需要一个统一的输入长度。对这个版本的FSDD的音频记录的分析表明,8192个样本的公共长度是合适的,以确保没有语音数字被切断。长度大于8192个样本的录音被截断为8192个样本,而小于8192个样本的录音被对称填充为8192个样本。辅助函数HelperReadsData将数据截断或划接到8192个样本,并按其最大值进行规范化。源代码HelperReadsData列在附录中。通过与转换数据存储一起使用,这个帮助函数被应用到每个记录音频数据存储

transTrain=transform(adsTrain,@(x,info)helperReadSPData(x,info),“IncludeInfo”,对);transtest =转换(adstest,@(x,信息)helperreadspdata(x,Info),“IncludeInfo”,对);

定义自定义日志谱图层

当在网络之外进行任何信号处理作为预处理步骤时,有更多的机会,网络预测由不同的预处理设置而不是网络训练中使用的网络预测。这可能对网络性能产生重大影响,通常导致比预期更差。将频谱图或网络内的任何其他预处理计算放置为层,为您提供一个自包含的模型,并简化了部署的管道。它允许您通过所有所需的信号处理操作有效地培训,部署或共享您的网络。在该示例中,主要信号处理操作是频谱图的计算。计算网络内的谱图的能力对于推理和当设备存储空间不足以保存频谱图时非常有用。计算网络中的频谱图仅需要对当前批量频谱图进行足够的内存分配。但是,应该指出的是,在训练速度方面不是最佳选择。如果您有足够的内存,通过预先计算所有频谱图并存储这些结果,培训时间显着降低。然后,要培训网络,从存储而不是原始音频读取频谱图“图像”并直接在网络中输入频谱图。 Note that while this results in the fastest training time, the ability to perform signal processing inside the network still has considerable advantages for the reasons previously cited.

在训练深度网络时,使用信号表示的对数通常是有利的,因为对数的作用类似于动态范围压缩器,提升了具有较小幅度(振幅)但仍携带重要信息的表示值。在本例中,对数谱图的性能优于谱图。因此,本例创建了一个自定义日志谱图层,并将其插入到输入层之后的网络中。提到定义自定义深度学习层(深度学习工具箱)有关如何创建自定义图层的详细信息,请参见。

声明参数和创建构造函数

logspectroggeLayer.是没有可学习参数的图层,因此只需要不可学习的特性。这里唯一需要的属性是谱图计算所需的属性。在表格中申报特性部分。在图层中预测函数,dlarray-万博1manbetx 支持的短时傅里叶变换功能dlstft.用于计算光谱图。有关dlstft.这些参数,请参考dlstft.文档。创建构造层和初始化层属性的函数。指定创建层所需的任何变量作为构造函数的输入。

classdeflogspectroggeLay 特性%(可选)图层特性。%光谱窗窗口%重叠的次腹板数量overtaplenth% DFT点数FFTLength%信号长度signallength.结束方法功能tillay = logspectroggeLer(siglength,nvargs)争论sigLength{mustBeNumeric}NVargs。窗口{mustBeFloat, mustBeNonempty, mustBeFinite、mustBeReal mustBeVector}=损害(128“周期性”)NVargs.overlapplength{mustBeNumeric}= 96 NVargs。FFTLength{mustBeNumeric}= 128 nvargs.name.字符串=“logspec”结束层。类型=“logSpectrogram”;layer.name = nvargs.name;tillay.signallength = siglength;layer.window = nvargs.window;tillay.overlaplength = nvargs.overlaplength;tillay.fftlength = nvargs.fftlength;结束...结束

预测函数

如前所述,自定义层使用dlstft.获得STFT,然后计算平方震级STFT的对数,以获得对数光谱图。您还可以删除日志函数,或者添加任何其他dlarray支持的函数来自定义输出。你可以复制万博1manbetxlogSpectrogramLayer.m如果要尝试从预测功能的不同输出,则到一个不同的文件夹。建议将自定义层保存在不同的名称下,以防止任何与此示例中使用的版本的冲突。

功能Z=预测(层,X)%在预测时通过层转发输入数据,并%输出结果。%%输入:% layer -要转发的层%x  - 输入数据,指定为1-by-1-c-by-n% dlarray,其中N为迷你批处理大小。%产出:% Z -层前向函数的输出返回为% an sz(1)-by-sz(2)-by-sz(3)-by-N%sz是图层输出大小和n是%最小批量大小。%使用dlstft计算短时傅里叶变换。%将数据格式指定为SSCB以匹配输出% imageInputLayer。x =挤压(x);[Yr,yi] = dlstft(x,“窗口”,layer.Window,...“FFTLength”,layer.fft长度,“重叠长度”,tillay.overlaplength,...'datomformat','TBC');%此代码需要处理2D卷积的事实%DAG网络期望SSCBYR=排列(YR[1 4 2 3]);YI=permute(YI[1 4 2 3]);取短时间傅里叶模的对数平方%变换。Z=对数(年数^2+YI.^2);结束

因为logSpectrogramLayer使用相同的前向通道进行训练和预测(推断),只有预测功能是必需的,不需要向前函数是必需的。另外,因为预测功能使用dlstft.,它支持万博1manbetxdlarray,反向传播中的微分可以自动完成。这意味着您不必编写落后功能。这是编写支持万博1manbetxdlarray.有关支持的功能列表万博1manbetxdlarray对象,参见Dlarray支持的函数列表万博1manbetx(深度学习工具箱)

深度卷积神经网络(DCNN)架构

您可以使用自定义层与深度学习工具箱中的任何其他层相同的方式。构造一个小的DCNN作为层数组,其中包括自定义层logspectroggeLayer..使用卷积和批量归一化层次,使用MAX池图层下映射特征映射。为了防止过度装备,将少量丢失添加到最后完全连接的层的输入。

sigLength=8192;dropoutProb=0.2;numF=12;层=[imageInputLayer([sigLength 1])logSpectrogramLayer(sigLength,“窗口”、汉明(1280)“FFTLength”,1280,...“重叠长度”, 900) convolution2dLayer (5 numF“填充”,'相同的'maxPooling2dLayer(3,“大步走”2,“填充”,'相同的')卷积2层(3,2*numF,“填充”,'相同的'maxPooling2dLayer(3,“大步走”2,“填充”,'相同的')卷积2dlayer(3,4 * numf,“填充”,'相同的'maxPooling2dLayer(3,“大步走”2,“填充”,'相同的')卷积2dlayer(3,4 * numf,“填充”,'相同的') batchNormalizationLayer reluLayer卷积2dlayer (3,4*numF,“填充”,'相同的') batchNormalizationLayer reluLayer maxPooling2dLayer(2) dropoutLayer(dropoutProb) fulllyconnectedlayer (numel(categories(ads.Labels))) softmaxLayer classificationLayer('课程',类别(广告标签));];

设置用于训练网络的超参数。使用小批量的50学习速率1的军医.指定亚当优化。集使用预取真的启用异步预取和数据排队,优化训练性能。后台数据调度和使用GPU训练网络需要并行计算工具箱™。

uderprefetch =.真的;选择= trainingOptions (“亚当”,...“InitialLearnRate”,1e-4,...“MaxEpochs”,30,...“MiniBatchSize”,50,...“洗牌”,'每个时代',...'disparctinbackground'UsePrefetch,...“情节”,“培训进度”,...“冗长”,错误的);

培训网络。

[trainedNet, trainInfo] = trainNetwork (transTrain层,选项);

使用经过训练的网络来预测测试集的数字标签。计算预测精度。

[YPred,probs]=分类(训练网,transTest);cnnAccuracy=sum(YPred==adsTest.Labels)/numel(YPred)*100
cnnAccuracy=97

使用混淆图总结测试集上经过培训的网络的性能。使用列和行摘要显示每个类的精度和召回率。混淆图底部的表格显示了精度值。混淆图右侧的表格显示了召回值。

图('单位',“正常化”,'位置',[0.2 0.2 0.5 0.5]);ccdcnn = confusionchart(adstest.labels,ypred);ccdcnn.title =“DCNN的困惑图”;ccdcnn.columnsummary =“列规格化”; ccDCNN.RowSummary='行标准化'

概括

此示例显示了如何使用自定义频谱图层使用dlstft..使用支持的功能万博1manbetxdlarray,该示例演示了如何以一种支持反向传播和gpu使用的方式将信号处理操作嵌入到网络中。万博1manbetx

附录:辅助函数

功能标签= helpergenLabels(广告)%此函数仅用于“与之展示的数字识别”%自定义日志谱图层和深度学习“示例。它可能会改变或改变%在将来的释放中删除。tmp=单元(numel(ads.Files),1);表情=“[0-9] + _”nf = 1:numel(ads.Files) idx = regexp(ads.Files{nf},expression);tmp {nf} = ads.Files {nf} (idx);结束标签=分类(TMP);结束
功能[out,信息] = HelperReadspdata(X,Info)%此函数仅用于“与之展示的数字识别”%自定义日志谱图层和深度学习“示例。它可能会改变或改变%在将来的释放中删除。N=努美尔(x);如果n> 8192 x = x(1:8192);埃尔塞夫N<8192 pad=8192-N;预垫=地板(垫/2);postpad=ceil(pad/2);x=[零(前置,1);x;零(后置,1)];结束x = x / max (abs (x));出= {x / max (abs (x)), info.Label};结束