主要内容

音频特征的顺序特征选择

这个例子展示了一个典型的语音数字识别特征选择的工作流程。

在序列特征选择中,你在给定的特征集上训练一个网络,然后递增地添加或删除特征,直到达到最高的精度[1]。在此示例中,您使用自由语音数字数据集将顺序正向选择应用于语音数字识别任务[2]

流式语音数字识别

为了激发示例的积极性,首先加载一个预训练的网络音频特征提取器用于训练网络的对象,以及用于特征的归一化因子。

负载(“网络\u音频\u顺序功能选择.mat”,“最佳网络”,“安全的”,“标准化者”);

创建一个audioDeviceReader从麦克风中读出声音。创建三个异步缓冲器对象:一个用于缓冲从麦克风读取的音频,一个用于缓冲用于语音检测的输入音频的短期能量,一个用于缓冲预测。

fs = afe.SampleRate;deviceReader = audioDeviceReader (“采样器”fs,“SamplesPerFrame”, 256);audioBuffer = dsp.AsyncBuffer (fs * 3);steBuffer = dsp.AsyncBuffer (1000);predictionBuffer = dsp.AsyncBuffer (5);

创建一个绘图以显示流式音频、网络在推理过程中输出的概率以及预测。

无花果=图;streamAxes =次要情节(1,1);streamPlot =情节(0 (fs, 1));ylabel (“振幅”)包含(“时间(s)”)头衔(“音频流”) streamAxes。XTick = (0, fs);streamAxes。XTickLabel = [0, 1];streamAxes。YLim = [1];analyzedAxes =次要情节(3、1、2);analyzedPlot =情节(0 (fs / 2,1));标题(“分析段”) ylabel (“振幅”)包含(“时间(s)”甘氨胆酸)组(,“XTickLabel”,[])analyzedAxes.XTick=[0,fs/2];analyzedAxes.XTickLabel=[0,0.5];analyzedAxes.YLim=[-1,1];probabilityAxes=子批次(3,1,3);probabilityPlot=条形(0:9,0.1*个(1,10));轴([-1,10,0,1])ylabel(“概率”)包含(“阶级”)

执行流式数字识别(数字0到9)20秒。循环运行时,说出其中一个数字并测试其准确性。

首先,定义一个短期能量阈值,在此阈值下假设信号不包含语音。

