主要内容

语音数字识别自定义测井谱图层和深度学习

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

数据

克隆或下载免费语音数字数据集(FSDD),可在https://github.com/Jakobovski/free-spoken-digit-dataset.FSDD是一个开放的数据集,这意味着它可以随着时间的推移而增长。本例使用的是2020年8月12日提交的版本,该版本包含3000份来自6位演讲者的数字0到9的英语录音。每个数字由每个人说50次。采样频率为8000hz。

使用audioDatastore管理数据访问。设置位置属性到计算机上FSDD录音文件夹的位置。这个例子使用了MATLAB返回的基本文件夹tempdir命令。

pathToRecordingsFolder = fullfile(tempdir,“free-spoken-digit-dataset”“录音”);location = pathToRecordingsFolder;ads = audioDatastore(location);

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

ads. labels = helpergenLabels(广告);总结(ads.Labels)
0 300 1 300 2 300 3 300 4 300 5 300 6 300 7 300 8 300 9 300

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

adsSample =子集(广告,[1,301,601,901]);SampleRate = 8000;i = 1:4 [audiossamples,info] = read(adsSample);次要情节(2,2,我)stft (audioSamples SampleRate,“FrequencyRange”“单向的”);标题(的数字:+字符串(info.Label))结束

将FSDD分为训练集和测试集,同时在每个子集中保持相同的标签比例。为了获得可重复的结果,请将随机数生成器设置为默认值。80%,也就是2400个录音被用于训练。剩下的600份录音,占总数的20%,被保留用于测试。

rng默认的;广告= shuffle(广告);[adsTrain,adsTest] = splitEachLabel(ads,0.8);

确认训练集和测试集都包含每个类的正确比例。

