主要内容

语音情感识别

该示例说明了使用Bilstm网络的简单语音情感识别(SER)系统。您首先下载数据集,然后在各个文件上测试培训的网络。网络培训了小德语数据库[1]

该示例将引导您对网络进行培训,其中包括下载、扩充和培训数据集。最后,执行遗漏一个扬声器(LOSO) 10倍交叉验证以评估网络体系结构。

本例中使用的特征是使用顺序特征选择来选择的,类似于音频特征的顺序特征选择(音频工具箱)

下载数据集

下载情感语音的柏林数据库[1].该数据库包含10名演员所说的535句话,旨在表达以下情绪之一:愤怒、无聊、厌恶、焦虑/恐惧、幸福、悲伤或中性。这些情绪与文本无关。

URL =.“http://emodb.bilderbar.info/download/download.zip”;downloadFolder = tempdir;datasetFolder = fullfile (downloadFolder,“EMO-DB”);如果~exist(datasetFolder,“dir”)DISP(“下载Emo-DB (40.5 MB)……”解压缩(url, datasetFolder)结尾

创建一个audioDatastore(音频工具箱)指向音频文件。

广告= audioDatastore (fullfile (datasetFolder,“wav”));

文件名是表示说话人ID、所说文本、情感和版本的代码。网站包含用于解释代码的键以及有关说话人的其他信息,如性别和年龄。创建一个包含变量的表演讲者强烈的感情。将文件名解码到表中。

