主要内容

音频特征的顺序特征选择

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

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

流语音数字识别

为了激发这个例子,首先加载一个预先训练过的网络audioFeatureExtractor(音频工具箱)对象用于训练网络,并对特征进行归一化因子。

负载(“network_Audio_SequentialFeatureSelection.mat”“bestNet”“安全的”“标准化者”);

创建一个audioDeviceReader(音频工具箱)从麦克风中读出声音。创建三个dsp。AsyncBuffer(DSP系统工具箱)对象:一个用于缓冲从麦克风读取的音频,一个用于缓冲用于语音检测的输入音频的短期能量,一个用于缓冲预测。

fs = afe.SampleRate;deviceReader = audioDeviceReader (“SampleRate”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];probabilityAxes =情节(3、1,3);probabilityPlot =酒吧(0:9,0.1 * (10));轴([1,10,0,1])ylabel (“概率”)包含(“类”

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

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

steThreshold = 0.015;idxVec = 1: fs;抽搐toc < 20%从你的设备中读取音频帧。audioIn = deviceReader ();将音频写入缓冲区。写(audioBuffer audioIn);%当200毫秒的数据未使用时,继续此循环。audioBuffer。NumUnreadSamples > 0.2 * fs%从音频缓冲区读取1秒。这一秒的800毫秒%是重新读取旧数据,200ms是新数据。audioToAnalyze =阅读(audioBuffer, fs, 0.8 * fs);%更新图表以绘制当前的音频数据。streamPlot。YData = audioToAnalyze;ste =意味着(abs (audioToAnalyze));写(steBuffer, ste);如果steBuffer。NumUnreadSamples > 5 abc = sort(peek(steBuffer));steThreshold = abc(圆(0.4 *元素个数(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 audioToAnalyze) ';使特性正常化。feature = (features - normalizer . mean) ./ normalizer . standarddeviation;%调用分类以确定概率和%获得标签。特性(isnan(特性))= 0;(标签,聚合氯化铝)= (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 (1);analyzedPlot。YData = 0 (f / 2、1);重置(predictionBuffer)结束drawnowlimitrate结束结束

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

创建培训和验证数据集

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

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

创建一个audioDatastore(音频工具箱)指向录音得到数据集的抽样率。

广告= audioDatastore (datasetFolder,“IncludeSubfolders”,真正的);[~, adsInfo] =阅读(广告);fs = adsInfo.SampleRate;

文件名的第一个元素是文件中所说的数字。获取文件名的第一个元素,将它们转换为分类,然后设置标签财产的audioDatastore

(~,文件名)= cellfun (@ (x) fileparts (x)的广告。文件,“UniformOutput”、假);ads.Labels =分类(string (cellfun (@ (x) x(1),文件名)));

若要将数据存储划分为开发集和验证集,请使用splitEachLabel(音频工具箱).分配80%的数据用于开发,剩余20%用于验证。

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

设置音频特征提取器

创建一个audioFeatureExtractor(音频工具箱)对象提取音频特征超过30毫秒的Windows与10毫秒的更新率。将本例中要测试的所有特性设置为真正的

赢得=汉明(圆(0.03 * fs),“周期”);overlapLength =圆(0.02 * fs);afe = audioFeatureExtractor (...“窗口”,赢了,...“OverlapLength”overlapLength,...“SampleRate”fs,......“linearSpectrum”假的,...“melSpectrum”假的,...“barkSpectrum”假的,...“erbSpectrum”假的,......“mfcc”,真的,...“mfccDelta”,真的,...“mfccDeltaDelta”,真的,...“gtcc”,真的,...“gtccDelta”,真的,...“gtccDeltaDelta”,真的,......“spectralCentroid”,真的,...“spectralCrest”,真的,...“spectralDecrease”,真的,...“spectralEntropy”,真的,...“spectralFlatness”,真的,...“spectralFlux”,真的,...“spectralKurtosis”,真的,...“spectralRolloffPoint”,真的,...“spectralSkewness”,真的,...“spectralSlope”,真的,...“spectralSpread”,真的,......“节”假的,...“harmonicRatio”、假);

定义图层和培训选项

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

numUnits =One hundred.;层= [...sequenceInputLayer (1) bilstmLayer (numUnits“OutputMode”“最后一次”) full connectedlayer (numel(categories(adsTrain.Labels))) softmaxLayer classificationLayer];选择= trainingOptions (“亚当”...“LearnRateSchedule”“分段”...“洗牌”“every-epoch”...“详细”假的,...“MaxEpochs”, 20);

连续的特征选择

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

提出了选择

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

逆向选择

在向后特征选择中,首先在包含所有特征的特征集上进行训练,并测试在删除特征时准确性是否会提高。

运行顺序特征选择

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

方向=“前进”;(日志,bestFeatures bestNet标准化者]= HelperSFS (adsTrain、adsValidation afe,层,选择,方向);
使用“local”配置文件启动并行池(parpool)…连接到并行池(工作人员数量:6)。

日志输出HelperFeatureExtractor是一个包含所有测试的特性配置和相应验证精度的表。

日志
日志=48×2表功能精度__________________________________ ________ "mfcc, gtcc" 97.333 "mfcc, mfccDelta, gtcc" 97 "mfcc, gtcc,频谱熵" 97 "mfcc, gtcc,频谱平坦度" 97 "mfcc, gtcc, spectralFlux" 97 "mfcc, gtcc, spectralSpread" 97 "gtcc" 96.667 "gtcc, spectralFlux" 96.667 "mfcc, gtcc,mfcc, gtcc, spectrum rolloffpoint“96.667”mfcc, gtcc, spectrum skewness“96.667”gtcc, spectrum entropy“96.333”mfcc, gtcc, gtccDeltaDelta“96.333”mfcc, gtcc, spectrum kurtosis“96.333”mfccDelta, gtcc“96”gtcc, gtccDelta“96⋮

bestFeatures输出HelperSFS包含将最佳特性设置为的结构体真正的

bestFeatures
bestFeatures =结构体字段:mfcc: 1 mfccDelta: 0 mfccDeltaDelta: 0 gtcc: 1 gtccDelta: 0 gtccDeltaDelta: 0 spectralCentroid: 0 spectralCrest: 0 spectralDecrease: 0 spectralEntropy: 0 spectralFlatness: 0 spectralFlux: 0 spectralKurtosis: 0 spectralRolloffPoint: 0 spectralSkewness: 0 spectralSlope: 0 spectralSpread: 0

你可以设置audioFeatureExtractor使用结构体。

安全设置(afe bestFeatures)
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并输出性能最佳的网络和与所选特征对应的归一化因子。保存已配置的网络audioFeatureExtractor,和归一化因子,取消注释这一行:

%保存(“network_Audio_SequentialFeatureSelection.mat”、“bestNet”,“安全的”,“标准化者”)

结论

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

金宝app支持功能

HelperTrainAndValidateNetwork

函数[trueLabels predictedLabels,净,标准化者]= HelperTrainAndValidateNetwork (adsTrain、adsValidation afe,层,选项)%培训和验证网络。%的输入:% adsTrain -指向训练集的audioDatastore对象% adsValidation - audioDatastore对象,指向验证集% afe - audioFeatureExtractor对象。% layers - LSTM或BiLSTM网络的层数% options - trainingOptions对象%输出:% true标签-验证集的真标签% predictedLabels -验证集的预测标签% net -训练的网络正规化因子-被测特性的正规化因子版权所有2019 The MathWorks, Inc.%将数据转换为高数组。tallTrain =高(adsTrain);tallValidation =高(adsValidation);%从训练集中提取特征。重新定位功能,以便% time沿着行与sequenceInputLayer兼容。fs = afe.SampleRate;tallTrain = cellfun (@ (x) HelperTrimOrPad (x, fs / 2) tallTrain,“UniformOutput”、假);tallTrain = cellfun (@ x (x) / max (abs (x)、[]“所有”)、tallTrain“UniformOutput”、假);tallFeaturesTrain = cellfun (@ (x)提取(afe x), tallTrain,“UniformOutput”、假);tallFeaturesTrain = cellfun (@ (x) x ', tallFeaturesTrain,“UniformOutput”、假);% #好< NASGU >[~, featuresTrain] = evalc (“收集(tallFeaturesTrain)”);%使用evalc抑制命令行输出。tallValidation = cellfun (@ (x) HelperTrimOrPad (x, fs / 2) tallValidation,“UniformOutput”、假);tallValidation = cellfun (@ x (x) / max (abs (x)、[]“所有”)、tallValidation“UniformOutput”、假);tallFeaturesValidation = cellfun (@ (x)提取(afe x), tallValidation,“UniformOutput”、假);tallFeaturesValidation = cellfun (@ (x) x ', tallFeaturesValidation,“UniformOutput”、假);% #好< NASGU >[~, featuresValidation] = evalc (“收集(tallFeaturesValidation)”);%使用evalc抑制命令行输出。%使用训练集确定每个的平均值和标准偏差%的特性。将训练和验证集规范化。allFeatures =猫(2,featuresTrain {:});M =意味着(allFeatures 2“omitnan”);S =性病(allFeatures 0 2,“omitnan”);featuresTrain = cellfun (@ (x)(即x m)。/ S, featuresTrain,“UniformOutput”、假);ii = 1:numel(featuresTrain) idx = find(isnan(featuresTrain{ii}));如果~isempty(idx) featuresTrain{ii}(idx) = 0;结束结束featuresValidation = cellfun (@ (x)(即x m)。/ S, featuresValidation,“UniformOutput”、假);ii = 1:numel(featuresValidation) idx = find(isnan(featuresValidation{ii}));如果~isempty(idx) featuresValidation{ii}(idx) = 0;结束结束%复制列车和验证集的标签,以便它们在%与序列一一对应。labelsTrain = adsTrain.Labels;%更新输入层的测试特性的数量。层(1)= sequenceInputLayer(大小(featuresTrain {1}, 1));%培训网络。网= trainNetwork (featuresTrain、labelsTrain层,选择);%评估网络。调用classify以获得每个的预测标签%的序列。predictedLabels =分类(净,featuresValidation);trueLabels = adsValidation.Labels;%将标准化因子保存为结构体。标准化者。意味着= M;标准化者。StandardDeviation = S;结束

HelperSFS

函数(日志,bestFeatures bestNet bestNormalizers] = HelperSFS (adsTrain、adsValidate afeThis,层,选择,方向)%的输入:% adsTrain -指向训练集的audioDatastore对象% adsValidate -指向验证集的audioDatastore对象% afe - audioFeatureExtractor对象。设置所有功能测试为真% layers - LSTM或BiLSTM网络的层数% options - trainingOptions对象% direction - SFS方向,指定为“forward”或“backward”%输出:%日志-包含测试特性配置和相应验证精度的表% bestFeatures -包含最佳特性配置的结构体% bestNet -训练有素的网络,具有最高的验证精度% bestnormalizer -最佳特征的特征归一化因子版权所有2019 The MathWorks, Inc.afe = (afeThis)复印件;featuresToTest =字段名(信息(afe));N =元素个数(featuresToTest);bestValidationAccuracy = 0;设置初始特性配置:开启向后选择%或全部关闭向前选择。featureConfig = info (afe);i = 1: N如果strcmpi(方向,“落后”) featureConfig.(featuresToTest{i}) = true;其他的featureConfig。(featuresToTest{我})= false;结束结束%初始化日志,以跟踪特征配置和准确性。日志=表(featureConfig 0“VariableNames”,[“功能配置”“准确性”]);执行顺序特征评估。wrapperIdx = 1;bestAccuracy = 0;wrapperIdx < = N创建包含要测试的所有功能配置的单元格数组在当前循环中。featureConfigsToTest =细胞(元素个数(featuresToTest), 1);2 = 1:元素个数(featuresToTest)如果strcmpi(方向,“落后”) featureConfig.(featuresToTest{ii}) = false;其他的featureConfig。(featuresToTest {2}) = true;结束featureConfigsToTest {2} = featureConfig;如果strcmpi(方向,“落后”) featureConfig.(featuresToTest{ii}) = true;其他的featureConfig。(featuresToTest {2}) = false;结束结束%循环每个特性集。2 = 1:元素个数(featureConfigsToTest)确定当前要测试的特性配置。更新%该功能安全。currentConfig = featureConfigsToTest {2};currentConfig集(afe)%培训并获得当前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;结束bestAccuracy =一个;%根据最近的胜出者更新待测试的功能。赢家=日志{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 {2}) = true;结束结束结束%对日志进行排序,使其更具可读性。:日志(1)= [];%删除第一行占位符。日志= sortrows(日志,{“准确性”}, {“下”});bestFeatures =日志{1,“功能配置”};m =日志{:,“功能配置”};fn =字段名(m);myString =字符串(元素个数(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填充。对于奇数长度的修剪或%填充,额外的样品从后面修剪或填充。版权所有2019 The MathWorks, Inc.一个=大小(x, 1);如果a < n frontPad = floor((n-a)/2);backPad = n - a - frontPad;(y = 0 (frontPad 1); x; 0(挤压垫,1)];elseifa > n frontTrim = floor((a-n)/2)+1;backTrim = a - n - frontTrim;y = x (frontTrim: end-backTrim);其他的y = x;结束结束

参考文献

Jain A.和D. Zongker。《特征选择:评估、应用和小样本性能》模式分析与机器智能学报。1997年第19卷第2期153-158页。

[2] Jakobovski。“Jakobovski / Free-Spoken-Digit-Dataset。”GitHub, 2019年5月30日。https://github.com/Jakobovski/free-spoken-digit-dataset。