阈值=0.015;idxVec=1:fs;抽搐toc < 20%从你的设备中读取音频帧。audioIn=deviceReader();将音频写入缓冲区。写入(音频缓冲区、音频输入);%当200毫秒的数据未使用时,继续此循环。audioBuffer。NumUnreadSamples > 0.2 * fs%从音频缓冲区读取1秒。在这一秒中,800毫秒%是重新读取旧数据,200ms是新数据。audioToAnalyze =阅读(audioBuffer, fs, 0.8 * fs);%更新图形以绘制当前音频数据。streamPlot.YData=音频分析;ste=平均值(abs(音频分析));write(steBuffer,ste);如果steBuffer.numreadsamples>5abc=sort(peek(steBuffer));steThreshold=abc(round(0.4*numel(abc));结束如果ste > steThreshold%使用DetectSpeech功能确定语音区域%他在场。idx = detectSpeech (audioToAnalyze, fs);%如果存在语音区域,执行以下操作。如果~ isempty (idx)除语音外,信号的所有部分都调零%区域,并修剪到0.5秒。audioToAnalyze = HelperTrimOrPad (audioToAnalyze (idx (1,1): idx(1、2),fs / 2);使音频正常化。audioToAnalyze=audioToAnalyze/max(abs(audioToAnalyze));%更新分析的分段图analyzedPlot。YData = audioToAnalyze;%提取特征并转置,以便节省时间%跨列。特征=(提取(afe,音频分析));%规范化特征。特征=(特征-normalizers.Mean)。/normalizers.StandardDeviation;%调用classify以确定概率和%获得标签。特征(isnan(特征))=0;[label,probs]=分类(bestNet,特征);%用概率和获胜概率更新情节%的标签。probabilityPlot。YData =聚合氯化铝;写(predictionBuffer,聚合氯化铝);如果predictionBuffer。NumUnreadSamples = = predictionBuffer。lastTen = peek(predictionBuffer);[~,决定]= max(平均(lastTen。*损害(大小(lastTen, 1)), 1));probabilityAxes.Title.String = num2str (decision-1);结束结束其他的%如果信号能量低于阈值,则假设没有语音%检测到。probabilityAxes.Title.String='';probabilityPlot.YData=0.1*1(10,1);analyzedPlot.YData=0(fs/2,1);重置(predictionBuffer)结束drawnow限制结束结束

示例的其余部分说明了流检测中使用的网络是如何训练的,以及馈入网络的特征是如何选择的。

创建培训和验证数据集

下载免费语音数字数据集(FSDD)[2].FSDD由带有语音数字(0-9)的短音频文件组成。

网址="https://zenodo.org/record/1342401/files/Jakobovski/free-spoken-digit-dataset-v1.0.8.zip"; downloadFolder=tempdir;datasetFolder=fullfile(下载文件夹,“FSDD”);如果~存在(datasetFolder“dir”)fprintf('正在下载免费语音数字数据集…\n')解压(url,数据集文件夹)结束

创建一个音频数据存储指向录音得到数据集的抽样率。

广告= audioDatastore (datasetFolder,“IncludeSubfolders”,对);[~,adsInfo]=读取(ads);fs=adsInfo.SampleRate;

文件名的第一个元素是文件中的数字。获取文件名的第一个元素,将其转换为分类,然后设置标签财产音频数据存储

(~,文件名)= cellfun (@ (x) fileparts (x)的广告。文件,“UniformOutput”,假);ads.Labels=categorical(字符串(cellfun(@(x)x(1),文件名));

要将数据存储拆分为开发集和验证集,请使用splitEachLabel.分配80%的数据用于开发,剩余的20%用于验证。

[adsTrain, adsValidation] = splitEachLabel(广告,0.8);

设置音频特征提取器

创建一个音频特征提取器对象在30毫秒窗口内提取音频功能,更新率为10毫秒。将本例中要测试的所有功能设置为真正的

赢得=汉明(圆(0.03 * fs),“定期”);overlapLength =圆(0.02 * fs);afe = audioFeatureExtractor (...“窗口”,赢了,...“OverlapLength”,重叠长度,...“采样器”fs,......“线性光谱”错误的...“梅尔斯波谱”错误的...“barkSpectrum”错误的...“erbSpectrum”错误的......“mfcc”符合事实的...“mfccDelta”符合事实的...“mfccDeltaDelta”符合事实的...“gtcc”符合事实的...“gtccDelta”符合事实的...“gtccDeltaDelta”符合事实的......“spectralCentroid”符合事实的...“spectralCrest”符合事实的...“spectralDecrease”符合事实的...“光谱性”符合事实的...“光谱平坦性”符合事实的...“spectralFlux”符合事实的...“spectralKurtosis”符合事实的...“spectralRolloffPoint”,真的,...“spectralSkewness”符合事实的...“光谱坡”符合事实的...“spectralSpread”符合事实的......“投球”错误的...“harmonicRatio”,假);

定义图层和培训选项

定义深度学习层列表(深度学习工具箱)trainingOptions(深度学习工具箱)在这个例子中使用。第一层,sequenceInputLayer(深度学习工具箱),只是一个占位符。根据在顺序特征选择过程中测试的特征,第一个图层将替换为sequenceInputLayer大小合适的。

核弹=One hundred.;图层=[...sequenceInputLayer(1)BilstLayer(numUnits,“OutputMode”,“最后一次”)fullyConnectedLayer(numel(类别(adsTrain.Labels)))softmaxLayer classificationLayer];选项=培训选项(“亚当”,...“LearnRateSchedule”,“分段”,...“洗牌”,“每个时代”,...“冗长”假的,...“最大时代”,20);

序列特征选择

在顺序特征选择的基本形式中,在给定特征集上训练网络,然后递增地添加或删除特征,直到精度不再提高[1]

正向选择

考虑一个简单的例子,对一组四个特性进行正向选择。在第一个正向选择循环中,通过训练网络独立测试四个特征,并比较它们的验证精度。说明了导致验证精度最高的特征。在第二个正向选择循环中,第一个循环中的最佳特征与每个剩余特征相结合。现在每对特征都用于训练。如果第二个回路的精度没有提高到第一个回路的精度,则选择过程结束。否则,将选择一个新的最佳特性集。前向选择循环继续,直到精确度不再提高。

反向选择

在“反向特征选择”中,首先在包含所有特征的特征集上进行训练,并测试在删除特征时精度是否提高。

运行顺序特征选择

辅助函数(HelperSFS,HelperTrainAndValidateNetwork,HelperTrimOrPad)实现向前或向后顺序特征选择。指定训练数据存储、验证数据存储、音频特征提取器、网络层、网络选项和方向。一般来说,如果您预期的是小的特性集,则选择向前;如果您预期的是大的特性集,则选择向后。

方向=“前进”;[logbook,bestFeatures,bestNet,normalizers]=助手FS(adsTrain,adsValidation,afe,层,选项,方向);
使用“local”配置文件启动并行池(parpool)…连接到并行池(工作人员数量:6)。

这个航海日志输出自辅助特征提取程序是一个包含所有已测试功能配置和相应验证精度的表格。

航海日志
日志=48×2表“mfcc,gtcc“97.333”mfcc,mfcc三角洲,gtcc“97”mfcc,gtcc,“97”mfcc,gtcc,“97”mfcc,gtcc,光谱“97”mfcc,gtcc,“97”mfcc,gtcc,光谱“97”mfcc,gtcc,光谱“97”mfcc,gtcc,“97”mfcc,gtcc,光谱“97”mfcc,“97”mfcc,gtcc,“97”mfcc,“97”mfcc,”mfcc,gtcc,gtcc,“97”mfcc,97”mfcc,“97”mfcc,“97”mfcc,”mfcc,抄抄抄抄抄抄抄抄抄。“97”mfcc,“97”mfcc,“97”mfcc,97”mfcc,“97”mfcc,”mfcc,97”mfcc,“97”mfcc,抄抄抄抄抄抄抄抄抄。“97”mfcc,“97”mfcc,“97”mfcc,“97”mfcc,”mfcc,97”mfcc,“97”mfcc,抄勒克斯“96.667”mfcc、gtcc、光谱衰减点96.667“mfcc,gtcc,光谱亮度”96.667“gtcc,光谱性”96.333“mfcc,gtcc,gtccDelta”96.333“mfcc,gtcc,光谱性荨麻疹”96.333“mfccDelta,gtcc”96“gtcc,gtccDelta”96⋮

这个最佳特征输出自HelperSFS包含将最佳特性设置为的结构体真正的

最佳特征
bestFeatures =结构体字段:mfcc:1 mfccDelta:0 mfccDeltaDelta:0 gtcc:1 gtccDeltaDelta:0 gtccDeltaDelta:0光谱阶跃:0光谱阶跃:0光谱阶跃:0光谱平坦度:0光谱通量:0光谱阶跃:0光谱阶跃:0光谱阶跃:0光谱阶跃:0光谱阶跃:0光谱阶跃:0光谱阶跃:0

你可以设置你的音频特征提取器使用struct。

设置(afe,最佳功能)afe
afe = audioFeatureExtractor with properties: properties Window: [240×1 double] OverlapLength: 160 SampleRate: 8000 FFTLength: [] SpectralDescriptorInput:'linearSpectrum' Enabled Features mfcc, gtcc Disabled Features linearSpectrum, melSpectrum, barkSpectrum, erbSpectrum, mfccDelta, mfccDeltaDelta gtccDelta, gtccDeltaDelta,频谱质心,频谱crest,频谱减少,频谱熵,频谱平直度,频谱通量,频谱峰度,频谱rolloffpoint,频谱偏斜度,要提取一个特征,将其属性设置为true。例如,obj。MFCC = true,将MFCC添加到已启用特性列表中。

HelperSFS并输出性能最佳的网络和与所选特征对应的归一化因子。保存已配置的网络音频特征提取器,和归一化因子,取消注释这一行:

%保存('network\u Audio\u SequentialFeatureSelection.mat'、'bestNet'、'afe'、'normalizers')

结论

这个例子说明了递归神经网络(LSTM或BiLSTM)的顺序特征选择的工作流。它可以很容易地适应CNN和RNN-CNN的工作流程。

万博1manbetx支持功能

HelperTrainAndValidateNetwork

函数[trueLabels predictedLabels,净,标准化者]= HelperTrainAndValidateNetwork (adsTrain、adsValidation afe,层,选项)%培训和验证网络。%%投入:%adsTrain—指向训练集的音频数据存储对象% adsValidation - audioDatastore对象,指向验证集% afe - audioFeatureExtractor对象。% layers - LSTM或BiLSTM网络的层数% options - trainingOptions对象%%产出:%trueLabels-验证集的真实标签%predictedLabels-验证集的预测标签% net -训练的网络%规格化器-测试特征的规格化因子%版权归MathWorks公司所有。%将数据转换为高数组。tallTrain=高(adsTrain);tallValidation=高(adsValidation);%从训练集中提取特征。重新定位特征,以便%时间是沿着行与sequenceInputLayer兼容的。fs = afe.SampleRate;tallTrain = cellfun (@ (x) HelperTrimOrPad (x, fs / 2) tallTrain,“统一输出”,假);tallTrain=cellfun(@(x)x/max(abs(x))[],“所有”),塔勒列,“统一输出”,假);TallFeatureRain=cellfun(@(x)提取物(afe,x),tallTrain,“统一输出”、假);tallFeaturesTrain = cellfun (@ (x) x ', tallFeaturesTrain,“统一输出”、假);% #好< NASGU >[~, featuresTrain] = evalc (“聚集(TallFeatureRain)”);%使用evalc抑制命令行输出。tallValidation = cellfun (@ (x) HelperTrimOrPad (x, fs / 2) tallValidation,“统一输出”,false);tallValidation=cellfun(@(x)x/max(abs(x),[],“所有”)、tallValidation“统一输出”,false);tallFeaturesValidation=cellfun(@(x)提取物(afe,x),tallValidation,“统一输出”,假);tallFeaturesValidation=cellfun(@(x)x',tallFeaturesValidation,“统一输出”、假);% #好< NASGU >[~, featuresValidation] = evalc (“收集(tallFeaturesValidation)”);%使用evalc抑制命令行输出。%使用训练集来确定每种方法的平均值和标准偏差%特色。规范化培训和验证集。allFeatures =猫(2,featuresTrain {:});M =意味着(allFeatures 2“omitnan”);S=标准(所有特征,0,2,“omitnan”);featuresTrain=cellfun(@(x)(x-M)。/S,featuresTrain,“UniformOutput”、假);ii=1:numel(featuresTrain)idx=find(isnan(featuresTrain{ii}));如果~isempty(idx)特征菌株{ii}(idx)=0;结束结束featuresValidation = cellfun (@ (x)(即x m)。/ S, featuresValidation,“UniformOutput”、假);ii = 1:numel(featuresValidation) idx = find(isnan(featuresValidation{ii}));如果~isempty(idx)特征验证{ii}(idx)=0;结束结束%复制序列和验证集的标签,使其处于%与序列一一对应。labelsTrain=adsTrain.Labels;%为测试中的特征数量更新输入层。层(1)=sequenceInputLayer(大小(特征应变{1},1));%培训网络。网= trainNetwork (featuresTrain、labelsTrain层,选择);%评估网络。调用classify以获取每个网络的预测标签%的序列。predictedLabels=classify(net,featuresValidation);trueLabels=adsValidation.Labels;%将规范化因子另存为结构。标准化器。平均值=M;标准化器。标准偏差=S;结束

HelperSFS

函数(日志,bestFeatures bestNet bestNormalizers] = HelperSFS (adsTrain、adsValidate afeThis,层,选择,方向)%%投入:%adsTrain—指向训练集的音频数据存储对象% adsValidate -指向验证集的audioDatastore对象% afe - audioFeatureExtractor对象。设置所有功能测试为真% layers - LSTM或BiLSTM网络的层数% options - trainingOptions对象% direction - SFS方向,指定为“forward”或“backward”%%产出:%日志-包含已测试功能配置和相应验证精度的表格% bestFeatures -包含最佳特性配置的结构体%bestNet-具有最高验证精度的经过培训的网络%最佳标准化器-最佳特征的特征标准化因子%版权归MathWorks公司所有。afe = (afeThis)复印件;featuresToTest =字段名(信息(afe));N =元素个数(featuresToTest);bestValidationAccuracy = 0;%设置初始功能配置:全部启用以进行反向选择%或全部关闭以进行正向选择。featureConfig = info (afe);i = 1: N如果strcmpi(方向,“向后”)featureConfig.(featuresToTest{i})=真;其他的featureConfig。(featuresToTest{我})= false;结束结束%初始化日志,以跟踪特征配置和准确性。日志=表格(功能配置,0,“VariableNames”,[“功能配置”,“准确性”]);%执行顺序特征评估。wrapperIdx = 1;bestAccuracy = 0;wrapperIdx<=N%创建包含所有要测试的功能配置的单元阵列%在当前循环中。featureConfigsToTest =细胞(元素个数(featuresToTest), 1);ii=1:numel(特性测试)如果strcmpi(方向,“向后”)featureConfig.(featuresToTest{ii})=false;其他的featureConfig。(featuresToTest {2}) = true;结束featureConfigsToTest {2} = featureConfig;如果strcmpi(方向,“向后”) featureConfig.(featuresToTest{ii}) = true;其他的featureConfig.(featuresToTest{ii})=false;结束结束%在每个功能集上循环。ii=1:numel(特性配置测试)%确定要测试的当前功能配置。更新%这部电影的特色是afe。currentConfig=featureConfigsToTest{ii};set(afe,currentConfig)%培训并获得当前k倍交叉验证精度%功能配置。[trueLabels predictedLabels,净,标准化者]= HelperTrainAndValidateNetwork (adsTrain、adsValidate afe,层,选项);valAccuracy =意味着(trueLabels = = predictedLabels) * 100;如果bestValidationAccuracy = valAccuracy;bestNet =净;bestNormalizers =标准化者;结束%更新日志结果=表(currentConfig valAccuracy,“VariableNames”,[“功能配置”,“准确性”]);日志=[日志;结果];% #好< AGROW >结束%以最佳精度确定并打印设置。如果%没有提高,结束跑。[a, b] = max(日志{:,“准确性”});如果a <= bestAccuracy wrapperIdx = inf;其他的wrapperIdx=wrapperIdx+1;结束最佳精度=a;%根据最近的获胜者更新要测试的功能。赢家=日志{b,“功能配置”};fn=字段名(获胜者);tf=structfun(@(x)(x),获胜者);如果strcmpi(方向,“向后”)featuresToRemove=fn(~tf);其他的featuresToRemove=fn(tf);结束ii=1:numel(featuresToRemove)loc=strcmp(featuresToTest,featuresToRemove{ii});featuresToTest(loc)=[];如果strcmpi(方向,“向后”) featureConfig.(featuresToRemove{ii}) = false;其他的featureConfig.(featuresToRemove{ii})=真;结束结束结束%对日志进行排序,使其更具可读性。:日志(1)= [];%删除第一行占位符。日志= sortrows(日志,{“准确性”},{“下降”}); 最佳功能=日志{1,“功能配置”};m=日志{:,“功能配置”}; fn=字段名(m);myString=strings(numel(m),1);wrapperIdx = 1:num (m) tf = structfun(@(x)(x),logbook{wrapperIdx,“功能配置”});myString (wrapperIdx) = strjoin (fn (tf),", ");结束日志=表(myString,日志{:,“准确性”},“VariableNames”,[“特征”,“准确性”]);结束

HelperTrimOrPad

函数y = HelperTrimOrPad (x, n)% y = HelperTrimOrPad(x,n)修剪或填充输入x到n个样本。如果x是%修剪,前后修剪均匀。如果x被填充,它就是%在前面和后面用0填充。对于奇数长度的修剪或%填充,额外的样品从后面修剪或填充。%版权归MathWorks公司所有。a=尺寸(x,1);如果a埃尔塞夫a > n frontTrim = floor((a-n)/2)+1;backTrim = a - n - frontTrim;y = x (frontTrim: end-backTrim);其他的y=x;结束结束

工具书类

[1] Jain,A.和D.Zongker。“特征选择:评估、应用和小样本性能”,《模式分析和机器智能IEEE交易》。第19卷,第2期,1997年,第153-158页。

[2] 雅科博夫斯基。“Jakobovski/自由语音数字数据集”,GitHub,2019年5月30日。https://github.com/Jakobovski/free-spoken-digit-dataset.