filepaths = ads.Files;emotionCodes = cellfun (@ (x) x(录得5个),filepaths,“UniformOutput”、假);情绪=替换(emotionCodes,{'W'“L”'e'“A”'F'“T”“N”},...“愤怒”'无聊''厌恶'焦虑/恐惧''幸福''悲伤'“中立”});speakerCodes = cellfun (@ (x) x (end-10: end-9) filepaths,“UniformOutput”、假);labelTable = cell2table (speakerCodes,情感,“变化无常”,{“议长”“情感”});Labeltable.emotion =分类(Labeltable.eMotion);labeltable.speaker = patporical(labeltable.speaker);摘要(柔软的)
变量:讲话者:535×1分类价值:03 49 08 58 09 43 10 38 11 55 12 35 13 61 14 69 15 56 16 71情绪:535×1分类价值:愤怒127焦虑/恐惧69无聊81厌恶46幸福71中性79悲伤62

labelTable与中的文件顺序相同audioDatastore.设置标签财产的audioDatastore到了labelTable

Ads.Labels = Labeltable;

执行语音情感识别

下载并加载预训练网络audioFeatureExtractor(音频工具箱)用于培训网络的对象,以及特征的标准化因子。除扬声器之外的数据集中的所有扬声器培训此网络03

URL =.“http://ssd.mathworks.com/金宝appsupportfiles/audio/SpeechEmotionRecognition.zip”;downloadNetFolder=tempdir;netFolder=fullfile(downloadNetFolder,“SpeechEmotionRecognition”);如果〜存在(netFolder,“dir”)DISP('下载掠夺网络(1档 -  1.5 MB)......')解压缩(url,下载NetFolder)结尾加载(完整文件)(netFolder,“网络音频服务器垫”));

上设置的采样率audioFeatureExtractor对应于数据集的采样率。

fs=afe采样器;

选择扬声器和情绪,然后将数据存储区集中仅包含所选的扬声器和情感。从数据存储读取并收听文件。

演讲者=分类( “03”);情绪=绝对(“厌恶”);ADSSUBSET =子集(广告,ADS.LABELS.SPEAKER ==扬声器&ADS.LABELS.emotion ==情绪);AUDIO =读取(ADSSUBSET);声音(音频,FS)

使用audioFeatureExtractor对象,提取特征,然后转置它们,使时间沿着行。对特征进行归一化,然后将其转换为20个元素序列,10个元素重叠,对应约600ms窗口,300ms重叠。使用支持功能,金宝appHelperFeatureVector2序列,将特征向量阵列转换为序列。

特征=(提取物(AFE,音频))';featuresNormalized =(功能 -  normalizers.Mean)./ normalizers.StandardDeviation;numOverlap =10;featureSequences = HelperFeatureVector2Sequence (featuresNormalized 20 numOverlap);

将特征序列馈送到网络中以进行预测。计算平均预测,并将所选情绪的概率分布绘制为饼图。您可以尝试不同的扬声器,情绪,序列重叠和预测平均值以测试网络的性能。为了获得网络性能的现实近似,请使用扬声器03,该网络是没有受过训练上。

YPred=双倍(预测(净,特征序列));平均值=“模式”转换平均案件'意思'probs =平均值(YPred,1);案件“中位数”probs =中间值(YPred,1);案件“模式”probs =模式(YPred,1);结尾派(probs. /笔(聚合氯化铝),字符串(net.Layers(结束). class))

该示例的其余部分说明了网络是如何训练和验证。

列车网络的

由于训练数据不足,首次尝试训练的10倍交叉验证准确率约为60%。在数据不足的情况下训练的模型过度拟合某些折叠,而不足拟合其他折叠。为了提高整体拟合,请使用音频数据增强器(音频工具箱).每个文件50个扩充凭经验选择作为处理时间和精度的提高之间的良好折衷。你可以减少扩充数量,加快例子。

创建一个音频数据增强器对象。设定施加距离移位的概率0.5并使用默认范围。设置应用时移的概率为1并使用一系列[-0.3, 0.3]秒。设定的附加噪声的概率1并指定信噪比范围为[-20,40]D b。

numauginations =50;增量= audioDataAugmenter ('numauginations',裸体,...“TimeStretchProbability”,0,...'VolumeControlProbability',0,......“变桨可能性”,0.5,......“时移概率”,1,...'TimeShiftRange'[-0.3, 0.3],......“AddNoiseProbability”,1,...'SNRRange',[-20,40]);

在当前文件夹创建一个新的文件夹来保存增强数据集。

currentDir=pwd;writeDirectory=fullfile(currentDir,'augmenteddata');mkdir(writeDirectory)

对于音频数据存储的每个文件:

  1. 创建50个增强。

  2. 规范化音频具有1的最大绝对值。

  3. 将增强音频数据写入WAV文件。附加_augK每个文件名,其中的K是扩充数。若要加快处理速度,请使用parfor并分区数据存储。

这种扩充数据库的方法非常耗时(大约1小时)和占用空间(大约26 GB)。然而,当迭代选择网络架构或特征提取管道时,这种前期成本通常是有利的。

n = numel(ads.files)* numauginations;mywaitbar = helperpoolwaitbar(n,“增加数据集……”);reset(ads) numPartitions = 18;抽搐parforII = 1:numPartitions adsPart =分区(广告,numPartitions,ⅱ);尽管hasdata(Adspart)[x,AdsInfo] =读取(Adspart);数据=增强(增强器,X,FS);[〜,fn] = fileparts(adsinfo.filename);i=1:size(data,1)augmentedAudio=data.Audio{i};augmentedAudio=augmentedAudio/max(abs(augmentedAudio),[],'全部');augNum = num2str(ⅰ);如果numel(augNum)==1 iString=[' 0 ',奥努姆];别的istring =奥努姆;结尾audiowrite (fullfile (writeDirectory sprintf (“%s_八月%s.wav”,FN,iString)),augmentedAudio,FS);增量(myWaitBar)结尾结尾结尾
开始使用“本地”轮廓平行池(parpool)......连接到并行池(工号:6)。
删除(myWaitBar)流('扩充完成(%0.2f分钟)。\n'toc / 60)
完整的增强(6.28mg分钟)。

创建一个指向增强数据集的音频数据存储。复制原始数据存储的标签表的行NumAugmentations确定增强数据存储的标签的时间。

adsAug = audioDatastore (writeDirectory);adsAug。标签= repelem(ads.Labels,augmenter.NumAugmentations,1);

创建一个audioFeatureExtractor(音频工具箱)对象。集到30毫秒的周期性汉明窗口,overtaplenth0, 和取样频率到数据库的采样率。集gtccGTCCDeltamfccDelta, 和光谱休息符合事实的提取它们。集SpectralDescriptorInput.熔化光谱所以这样光谱休息计算用于梅尔频谱。

win=hamming(一轮(0.03*fs),“周期”);overlapLength = 0;afe = audioFeatureExtractor (...'窗户',赢,...“重叠长度”overlapLength,...'采样率',fs,......'GTCC'符合事实的...'gtccDelta'符合事实的...“mfccDelta”符合事实的......“SpectralDescriptorInput”“melSpectrum”...'spectralCrest',对);

部署训练

培训用于部署时,使用数据集中的所有可用扬声器。将训练数据存储设置为增强数据存储。

adsTrain=adsAug;

将训练音频数据存储转换为一个高数组。如果您有Parallel Computing Toolbox™,提取将自动并行化。如果没有“并行计算工具箱”,代码将继续运行。

塔塔特拉特=高(adstrain);

提取训练特征并重新确定特征的方向,以便时间沿行与序列输入层

featuresTallTrain = cellfun (@ (x)提取(afe x), tallTrain,“UniformOutput”、假);featureStalltrain = Cellfun(@(x)x',featustalltrain,“UniformOutput”,false);featuresTrain=聚集(featuresTallTrain);
使用并行池“本地”评估高表达: - 通行证1:1分钟内完成7秒评估,在1分7秒内完成

使用训练集来确定每个功能的平均值和标准偏差。

allFeatures =猫(2,featuresTrain {:});M =平均(allFeatures,2,“奥米南”);S=标准(所有特征,0,2,“奥米南”);FeatureStrain = Cellfun(@(x)(x-m)./ s,featureastrain,“UniformOutput”、假);

将特征向量缓冲成序列,使每个序列由20个特征向量和10个特征向量重叠组成。

featureVectorsPerSequence = 20;featureVectorOverlap = 10;[sequencesTrain,sequencePerFileTrain] = HelperFeatureVector2Sequence(featuresTrain,featureVectorsPerSequence,featureVectorOverlap);

复制的训练和验证集的标签,使它们在一到一一对应的序列。不是所有扬声器对所有的情绪言论。创建一个空分类包含所有情感类别的数组,并将其附加到验证标签,以便类别数组包含所有情感。

labelsTrain = repelem(adsTrain.Labels.Emotion,[sequencePerFileTrain {:}]);emptyEmotions = ads.Labels.Emotion;emptyEmotions(:) = [];

使用定义BiLSTM网络双层膜.放置A.落花人前后双层膜为了帮助防止过度拟合。

dropoutProb1 = 0.3;numUnits = 200;dropoutProb2 = 0.6;层= [...sequenceInputLayer(大小(sequencesTrain {1}, 1)) dropoutLayer dropoutProb1 bilstmLayer (numUnits,“输出模式”“最后的”)dropoutLayer(dropoutProb2)fullyConnectedLayer(numel(类别(emptyEmotions)))softmaxLayer classificationLayer];

使用以下方法确定培训选项培训选项

minibatchsize = 512;initiallearnrate = 0.005;学习ropperiod = 2;maxepochs = 3;选项=培训选项(“亚当”...“MiniBatchSize”,小匹马,...“initiallearnrate”,initialLearnRate,...“LearnRateDropPeriod”,learnRateDropPeriod,...“LearnRateSchedule”“分段”...“maxepochs”,maxEpochs,...“洗牌”“每个时代”...“详细”错误的...“阴谋”“培训 - 进展”);

使用培训网络trainNetwork

净= trainNetwork(sequencesTrain,labelsTrain,层,选项);

要保存网络,请配置audioFeatureExtractor,和标准化因素,设置saveSERSystem符合事实的

saveSERSystem =错误的如果SaveserSystem Inclanizers.mean = m;Inclandizers.StandardDeviation = S;节省(“网络音频服务器垫”“净”“afe”“正规化”结尾

系统验证培训

要对您在本例中创建的模型提供准确的评估,请使用“遗漏一个发言人”(LOSO)进行培训和验证k倍交叉验证。在这种方法中,你训练使用 k - 1 扬声器,然后对省略的扬声器进行验证。重复这个步骤k次。最终验证精度为k褶皱。

创建一个包含扬声器ID的变量。确定折叠的数量:1为每个扬声器。该数据库包含来自10个独特的扬声器发声。用概括显示说话人id(左列)和他们贡献到数据库的话语数量(右列)。

演讲者= ads.Labels.Speaker;numFolds =元素个数(扬声器);总结(扬声器)
03 49 08 58 09 43 10 38 11 55 12 35 13 61 14 69 15 56 16 71

辅助功能HelperTrainAndValidateNetwork对所有10次折叠执行上述步骤,并为每个折叠返回真实的和预测的标签。调用HelperTrainAndValidateNetworkaudioDatastore,增强audioDatastore,而且audioFeatureExtractor

[labelsTrue,labelsPred] = HelperTrainAndValidateNetwork(广告,adsAug,AFE);

打印每折叠的准确性,并绘制10倍的混淆图。

ii=1:numel(labelsTrue)Foldac=平均值(labelsTrue{ii}==labelsPred{ii})*100;fprintf('折叠%1.0f,精度= %0.1f\n'第二,foldAcc);结尾
折叠1,精度=73.5折叠2,精度=77.6折叠3,精度=74.4折叠4,精度=68.4折叠5,精度=76.4折叠6,精度=80.0折叠7,精度=73.8折叠8,精度=87.0折叠9,精度=69.6折叠10,精度=70.4
labelstruemat = cat(1,labelstrue {:});labelspredmat = cat(1,labelspred {:});图cm = confusionchart(labelstruemat,labelspredmat);valaccuracy =均值(labelstruemat == labelspredmat)* 100;cm.title = sprintf('混淆矩阵为10倍交叉验证\ naverage精度=%0.1f', valAccuracy);sortClasses(厘米、类别(emptyEmotions))厘米。ColumnSummary =“column-normalized”;cm.RowSummary =“row-normalized”

金宝app辅助功能

将特征向量数组转换为序列

功能[序列,序列perfile] = HelperFeatureVector2序列(功能,FeatureVectorsPersequence,FeatureVectoroverlap)%版权所有2019 MathWorks公司如果featurevectorspersequence <= featurevectoroverlap错误(重叠特征向量的数量必须小于每个序列的特征向量的数量。结尾如果~iscell(feature) feature = {feature};结尾hopLength = featureVectorsPerSequence - featureVectorOverlap;idx1 = 1;序列= {};sequencePerFile =细胞(元素个数(特性),1);ii=1:numel(features)sequencePerFile{ii}=floor((size(features{ii},2)-featureVectorsPerSequence)/hopLength)+1;idx2=1;j = 1:sequenceperfile {ii}序列{idx1,1} =特征{ii}(:, idx2:idx2 + featurevectorspersequence  -  1);%#确定IDX1 = IDX1 + 1;IDX2 = IDX2 + HopLength;结尾结尾结尾

火车和验证网络

功能[trueLabelsCrossFold, predictedLabelsCrossFold] = HelperTrainAndValidateNetwork(变长度输入宗量)版权所有2019 The MathWorks, Inc.如果nargin == 3广告= varargin {1};augads = varargin {2};Extractor = Varargin {3};埃尔塞夫nargin == 2个广告= varargin {1};augads = varargin {1};提取= varargin {2};结尾扬声器=类别(ads.Labels.Speaker);numFolds =元素个数(扬声器);emptyEmotions =(ads.Labels.Emotion);emptyEmotions(:) = [];在每条折线上循环。trueLabelsCrossFold = {};predictedLabelsCrossFold = {};i=1:numfold%1.将音频数据存储划分为训练集和验证集。%将数据转换为高阵列。idxTrain = augads.Labels.Speaker〜=扬声器(ⅰ);augadsTrain =子集(augads,idxTrain);augadsTrain.Labels = augadsTrain.Labels.Emotion;tallTrain =高(augadsTrain);idxValidation = ads.Labels.Speaker ==扬声器(ⅰ);adsValidation =子集(广告,idxValidation);adsValidation.Labels = adsValidation.Labels.Emotion;tallValidation =高(adsValidation);%2.从培训集中提取功能。重新定位功能%因此,时间是沿着要与之兼容的行进行的%sequenceInputLayer。tallTrain = cellfun(@(X)X / MAX(ABS(x)中,[],'全部')、tallTrain“UniformOutput”、假);tallFeaturesTrain = cellfun (@ (x)提取(萃取器,x), tallTrain,“UniformOutput”,假);TallFeatureRain=cellfun(@(x)x',TallFeatureRain,“UniformOutput”、假);%#好的[~,特征菌株]=evalc('聚集(Tallfeaturestain)');%用途EVALC为了抑制命令行输出。tallValidation=cellfun(@(x)x/max(abs(x),[],'全部'),tallValidation,“UniformOutput”,false);tallFeaturesValidation=cellfun(@(x)提取物(提取器,x),tallValidation,“UniformOutput”、假);TallfeaturesValidation = Cellfun(@(x)x',tallfeatureveridation,“UniformOutput”、假);%#好的[~,特征验证]=evalc('聚(tallFeaturesValidation)');%用途EVALC为了抑制命令行输出。%3.使用训练集来确定均值和标准%每个特征的偏差。规范培训和验证%设置。allFeatures =猫(2,featuresTrain {:});M =平均(allFeatures,2,“奥米南”);S=标准(所有特征,0,2,“奥米南”);FeatureStrain = Cellfun(@(x)(x-m)./ s,featureastrain,“UniformOutput”、假);ii = 1:numel(featuresTrain) idx = find(isnan(featuresTrain{ii}));如果〜isempty(idx)featureastain {ii}(idx)= 0;结尾结尾featuresValidation = cellfun(@(X)(X-M)./ S,featuresValidation,“UniformOutput”、假);II = 1:numel(featuresValidation)IDX =找到(isnan(featuresValidation {II}));如果~isempty(idx) featuresValidation{ii}(idx) = 0;结尾结尾%4.缓冲序列,使每个序列由二十个组成%具有10个特征向量重叠的特征向量。featureVectorsPerSequence = 20;featureVectorOverlap = 10;[sequencesTrain,sequencePerFileTrain] = HelperFeatureVector2Sequence(featuresTrain,featureVectorsPerSequence,featureVectorOverlap);[sequencesValidation,sequencePerFileValidation] = HelperFeatureVector2Sequence(featuresValidation,featureVectorsPerSequence,featureVectorOverlap);%5.复制列车和验证集的标签,以便%它们与序列一一对应。labelsTrain=[emptyEmotions;augadsTrain.Labels];labelsTrain=labelsTrain(:);labelsTrain=repelem(labelsTrain[sequencePerFileTrain{:}]);% 6. 定义BiLSTM网络。dropoutProb1 = 0.3;numUnits = 200;dropoutProb2 = 0.6;层= [...sequenceInputLayer(大小(sequencesTrain {1}, 1)) dropoutLayer dropoutProb1 bilstmLayer (numUnits,“输出模式”“最后的”)dropoutLayer(dropoutProb2)fullyConnectedLayer(numel(类别(emptyEmotions)))softmaxLayer classificationLayer];% 7。定义培训选项。minibatchsize = 512;initiallearnrate = 0.005;学习ropperiod = 2;maxepochs = 3;选项=培训选项(“亚当”...“MiniBatchSize”,小匹马,...“initiallearnrate”,initialLearnRate,...“LearnRateDropPeriod”,learnRateDropPeriod,...“LearnRateSchedule”“分段”...“maxepochs”,maxEpochs,...“洗牌”“每个时代”...“详细”、假);% 8。培训网络。净= trainNetwork(sequencesTrain,labelsTrain,层,选项);%9.评估网络。调用分类以获取预测的标签每个序列的%。获取每个预测标签的模式%序列以获取每个文件的预测标签。predictedLabelsPerSequence =分类(净,sequencesValidation);trueLabels =分类(adsValidation.Labels);predictedLabels = trueLabels;IDX1 = 1;ii = 1:numel(true) predictedLabels(ii,:) = mode(predictedLabelsPerSequence(idx1:idx1 + sequencePerFileValidation{ii} - 1,:),1);idx1 = idx1 + sequencePerFileValidation{ii};结尾trueLabelsCrossFold{我}= trueLabels;%#确定predictedLabelsCrossFold {I} = predictedLabels;%#确定结尾结尾

参考文献

[1]伯克哈德,F., A. Paeschke, M. Rolfes, W.F. Sendlmeier, B. Weiss,《德语情感语言数据库》在诉讼Interspeech 2005.葡萄牙里斯本:国际语言传播协会,2005年。

另请参阅

|||

相关话题