主要内容

语音情感识别

本示例演示了一个使用BiLSTM网络的简单语音情感识别系统。首先下载数据集,然后在单个文件上测试经过训练的网络。该网络根据一个小型德语数据库进行培训[1]

该示例将引导您完成网络培训,包括下载、扩充和培训数据集。最后,您将执行遗漏一个扬声器(LOSO)10倍交叉验证来评估网络架构。

本例中使用的特征是使用顺序特征选择来选择的,类似于音频功能的顺序功能选择

下载数据集

下载柏林情感演讲数据库[1].这个数据库包含了由10个演员说出的535个话语,这些话语旨在传达以下情绪之一:愤怒、无聊、厌恶、焦虑/恐惧、快乐、悲伤或中性。情感是独立于文本的。

url ="http://emodb.bilderbar.info/download/download.zip";downloadFolder=tempdir;datasetFolder=fullfile(downloadFolder,“Emo-DB”);如果~存在(datasetFolder“dir”) disp ('正在下载Emo DB(40.5 MB)…')解压(url,数据集文件夹)结束

创建一个音频数据存储指向音频文件。

ads=音频数据存储(完整文件(数据集文件夹,“wav”));

文件名是表示说话者ID、所讲文本、情感和版本的代码。该网站包含破译密码的钥匙,以及演讲者的性别和年龄等附加信息。用这些变量创建一个表发言者情感.将文件名解码到表中。

filepath=ads.Files;emotioncode=cellfun(@(x)x(end-5),filepath,“UniformOutput”、假);情感=取代(emotionCodes, {' W ',“L”,“E”,“一个”,“F”,“不”,“不”},...{“愤怒”,“无聊”,“厌恶”,焦虑和恐惧的,“幸福”,“悲伤”,“中性”});speakerCodes=cellfun(@(x)x(end-10:end-9),文件路径,“UniformOutput”,false);labelTable=cell2table([speakerCodes,情感],“VariableNames”,{“议长”,“情感”});labelTable。情感= categorical(labelTable.Emotion); labelTable.Speaker = categorical(labelTable.Speaker); summary(labelTable)
变量:说话人: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

易变的和文件的顺序一样吗音频数据存储.设定标签财产的音频数据存储易变的

ads.Labels = labelTable;

进行语音情感识别

下载和加载预先训练的网络audioFeatureExtractor对象用于训练网络,并对特征进行归一化因子。该网络使用数据集中除发言者外的所有发言者进行训练03

