主要内容

使用深度学习的言语命令识别

此示例演示如何训练一个深度学习模型,该模型检测音频中是否存在语音命令。该示例使用语音命令数据集[1]训练卷积神经网络以识别给定的命令集。

要从头开始训练网络,必须先下载数据集。如果不想下载数据集或训练网络,则可以加载本示例提供的预训练网络,并执行示例的下两部分:通过预先训练的网络识别命令使用来自麦克风的流音频检测命令

通过预先训练的网络识别命令

在详细介绍培训过程之前,您将使用经过预培训的语音识别网络来识别语音命令。

加载预先训练好的网络。

装载(“commandNet.mat”

对网络进行培训,以识别以下语音命令:

  • “是的”

  • “没有”

  • “向上”

  • “向下”

  • “左”

  • “对”

  • “关于”

  • “关”

  • “停下来”

  • “走”

装载一个人说“停止”的短语信号。

[x,fs]=音频读取(“停止命令。flac”);

听指挥。

声音(x,fs)

预先训练的网络将基于听觉的频谱图作为输入。您将首先将语音波形转换为基于听觉的频谱图。

使用函数extractAuditoryFeature来计算听觉谱图。在稍后的示例中,您将了解特征提取的细节。

auditorySpect=helperExtractAuditoryFeatures(x,fs);

根据命令的听觉频谱图对命令进行分类。

命令=分类(trainedNet、auditorySpect)
命令=分类停止

训练网络将不属于该集合的单词分类为“未知”。

现在,您将对未包含在要识别的命令列表中的单词(“play”)进行分类。

加载语音信号并收听。

x=音频读取(“play_command.flac”); 声音(x,fs)

计算听觉频谱图。

auditorySpect=helperExtractAuditoryFeatures(x,fs);

对信号进行分类。

命令=分类(trainedNet、auditorySpect)
命令=分类未知

训练网络将背景噪声分类为“背景”。

创建由随机噪声组成的1秒信号。

X = PinkNoise(16E3);

计算听觉频谱图。

auditorySpect=helperExtractAuditoryFeatures(x,fs);

对背景噪声进行分类。

命令=分类(trainedNet、auditorySpect)
命令=分类背景

使用来自麦克风的流音频检测命令

在麦克风的流式音频上测试预先训练好的命令检测网络。例如,尝试说出其中一个命令,停止。然后,尝试说这样一个未知的单词,如马文希拉房屋,或0到9之间的任意数字。

以Hz为单位指定分类率,并创建可以从麦克风读取音频的音频设备读取器。

分类率=20;adr=音频设备阅读器(“采样器”,财政司司长,“样品性能框架”,楼(fs/分级率);

初始化音频缓冲区。提取网络的分类标签。为流式音频的标签和分类概率初始化半秒的缓冲区。使用这些缓冲区比较较长时间内的分类结果,并在检测到命令时通过构建“一致性”。指定决策逻辑的阈值。

audioBuffer=dsp.AsyncBuffer(fs);labels=trainedNet.Layers(end).Classes;YBuffer(1:classificationRate/2)=分类(“背景”);probBuffer=0([numel(标签),classificationRate/2]);countThreshold=ceil(classificationRate*0.2);probThreshold=0.7;

只要创建的图形存在,就创建图形并检测命令时限.要停止实时检测,只需关闭图形。

h =图(“单位”'标准化'“位置”,[0.20.1 0.6 0.8]);时限=20;tic虽然ishandle(h)和&toc<时限%从音频设备提取音频样本并将样品添加到%缓冲区。x=adr();write(audioBuffer,x);y=read(audioBuffer,fs,fs adr.SamplesPerFrame);spec=helperExtractAuditoryFeatures(y,fs);%对当前光谱图进行分类,将标签保存到标签缓冲区,%并将预测的概率保存到概率缓冲区。[Y预测,问题]=分类(培训网,规范,'executionenvironment'“cpu”);YBUFFER = [YBUFFER(2:END),Y预期];probbuffer = [probbuffer(:,2:结束),probs(:)];%绘制电流波形和频谱图。子地块(2,1,1)绘图(y)轴牢固的Ylim([ -  1,1])子图(2,1,2)PColor(SPEC')Caxis([ -  4 2.6445])阴影平的%现在通过执行一个非常简单的实际命令检测来进行实际命令检测%阈值操作。声明检测并在%图标题(如果以下所有条件均成立):1)最常见的标签%不是背景。2)至少是最新帧的countThreshold%标签同意。3)预测标签的最大概率是在%最小阈值。否则,不要声明检测。[YMode,count]=mode(YBuffer);maxProb=max(probBuffer(labels==YMode,:);子批(2,1,1)如果伊莫德==“背景”||计数" ")其他的标题(字符串(YMode),“字体大小”,20)终止刷新屏幕终止

加载语音命令数据集

此示例使用Google Speech Commands数据集[1]。下载该数据集并卸载下载的文件。将PathToDatabase设置为数据的位置。

网址='https://ssd.mathworks.com/万博1manbetxsupportfiles/audio/google_speech.zip';downloadFolder=tempdir;dataFolder=fullfile(downloadFolder,“谷歌演讲”);如果~存在(dataFolder“dir”)disp('正在下载数据集(1.4 GB)…')解压(url,下载文件夹)终止

创建培训数据存储

创建一个audiodatastore.(音频工具箱)这指向训练数据集。

ads=音频数据存储(完整文件(数据文件夹,“火车”),...“包含子文件夹”符合事实的...“FileExtensions”“.wav”...“标签源”“foldernames”
ads=audioDatastore,具有以下属性:文件:{'.\AppData\Local\Temp\google_speech\train\bed\00176480_nohash_0.wav'.''.\AppData\Local\Temp\google_speech\train\bed\Temp\google_speech\train\bed\004ae714_nohash_1.wav'.'和51085个以上}文件夹:{'C:\Users\jibrahim\AppData\Local\Temp\google_speech\train'}标签:[bed;bed;bed…和51085更分类]AlternateFileSystemRoots:{}输出数据类型:'double'支持输出格式:[“wav”“flac”“ogg”“mp4”“m4a”]默认输出格式:“wav”万博1manbetx

选择要识别的单词

指定希望模型识别为命令的单词。将所有非命令的单词标记为命令未知的.将非命令的单词标记为未知的创建一组单词,该单词近似于命令以外的所有单词的分布。该网络使用此组来了解命令和所有其他单词之间的差异。

为了减少已知和未知单词之间的类别不平衡,加快处理速度,只在训练集中包含一小部分未知单词。

使用子集(音频工具箱)创建仅包含命令和未知单词的子集的数据存储。计算属于每个类别的示例的数量。

命令=分类([“是的”“没有”“向上”“向下”“左”“对”“关于”“关”“停下来”“走”]);isCommand=ismember(ads.Labels,commands);isUnknown=~isCommand;includeAction=0.2;mask=rand(numel(ads.Labels),1)“未知”); adsTrain=子集(ads,isCommand | isUnknown);计数标签(adsTrain)
ans=11×2表格标签计数\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

创建验证数据存储

创建一个audiodatastore.(音频工具箱)指向验证数据集。按照创建培训数据存储所用的相同步骤操作。

ads=音频数据存储(完整文件(数据文件夹,“验证”),...“包含子文件夹”符合事实的...“FileExtensions”“.wav”...“标签源”“foldernames”)isCommand=ismember(ads.Labels,commands);isUnknown=~isCommand;includeAction=0.2;mask=rand(numel(ads.Labels),1)“未知”);adsValidation=子集(ads,isCommand |未知);countEachLabel(adsValidation)
ads=audioDatastore,具有以下属性:文件:{'.\AppData\Local\Temp\google\u speech\validation\bed\026290a7\u nohash\u 0.wav';'.'.\AppData\Local\Temp\google\u speech\validation\bed\060cd039\u nohash\u speech\validation\bed\060cd039\u nohash\u 1.wav'.'和6795其他}文件夹:{'C:\Users\jibrahim\AppData\Local\Temp\google_speech\validation'}标签:[bed;bed;bed…和6795更分类]AlternateFileSystemRoots:{}输出数据类型:'double'支持输出格式:[“wav”“flac”“ogg”“mp4”“m4a”]默认输出格式:“wav”ans=11×2表格标签计数\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu万博1manbetxuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

要使用整个数据集对网络进行训练并达到尽可能高的精度,请设置还原酶错误的。快速运行此示例,设置还原酶符合事实的

reducedastatset=false;如果Depentataset numuniqueLabels = numel(唯一(adstrain.labels));%将数据集减少20倍adstrain = splitheachlabel(adstrain,round(numel(adstrain.files)/ numuniqueLabels / 20));ADSValidation = SpliteachLabel(ADSValidation,ROUND(NUMER(ADSValidation.Files)/ NumUnIqueLabels / 20));终止

计算听觉频谱图

为准备卷积神经网络的有效培训数据,将语音波形转换为基于听觉的频谱图。

定义特征提取的参数。分段是每个语音片段的持续时间(以秒为单位)。帧持续时间是用于频谱计算的每个帧的持续时间。啤酒花持续时间是每个光谱之间的时间步长。麻木是听觉频谱图中的过滤器数量。

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

fs=16e3;%数据集的已知采样率。segmentDuration=1;frameDuration=0.025;hopDuration=0.010;segmentSamples=round(segmentDuration*fs);frameSamples=round(frameDuration*fs);hopSamples=round(hopDuration*fs);OverlapseSamples=frameSamples-hopSamples;FFTLLength=512;Numberands=50;afe=audioFeatureExtractor(...“采样器”,财政司司长,...“FFTLength”,fft长度,...“窗口”,hann(框架样本,'定期'),...“重叠长度”,重叠样本,...“巴克光谱”,true);setExtractorParams(afe,“巴克光谱”“NumBands”,麻木,“窗口规范化”,假);

从数据集中读取文件。训练卷积神经网络需要输入尺寸是一致的大小。数据集中的某些文件少于1秒。将零填充应用于音频信号的正面和背面,使其长度为长度分段样本

x=读取(adsTrain);numSamples=大小(x,1);numToPadFront=地板((分段采样-numSamples)/2);numToPadBack=天花板((分段采样-numSamples)/2);xPadded=[零(numToPadFront,1,“喜欢”,x);x;零(numToPadBack,1,“喜欢”,x)];

要提取音频功能,请调用摘录.输出为横行随时间变化的树皮谱。

特征=提取(afe,xPadded);[numHops,numFeatures]=大小(特征)
numHops=98 numFeatures=50

在本例中,通过应用对数对听觉频谱图进行后处理。记录较小的数字可能导致舍入误差。

为了加快处理速度,可以使用将特征提取分布到多个辅助对象议案

首先,确定数据集的分区数。如果您没有并行计算工具箱™,请使用单个分区。

如果~z~我是空的(“平行”))&&&~reducedasetpool=gcp;numPar=numpartitions(adsTrain,pool);其他的numpar = 1;终止

对于每个分区,从数据存储中读取,将信号置零,然后提取特征。

议案ii=1:numPar subds=partition(adsTrain,numPar,ii);XTrain=zero(numHops,numBands,1,numel(subds.Files));为了idx=1:numel(subds.Files)x=read(subds);xPadded=[zeros(floor((segmentSamples size(x,1))/2),1);x;zeros(ceil((segmentSamples size(x,1))/2),1];XTrain(:,:,:,idx)=extract(afe,xPadded);终止XTrainC{ii}=XTrain;终止

将输出转换为四维阵列,并沿四维方向绘制听觉频谱图。

XTrain=cat(4,XTrainC{:});[numHops,numBands,numChannels,numSpec]=size(XTrain)
numHops=98 numBands=50 numChannels=1 numSpec=25021

根据窗户功率缩放特征,然后取日志。为了获得分布更平滑的数据,使用小偏移量对谱图取对数。

epsil=1e-6;XTrain=log10(XTrain+epsil);

对验证集执行上述特征提取步骤。

如果~z~我是空的(“平行”))pool=gcp;numPar=numpartitions(adsvalization,pool);其他的numpar = 1;终止议案ii=1:numPar subds=partition(adsvalization,numPar,ii);XValidation=zero(numHops,numBands,1,numel(subds.Files));为了idx = 1:numel(subds.files)x =读取(subds);Xpadded = [零(楼层((Segmensampless尺寸(x,1))/ 2),1); x; zeros(ceil((segmentsampless-size(x,1))/ 2),1)];xValidation(:,::,idx)=提取物(afe,xpadded);终止XValidationC {2} = XValidation;终止XValidation=cat(4,XValidationC{:});XValidation=log10(XValidation+epsil);

隔离列车和验证标签。删除空类别。

ytrain = removecats(adstrain.labels);yvalidation = removecats(adsvalidation.labels);

可视化数据

绘制一些训练样本的波形和听觉频谱图。播放相应的音频片段。

specmin = min(xtrain,[],“全部”);specMax=max(XTrain,[],“全部”);idx=randperm(numel(adsTrain.Files),3);图(“单位”'标准化'“位置”,[0.2 0.2 0.6 0.6]);为了i=1:3[x,fs]=audioread(adsTrain.Files{idx(i)});子地块(2,3,i)绘制(x)轴牢固的标题(字符串(adsTrain.Labels(idx(i)))子批次(2,3,i+3)spect=(XTrain(:,:,1,idx(i)));pcolor(spect)caxis([specMin specMax])着色平的sound(x,fs)暂停(2)终止

添加背景噪声数据

网络必须不仅能够识别不同的口语词,而且能够检测输入是否包含静音或背景噪声。

使用中的音频文件_background_文件夹以创建一秒钟背景噪音片段的示例。从每个背景噪音文件创建相同数量的背景噪音片段。您也可以创建自己的背景噪音录制并将其添加到_background_文件夹。在计算频谱图之前,该函数使用从对数均匀分布中采样的系数重新缩放每个音频片段,采样范围如下所示:容积法

adsBkg=音频数据存储(完整文件(数据文件夹,'背景'))numBkgClips=4000;如果reducedastatset numBkgClips=numBkgClips/20;终止volumerange = log10([1E-4,1]);numbkgfiles = numel(adsbkg.files);numclipsperfile = histcounts(1:numbkgclips,linspace(1,numbkgclips,numbkgfiles + 1));xbkg = zeros(尺寸(xtrain,1),尺寸(xtrain,2),1,numbkgclips,“单身”);bkgall = readall(adsbkg);IND = 1;为了count=1:numBkgFiles bkg=bkgAll{count};idxStart=randi(nummel(bkg)-fs,numClipsPerFile(count),1);idxEnd=idxStart+fs-1;增益=10^((volumeRange(2)-volumeRange(1))*rand(numClipsPerFile(count),1)+volumeRange(1));为了j=1:numClipsPerFile(count)x=bkg(idxStart(j):idxEnd(j))*增益(j);x=最大值(最小值(x,1),-1);Xbkg(:,:,:,ind)=提取物(afe,x);如果模(ind,1000)=0显示(“已处理”+字符串(IND)+“背景剪辑来自”+字符串(numBkgClips))终止ind=ind+1;终止终止Xbkg=log10(Xbkg+epsil);
adsBkg=audioDatastore及其属性:文件:{'.\AppData\Local\Temp\google\u speech\background\doing\u the_disks.wav'.'.'.\AppData\Local\Temp\google\U speech\background\doing\u the_the_Discip.wav'.'.\AppData\Local\Temp\Temp\google\Temp\Temp\google\Temp\Temp\Temp\google\speech\google\bike\wav'.'和其他3个文件夹:{'C:\Users\jibrahim\AppData\Local\Temp\google\u speech\background'}可选文件系统根:{}输出数据类型:{}双标签:{}支持输出格式:[“wav”“flac”“ogg”“mp4”“m4a”]默认输出格式万博1manbetx:“wav”处理了4000个背景剪辑中的1000个,处理了4000个背景剪辑中的2000个,处理了4000个背景剪辑中的3000个,处理了4000个背景剪辑中的4000个

在训练,验证和测试集之间分离背景噪声的谱图。因为这_背景噪声_文件夹仅包含大约五分钟半的背景噪声,不同数据集中的背景样本高度相关。若要增加背景噪声的变化,可以创建自己的背景文件并将其添加到文件夹中。若要提高网络对噪声的鲁棒性,还可以尝试混合backgr将噪音输入语音文件。

numTrainBkg =地板(0.85 * numBkgClips);numValidationBkg =地板(0.15 * numBkgClips);XTrain(:,:,: + 1:终端+ numTrainBkg) = Xbkg (:,:,:, 1: numTrainBkg);YTrain(+ 1:结束+ numTrainBkg) =“背景”;XValidation(:,:,: + 1:终端+ numValidationBkg) = Xbkg (:,:,:, numTrainBkg + 1:结束);YValidation(+ 1:结束+ numValidationBkg) =“背景”

绘制培训和验证集中不同类标签的分布。

身材(“单位”'标准化'“位置”,[0.2 0.2 0.5 0.5])子批次(2,1,1)直方图(YTrain)标题(“培训标签分配”)子批次(2,1,2)直方图(YValidation)标题(“验证标签分发”

定义神经网络架构

创建一个简单的网络架构作为一系列图层。使用卷积和批量归一化层,并将特征映射“空间上”(即,在时间和频率上)使用MAX池层。添加最终最大池层,可以随时间全局汇集输入功能映射。这在输入频谱图中强制(近似)时间转换不变性,允许网络在时间上独立于语音的确切位置执行相同的分类。全球池也显着降低了最终完全连接层中的参数数量。为了减少网络记忆训练数据的特定功能的可能性,将少量丢失添加到最后一个完全连接的图层。

网络很小,因为它只有五个卷积层,滤波器很少。numF控制卷积层中的过滤器数量。若要提高网络的准确性,请尝试通过添加相同的卷积层、批量规范化层和ReLU层块来增加网络深度。也可以尝试通过增加numF

使用加权交叉熵分类损失。权重ClassificationLayer(类权重)创建一个自定义分类层,计算交叉熵损失与观测加权类权重。按照类在中出现的顺序指定类权重类别(YTrain)。要使每个类在损失中的总权重相等,请使用与每个类中的训练示例数成反比的类权重。使用Adam优化器训练网络时,训练算法独立于类权重的整体标准化。

classWeights=1./countcats(YTrain);classWeights=classWeights'/mean(classWeights);numclass=numel(categories(YTrain));timePoolSize=ceil(numHops/8);dropoutProb=0.2;numF=12;layers=[imageInputLayer([numHops numBands])卷积2dlayer(3,numF,“填充”“一样”)BatchnormalizationLayer Ruilulayer MaxPooling2dlayer(3,'走吧'2.“填充”“一样”)卷积2dlayer(3,2 * numf,“填充”“一样”)BatchnormalizationLayer Ruilulayer MaxPooling2dlayer(3,'走吧'2.“填充”“一样”)卷积2层(3,4*numF,“填充”“一样”)BatchnormalizationLayer Ruilulayer MaxPooling2dlayer(3,'走吧'2.“填充”“一样”)卷积2层(3,4*numF,“填充”“一样”)batchNormalizationLayer reluLayer卷积2Dlayer(3,4*numF,“填充”“一样”)batchNormalizationLayer reluLayer MaxPoolg2dLayer([timePoolSize,1])DropOutployer(dropoutProb)fullyConnectedLayer(numClasses)softmaxLayer weightedClassificationLayer(classWeights)];

火车网络

指定训练选项。使用最小批量为128的Adam优化器。训练25个阶段,20个阶段后将学习率降低10倍。

miniBatchSize = 128;validationFrequency =地板(元素个数(YTrain) / miniBatchSize);选择= trainingOptions (“亚当”...“初始学习率”,3e-4,...“MaxEpochs”,25,...“MiniBatchSize”,小批量,...“洗牌”“每个时代”...'plots'“培训进度”...“冗长”错误的...“验证数据”{XValidation, YValidation},...“验证频率”,验证频率,...“LearnRateSchedule”“分段”...“LearnRateDropFactor”,0.1,...“LearnRateDropPeriod”20);

培训网络。如果你没有GPU,那么训练网络可能会花费一些时间。

trainedNet=列车网络(XTrain、YTrain、图层、选项);

评估培训网络

在训练集(无数据扩充)和验证集上计算网络的最终精度。网络在此数据集上非常精确。但是,训练、验证和测试数据都具有类似的分布,不一定反映真实环境。此限制尤其适用于未知的类别,其中只包含少量单词的语句。

如果SDENTATASET LOAD(“commandNet.mat”“训练网”);终止YValPred=分类(trainedNet,XValidation);validationError=平均值(YValPred~=YValidation);YTrainPred=分类(trainedNet,XTrain);trainError=平均值(YTrainPred~=YTrain);disp(“训练错误:”+列车错误*100+“%”)disp(“验证错误:”+验证错误*100+“%”
培训错误:1.907%验证错误:5.5376%

绘制混乱矩阵。使用列和行摘要显示每个类的精度并回忆。对混淆矩阵的类进行排序。最大的混乱是在未知的单词和命令之间,向上的

身材(“单位”'标准化'“位置”,[0.2 0.2 0.5 0.5]);CM = ConfusionChart(YValidation,YVALPRED);cm.title =“验证数据的混淆矩阵”;厘米。ColumnSummary ='列 - 归一化';cm.概述=“行规范化”;SortClasses(cm,[命令,“未知”“背景”])

当对具有诸如移动应用的受限硬件资源的应用程序工作时,考虑可用内存和计算资源的限制。使用千兆字节计算网络的总大小,并在使用CPU时测试其预测速度。预测时间是对单个输入图像进行分类的时间。如果输入,如果将多个图像传输到网络,则可以同时对这些图像进行分类,从而缩短每个图像的预测时间。但是,在对流媒体音频进行分类时,单个图像的预测时间是最相关的。

信息=谁(“训练网”); disp(“网络大小:”+info.bytes/1024+“kB”为了i=1:100 x=randn([numHops,numBands]);tic[yppredicted,probs]=分类(trainedNet,x,“刽子果环境”“cpu”);时间(i)= toc;终止disp(“CPU上的单映像预测时间:”+的意思是(时间(11:结束))* 1000 +“女士”
网络大小:286.7402 kB CPU上的单映像预测时间:2.5119毫秒

参考文献

[1] Warden P.“语音命令:单词语音识别的公共数据集”,2017年。可从https://storage.googleapis.com/download.tensorflow.org/data/speech_commands_v0.01.tar.gz.Google 2017版权所有。语音命令数据集根据Creative Commons Attribute 4.0许可证获得许可,可从以下网址获得:https://creativeCommons.org/licenses/by/4.0/Legalcode.

参考文献

[1] Warden P.“语音命令:单词语音识别的公共数据集”,2017年。可从http://download.tensorflow.org/data/speech_commands_v0.01.tar.gz.Google 2017版权所有。语音命令数据集根据Creative Commons Attribute 4.0许可证获得许可,可从以下网址获得:https://creativeCommons.org/licenses/by/4.0/Legalcode.

也可以看看

||

相关话题