disp (countEachLabel (adsTrain))
标签计数_____ _____ 0 240 1 240 2 240 3 240 4 240 5 240 6 240 7 240 8 240 9 240
disp (countEachLabel (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个样本。辅助函数helperReadSPData截断或填充数据到8192个样本,并按其最大值归一化每个记录。的源代码helperReadSPData在附录中列出。通过结合使用转换数据存储,将此helper函数应用于每个记录audioDatastore

transstrain = transform(adsTrain,@(x,info)helperReadSPData(x,info),“IncludeInfo”,真正的);transTest = transform(adsTest,@(x,info)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.

在训练深度网络时,使用信号表示的对数通常是有利的,因为对数就像一个动态范围压缩器,提高具有小幅度(振幅)但仍然携带重要信息的表示值。在这个例子中,对数谱图比谱图表现更好。因此,本例创建了一个自定义的测井谱图层,并将其插入到输入层之后的网络中。指定义自定义深度学习层(深度学习工具箱)有关如何创建自定义层的更多信息。

声明参数和创建构造函数

logSpectrogramLayer是一个没有可学习参数的层,因此只需要不可学习的属性。这里唯一需要的属性是谱图计算所需的属性。在属性部分。在图层的预测函数,dlarray-金宝app支持的短时傅里叶变换函数dlstft用于计算谱图。如欲了解更多有关dlstft而这些参数,请参考dlstft文档。创建构造层和初始化层属性的函数。指定创建该层所需的任何变量作为构造函数的输入。

classdeflogSpectrogramLayer < nnet.layer.Layer属性%(可选)图层属性。%光谱窗口窗口重叠样本的百分比OverlapLength% DFT点数FFTLength信号长度%SignalLength结束方法函数层= logSpectrogramLayer(sigLength,NVargs)参数sigLength{mustBeNumeric}NVargs。窗口{mustBeFloat, mustBeNonempty, mustBeFinite、mustBeReal mustBeVector}=损害(128“周期”) NVargs。OverlapLength{mustBeNumeric}= 96个nvarg。FFTLength{mustBeNumeric}= 128个nvarg。的名字字符串“logspec”结束层。类型=“logSpectrogram”;层。的名字=NVargs。的名字;层。SignalLength = sigLength;层。Window = NVargs.Window;层。OverlapLength = NVargs.OverlapLength; layer.FFTLength = NVargs.FFTLength;结束...结束

预测功能

如前所述,自定义层使用dlstft得到STFT,然后计算STFT的平方幅度的对数,得到对数谱图。也可以删除日志函数,或者添加任何其他dlarray支持的函数来自定义输出。金宝app你可以复制logSpectrogramLayer.m如果您想尝试从predict函数获得不同的输出,则将其转移到不同的文件夹。建议将自定义层保存在不同的名称下,以防止与本例中使用的版本发生冲突。

函数Z = predict(图层,X)在预测时间通过层转发输入数据%输出结果。%的输入:% layer -向前传播的层% X -输入数据,指定为1 × 1 × c × n% dlarray,其中N是迷你批大小。%输出:% Z -层前向函数的输出返回为% an sz(1)-by-sz(2)-by-sz(3)-by-N darray,%,其中sz为层输出大小,N为%迷你批大小。%使用dlstft计算短时傅里叶变换。指定数据格式为SSCB,以匹配% imageInputLayer。X =挤压(X);[YR,YI] = dlstft(X;“窗口”层。窗口中,...“FFTLength”层。FFTLength,“OverlapLength”层。OverlapLength,...“DataFormat”“确认”);%这段代码是需要处理的事实,二维卷积% DAG网络期望SSCBYR = permute(YR,[1 4 2 3]);YI = permute(YI,[1 4 2 3]);取短时傅里叶的对数平方%变换。Z = log(YR。^2 + yi .^2);结束

因为logSpectrogramLayer使用相同的前向传递进行训练和预测(推断),只有预测函数是需要的,而不是向前函数是必需的。此外,因为预测函数使用dlstft,支持金宝appdlarray时,反向传播中的微分可以自动完成。这意味着你不需要写落后的函数。这在编写支持的自定义层时是一个显著的优势金宝appdlarray.获取支持的函数列表金宝appdlarray对象,看到支持dlarray的函数列表金宝app(深度学习工具箱)

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

您可以像使用“深度学习工具箱”中的任何其他层一样使用自定义层。构造一个小的DCNN作为包含自定义层的层数组logSpectrogramLayer.使用卷积和批处理归一化层,并使用最大池化层对特征映射进行下采样。为了防止过拟合,在最后一个全连接层的输入端添加少量的dropout。

sigLength = 8192;dropoutProb = 0.2;numF = 12;图层= [imageInputLayer([sigLength 1]) logSpectrogramLayer(sigLength,“窗口”、汉明(1280)“FFTLength”, 1280,...“OverlapLength”, 900) convolution2dLayer (5 numF“填充”“相同”maxPooling2dLayer(3,“步”2,“填充”“相同”) convolution2dLayer (3 2 * numF“填充”“相同”maxPooling2dLayer(3,“步”2,“填充”“相同”) convolution2dLayer(3、4 * numF,“填充”“相同”maxPooling2dLayer(3,“步”2,“填充”“相同”) convolution2dLayer(3、4 * numF,“填充”“相同”(3,4*numF,“填充”“相同”) batchNormalizationLayer reluLayer maxPooling2dLayer(2) dropoutLayer(dropoutProb) fullyConnectedLayer(numel(categories(ads.Labels)) softmaxLayer classificationLayer(“类”类别(ads.Labels));];

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

UsePrefetch =真正的;选项= trainingOptions(“亚当”...“InitialLearnRate”1的军医,...“MaxEpochs”30岁的...“MiniBatchSize”, 50岁,...“洗牌”“every-epoch”...“DispatchInBackground”UsePrefetch,...“阴谋”“训练进步”...“详细”、假);

培训网络。

[trainedNet,trainInfo] = trainNetwork(transTrain,layers,options);

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

[YPred,probs] = category (trainedNet,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 =“column-normalized”;ccDCNN。RowSummary =“row-normalized”

总结

这个例子展示了如何创建一个自定义频谱图层使用dlstft.使用支持的功能金宝appdlarray,该示例演示了如何以支持反向传播和gpu使用的方式将信号处理操作嵌入到网络中。金宝app

附录:Helper函数

函数标签= helpergenLabels(广告)此功能仅用于“语音数字识别”%自定义测井谱图层和深度学习的例子。它可能会改变%将在未来的版本中删除。tmp = cell(数字(ads.Files),1);表达=“[0 - 9]+ _”nf = 1: number (ads.Files) idx = regexp(ads.Files{nf},表达式);tmp{nf} = ads.Files{nf}(idx);结束标签=分类(tmp);结束
函数[out,info] = helperReadSPData(x,info)此功能仅用于“语音数字识别”%自定义测井谱图层和深度学习的例子。它可能会改变%将在未来的版本中删除。N =数字(x);如果N > 8192 x = x(1:8192);elseifN < 8192 pad = 8192-N;Prepad =地板(pad/2);Postpad = cell (pad/2);X = [0 (prepad,1);x;0 (postpad 1)];结束X = X /max(abs(X));out = {x /max(abs(x)),info.Label};结束