url ='http://ssd.mathworks.com/万博1manbetxsupportfiles/audio/SpeechEmotionRecognition.zip';downloadNetFolder = tempdir;netFolder = fullfile (downloadNetFolder,“言语情感识别”);如果~存在(netFolder“dir”) disp ('下载预训练网络(1文件- 1.5 MB)…'解压缩(url, downloadNetFolder)结束负载(fullfile (netFolder“network_Audio_SER.mat”));

抽样率设置在audioFeatureExtractor对应于数据集的抽样率。

fs = afe.SampleRate;

选择一个说话者和情绪,然后将数据存储子集为只包含所选的说话者和情绪。从数据存储中读取并监听文件。

演讲者=分类(“03”);情感=分类(“厌恶”);(广告、ads.Labels adsSubset =子集。发言者==speaker & ads.Labels.Emotion == emotion); audio = read(adsSubset); sound(audio,fs)

使用audioFeatureExtractor对象提取特征,然后将其转置,使时间沿行。对特征进行规范化,然后将其转换为20个元素序列,其中10个元素重叠,对应于大约600毫秒的窗口和300毫秒的重叠。使用支持功能,万博1manbetxHelperFeatureVector2Sequence,将特征向量数组转换为序列。

特点=(提取(afe、音频))';feature归一化= (features - normalizer . mean)./normalizer . standard deviation;numOverlap =10; featureSequences=HelperFeatureVector2Sequence(featuresNormalized,20,numOverlap);

将特征序列输入网络进行预测。计算平均预测,并将所选情绪的概率分布绘制成饼状图。你可以尝试不同的扬声器、情绪、序列重叠和预测平均值来测试网络的性能。要获得网络性能的近似真实值,请使用扬声器03而网络并没有接受过这种训练。

YPred =双(预测(网络,featureSequences));平均=“模式”开关平均的情况下“的意思是”聚合氯化铝=意味着(YPred, 1);情况下“中值”聚合氯化铝=值(YPred, 1);情况下“模式”聚合氯化铝=模式(YPred, 1);结束饼图(probs./sum(probs),字符串(net.Layers(end.Classes))

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

列车网络

由于训练数据不足,第一次训练的10倍交叉验证准确率约为60%。在数据不足的情况下训练的模型在某些折线上拟合过度,而在另一些折线上拟合不足。若要提高整体适合度,请增加数据集的大小audioDataAugmenter.根据经验,每个文件选择50个增强,这是处理时间和准确性提高之间的一个很好的权衡。您可以减少扩展的数量以加快示例的速度。

创建一个audioDataAugmenter对象。设置the probability of applying pitch shifting to0.5并使用默认范围。设置应用时间偏移的概率1.并使用一系列的[-0.3,0.3]秒。设置添加噪声的概率1.并将信噪比范围指定为(-20年,40)dB。

numAugmentations =50; 增强器=音频数据增强器(“NumAugmentations”numAugmentations,...“时间树概率”0,...“VolumeControlProbability”0,......“PitchShiftProbability”, 0.5,......“TimeShiftProbability”,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为增广数。为了加快处理速度,使用帕弗并对数据存储进行分区。

这种扩充数据库的方法既耗时(约1小时),又占用空间(约26 GB)。然而,在反复选择网络体系结构或特征提取管道时,这种前期成本通常是有利的。

N =元素个数(ads.Files) * numAugmentations;myWaitBar = HelperPoolWaitbar (N,“正在扩充数据集…”); 重置(ads)数值=18;抽搐帕弗ii = 1:numPartitions adsPart = partition(ads,numPartitions,ii);hasdata(adsPart) [x,adsInfo] = read(adsPart);data =增加(增压器,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'0'augNum);其他的iString = augNum;结束audiowrite(完整文件)(writeDirectory,sprintf(“% s_aug % s.wav”、fn iString))、augmentedAudio fs);增量(myWaitBar)结束结束结束
使用“local”配置文件启动并行池(parpool)…连接到并行池(工作人员数量:6)。
删除(myWaitBar)流('扩增完成(%0.2f分钟)',toc/60)
完成增强(6.28分钟)。

创建一个指向扩充数据集的音频数据存储。复制原始数据存储的标签表的行核爆确定扩充数据存储的标签的时间。

adsagug=音频数据存储(writeDirectory);adsagug.Labels=repelem(ads.Labels,augmenter.numumations,1);

创建一个audioFeatureExtractor对象。设置窗口到一个周期性的30毫秒汉明窗口,OverlapLength0,SampleRate到数据库的采样率。集gtcc,gtccDelta,mfccDelta,spectralCrest真正的提取它们。集SpectralDescriptorInputmelSpectrum这样spectralCrest为MEL谱计算。

赢得=汉明(圆(0.03 * fs),“定期”); 重叠长度=0;afe=音频特征提取程序(...“窗口”,赢了,...“OverlapLength”,重叠长度,...“SampleRate”fs,......“gtcc”,真的,...“gtccDelta”,真的,...“mfccDelta”,真的,......“SpectralDescriptorInput”,“梅尔斯波谱”,...“spectralCrest”,真正的);

训练部署

在进行部署培训时,请使用数据集中所有可用的扬声器。将训练数据存储设置为扩充数据存储。

adsTrain = adsAug;

将训练音频数据存储转换为高阵列。如果你有并行计算工具箱™, 提取过程自动并行化。如果没有并行计算工具箱™, 代码继续运行。

tallTrain =高(adsTrain);

提取训练特征,并重新定位特征,使时间沿着行兼容sequenceInputLayer(深度学习工具箱)

featuresTallTrain=cellfun(@(x)提取物(afe,x),tallTrain,“统一输出”、假);featuresTallTrain = cellfun (@ (x) x ', featuresTallTrain,“统一输出”、假);featuresTrain =收集(featuresTallTrain);
使用Parallel Pool 'local'计算tall表达式:- Pass 1 of 1: Completed in 1 min 7 sec

使用训练集来确定每个特征的均值和标准偏差。

allFeatures =猫(2,featuresTrain {:});M =意味着(allFeatures 2“omitnan”);S =性病(allFeatures 0 2,“omitnan”);featuresTrain = cellfun (@ (x)(即x m)。/ S, featuresTrain,“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网络使用bilstmLayer(深度学习工具箱).放置一个dropoutLayer(深度学习工具箱)前后bilstmLayer以防止过度拟合。

dropoutProb1 = 0.3;numUnits = 200;dropoutProb2 = 0.6;层= [...sequenceInputLayer(大小(sequencesTrain{1},1))DropOutputLayer(dropoutProb1)BilstLayer(numUnits,“OutputMode”,“最后一次”) dropoutLayer(dropoutProb2) fulllyconnectedlayer (numel(categories(emptyEmotions))) softmaxLayer classificationLayer];

使用定义培训选项trainingOptions(深度学习工具箱)

miniBatchSize = 512;initialLearnRate = 0.005;learnRateDropPeriod = 2;maxEpochs = 3;选择= trainingOptions (“亚当”,...“MiniBatchSize”miniBatchSize,...“InitialLearnRate”initialLearnRate,...“LearnRateDropPeriod”learnRateDropPeriod,...“LearnRateSchedule”,“分段”,...“MaxEpochs”maxEpochs,...“洗牌”,“every-epoch”,...“冗长”假的,...“情节”,“训练进步”);

培训网络使用trainNetwork(深度学习工具箱)

网= trainNetwork (sequencesTrain、labelsTrain层,选择);

保存已配置的网络audioFeatureExtractor,和归一化因子,集合储蓄系统真正的

saveSERSystem =如果saveSERSystem标准化者。意味着= M;标准化者。StandardDeviation = S;保存(“network_Audio_SER.mat”,“净”,“安全的”,“标准化者”)结束

系统验证培训

要对您在本例中创建的模型提供准确的评估,请使用Leve one speaker out(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个折叠执行上述步骤,并返回每个折叠的真实和预测标签。调用HelperTrainAndValidateNetwork音频数据存储,增强音频数据存储,audioFeatureExtractor

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

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

对于ii = 1:numel(labeltrue) foldAcc = mean(labeltrue {ii}==labelsPred{ii})*100;流('折叠%1.0f,精度=%0.1f\n',ii,foldac);结束
折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 =猫(1,labelsTrue {:});labelsPredMat =猫(1,labelsPred {:});figure cm = confusionchart(labelsTrueMat,labelsPredMat);valAccuracy =意味着(labelsTrueMat = = labelsPredMat) * 100;厘米。标题= sprintf (' 10倍交叉验证的混淆矩阵\nAverage Accuracy = %0.1f', valAccuracy);sortClasses(厘米、类别(emptyEmotions))厘米。ColumnSummary =“列规格化”;厘米。RowSummary =“row-normalized”

万博1manbetx支持功能

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

函数[序列,sequencePerFile] = HelperFeatureVector2Sequence(特性、featureVectorsPerSequence featureVectorOverlap)MathWorks, Inc.版权所有如果featureVectorsPerSequence <= featureVectorOverlap error('重叠特征向量的数量必须小于每个序列的特征向量数量。')结束如果~iscell(features)features={features};结束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} sequences{idx1,1} = features{ii}(:,idx2:idx2 + featureVectorsPerSequence - 1);% #好< AGROW >Idx1 = Idx1 + 1;idx2 = idx2 + hopLength;结束结束结束

培训和验证网络

函数[trueLabelsCrossFold,predictedLabelsCrossFold]=HelperTrain和ValidateNet工作(varargn)版权所有2019 The MathWorks, Inc.如果Nargin == 3 ads = varargin{1};augads =变长度输入宗量{2};器=变长度输入宗量{3};elseifNargin == 2 ads = varargin{1};augads =变长度输入宗量{1};器=变长度输入宗量{2};结束演讲者=类别(ads.Labels.Speaker);numFolds =元素个数(扬声器);emptyEmotions = (ads.Labels.Emotion);emptyEmotions (:) = [];%在每个折叠处打圈。trueLabelsCrossFold = {};predictedLabelsCrossFold = {};对于我= 1:numFolds% 1。将音频数据存储分为训练集和验证集。%将数据转换为高数组。idxTrain = augads.Labels.Speaker ~ =议长(i);augadsTrain =子集(augads idxTrain);augadsTrain。标签= augadsTrain.Labels.Emotion; tallTrain = tall(augadsTrain); idxValidation = ads.Labels.Speaker==speaker(i); adsValidation = subset(ads,idxValidation); adsValidation.Labels = adsValidation.Labels.Emotion; tallValidation = tall(adsValidation);% 2。从训练集中提取特征。重新定位的功能%以便时间沿着行兼容% sequenceInputLayer。tallTrain = cellfun (@ x (x) / max (abs (x)、[]“所有”),塔勒列,“统一输出”、假);tallFeaturesTrain = cellfun (@ (x)提取(萃取器,x), tallTrain,“统一输出”、假);tallFeaturesTrain = cellfun (@ (x) x ', tallFeaturesTrain,“统一输出”、假);% #好< NASGU >[~, featuresTrain] = evalc (“收集(tallFeaturesTrain)”);%使用evalc抑制命令行输出。tallValidation = cellfun (@ x (x) / max (abs (x)、[]“所有”)、tallValidation“统一输出”、假);tallFeaturesValidation = cellfun (@ (x)提取(萃取器,x), tallValidation,“统一输出”、假);tallFeaturesValidation = cellfun (@ (x) x ', tallFeaturesValidation,“统一输出”、假);% #好< NASGU >[~, featuresValidation] = evalc (“收集(tallFeaturesValidation)”);%使用evalc抑制命令行输出。% 3。使用训练集确定平均值和标准每个特征的偏差%。规范培训和验证%设置。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;结束结束% 4。缓冲序列,使每个序列由20个组成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))DropOutputLayer(dropoutProb1)BilstLayer(numUnits,“OutputMode”,“最后一次”) dropoutLayer(dropoutProb2) fulllyconnectedlayer (numel(categories(emptyEmotions))) softmaxLayer classificationLayer];%7.定义培训选项。miniBatchSize = 512;initialLearnRate = 0.005;learnRateDropPeriod = 2;maxEpochs = 3;选择= trainingOptions (“亚当”,...“MiniBatchSize”miniBatchSize,...“InitialLearnRate”initialLearnRate,...“LearnRateDropPeriod”learnRateDropPeriod,...“LearnRateSchedule”,“分段”,...“MaxEpochs”maxEpochs,...“洗牌”,“every-epoch”,...“冗长”、假);% 8. 培训网络。网= trainNetwork (sequencesTrain、labelsTrain层,选择);% 9。评估网络。调用分类以得到预测的标签%为每个序列。获取每个预测标签的模式%序列获取每个文件的预测标签。predictedLabelsPerSequence =分类(净,sequencesValidation);trueLabels =分类(adsValidation.Labels);predictedLabels = trueLabels;idx1 = 1;对于ii=1:numel(trueLabels)predictedLabels(ii,:)=模式(predictedLabelsPerSequence(idx1:idx1+sequencePerFileValidation{ii}-1,:),1);idx1=idx1+sequencePerFileValidation{ii};结束trueLabelsCrossFold{i}=trueLabels;% #好< AGROW >predictedLabelsCrossFold{我}= predictedLabels;% #好< AGROW >结束结束

参考文献

[1] Burkhardt,F.,A.Paeschke,M.Rolfes,W.F.Sendlmeier和B.Weiss,“德国情感语言数据库”,摘自2005年国际语言会议录葡萄牙里斯本:国际言语交流协会,2005年。