语音情感识别
这个示例演示了一个简单的语音情感识别使用BiLSTM网络(SER)系统。你先下载数据集训练网络,然后测试单个文件。网络训练小德语数据库[1]。
示例将引导您完成训练网络,包括下载、扩充和训练数据集。最后,您执行leave-one-speaker-out (LOSO) 10倍交叉验证来评估网络体系结构。
本例中使用的特性选择使用连续的特征选择,类似于中描述的方法连续的音频特性的特征选择(音频工具箱)。
下载数据集
下载柏林的情感语音数据库[1]。数据库包含535个口语话语10演员旨在传达的情绪:愤怒、无聊、厌恶、焦虑、恐惧、快乐、悲伤、或中性的。情感是文本无关的。
dataFolder = tempdir;数据集= fullfile (dataFolder,“Emo-DB”);如果~ datasetExists(集)的url =“http://emodb.bilderbar.info/download/download.zip”;disp (“下载Emo-DB (40.5 MB)……”解压缩(url,数据集)结束
下载Emo-DB (40.5 MB)…
创建一个audioDatastore
(音频工具箱)指向的音频文件。
广告= audioDatastore (fullfile(数据集,“wav”));
文件名称代码指示演讲者ID、文本语言,情感,和版本。解释代码的网站包含一个关键和关于扬声器的附加信息,如性别和年龄。创建一个表的变量演讲者
和情感
。解码文件名到桌子上。
filepaths = ads.Files;emotionCodes = cellfun (@ (x) x(录得5个),filepaths, UniformOutput = false);情感=取代(emotionCodes, (“W”,“L”,“E”,“一个”,“F”,“T”,“N”),…(“愤怒”,“无聊”,“厌恶”,“焦虑和恐惧”,“幸福”,“悲伤”,“中性”]);speakerCodes = cellfun (@ (x) x (end-10: end-9) filepaths, UniformOutput = false);labelTable = cell2table (speakerCodes、情感,VariableNames = [“议长”,“情感”]);labelTable。情感= categorical(labelTable.Emotion); labelTable.Speaker = categorical(labelTable.Speaker); summary(labelTable)
变量:演讲者:535×1分类值:03 49 08年58 09年10 38 43 11 55 12 35 13 61 14 69 15 56 16 71情感:535×1分类值:愤怒127焦虑/恐惧69无聊81厌恶46 62快乐71中性79悲伤
labelTable
在相同的顺序文件audioDatastore
。设置标签
财产的audioDatastore
到labelTable
。
ads.Labels = labelTable;
进行语音情感识别
下载和加载pretrained网络,audioFeatureExtractor
(音频工具箱)对象用于训练网络,和归一化因素的特性。这个网络是训练用数据集所有扬声器扬声器除外03
。
downloadFolder = matlab.internal.examples.download金宝appSupportFile (“音频”,“SpeechEmotionRecognition.zip”);dataFolder = tempdir;解压缩(downloadFolder dataFolder) netFolder = fullfile (dataFolder,“SpeechEmotionRecognition”);负载(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-element序列与10-element重叠,这对应于大约600 ms windows 300 ms重叠。使用支持函数,金宝appHelperFeatureVector2Sequence,特征向量的数组转换为序列。
特点=(提取(afe、音频))';featuresNormalized =(功能- normalizers.Mean)。/ normalizers.StandardDeviation;numOverlap =10;featureSequences = HelperFeatureVector2Sequence (featuresNormalized 20 numOverlap);
饲料特性序列进入网络的预测。计算的平均预测和情节的概率分布选择情感作为一个饼图。你可以尝试不同的扬声器,情感,序列重叠,并预测平均测试网络的性能。得到一个现实的近似的网络性能,使用扬声器03
网络并不是训练。
YPred =双(预测(网络,featureSequences));平均=“模式”;开关平均情况下“的意思是”聚合氯化铝=意味着(YPred, 1);情况下“中值”聚合氯化铝=值(YPred, 1);情况下“模式”聚合氯化铝=模式(YPred, 1);结束派(probs. /笔(聚合氯化铝),字符串(net.Layers(结束). class))
剩下的例子说明了网络训练和验证。
列车网络的
第一次尝试的10倍交叉验证准确性训练是由于训练数据不足60%。模型训练数据不足overfits有些折叠和underfits。提高整体健康,增加使用数据集的大小audioDataAugmenter
(音频工具箱)。50对应每个文件选择经验作为一个很好的权衡处理时间和准确性提高。可以减少数量的扩增加快的例子。
创建一个audioDataAugmenter
对象。集的概率应用转向0.5
和使用默认的范围。设置应用时间转移的概率1
和使用范围[-0.3,0.3]
秒。设置添加噪声的概率1
并指定的信噪比范围(-20年,40)
dB。
numAugmentations =50;增量= audioDataAugmenter (NumAugmentations = NumAugmentations,…TimeStretchProbability = 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)
每个文件的音频数据存储:
创建50个扩增。
音频正常化的最大绝对值1。
编写增强音频数据为WAV文件。附加
_
augK
每个文件的名字,K增加数量。加快处理,使用parfor
和分区数据存储。
这种方法增加数据库是耗费时间和空间消耗。然而,当迭代选择网络体系结构或特征提取管道,前期成本通常是有利的。
N =元素个数(ads.Files) * numAugmentations;重置(广告)numPartitions = 18;抽搐parfor2 = 1:numPartitions adsPart =分区(广告、numPartitions ii);而hasdata (adsPart) [x, adsInfo] =阅读(adsPart);data =增加(增压器,x, fs);[~,fn] = fileparts (adsInfo.FileName);为i = 1:尺寸(数据,1)augmentedAudio = data.Audio {};augmentedAudio = augmentedAudio / max (abs (augmentedAudio), [],“所有”);augNum = num2str(我);如果元素个数(augNum) = = 1 iString = (' 0 'augNum);其他的iString = augNum;结束audiowrite (fullfile (writeDirectory sprintf (“% s_aug % s.wav”、fn iString))、augmentedAudio fs);结束结束结束disp (“增加完成”+ (toc / 60, 2) +“分钟”。)
增加在3.84分钟完成。
创建一个音频数据存储指向增广数据集。复制的行标签表的原始数据存储NumAugmentations
次确定标签的增广数据存储。
adsAug = audioDatastore (writeDirectory);adsAug。标签= repelem(ads.Labels,augmenter.NumAugmentations,1);
创建一个audioFeatureExtractor
(音频工具箱)对象。集窗口
一个周期30 ms汉明窗,OverlapLength
来0
,SampleRate
数据库的采样率。集gtcc
,gtccDelta
,mfccDelta
,spectralCrest
来真正的
提取它们。集SpectralDescriptorInput
来melSpectrum
这样spectralCrest
梅尔·谱计算。
赢得=汉明(圆(0.03 * fs),“周期”);overlapLength = 0;afe = audioFeatureExtractor (…窗口=赢,…OverlapLength = OverlapLength,…SampleRate = fs,……gtcc = true,…gtccDelta = true,…mfccDelta = true,……SpectralDescriptorInput =“melSpectrum”,…spectralCrest = true);
训练部署
当你训练部署,使用所有可用的数据集内的扬声器。组训练数据存储到增广数据存储。
adsTrain = adsAug;
把培训音频高数据存储到一个数组中。如果你有并行计算工具箱™,提取自动并行化。如果你没有并行计算工具箱™,继续运行的代码。
tallTrain =高(adsTrain);
提取训练特点和调整功能,这样时间是沿着行兼容sequenceInputLayer
。
featuresTallTrain = cellfun (@ (x)提取(afe x), tallTrain, UniformOutput = false);featuresTallTrain = cellfun (@ (x) x ', featuresTallTrain, UniformOutput = false);featuresTrain =收集(featuresTallTrain);
评估高表达式使用并行池“当地”:通过1对1:0%完成评价0%完成-通过1 1:在1分7秒内完成评估完成1分7秒
使用训练集来确定每个特性的平均值和标准偏差。
allFeatures =猫(2,featuresTrain {:});M =意味着(allFeatures 2“omitnan”);S =性病(allFeatures 0 2,“omitnan”);featuresTrain = cellfun (@ (x)(即x m)。/ S, featuresTrain, UniformOutput = false);
缓冲特性向量序列,以便每个序列由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 (afe.FeatureVectorLength) dropoutLayer dropoutProb1 bilstmLayer (numUnits OutputMode =“最后一次”)dropoutLayer (dropoutProb2) fullyConnectedLayer(元素个数(类别(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”,…Verbose = false,…情节=“训练进步”);
列车网络使用trainNetwork
。
网= trainNetwork (sequencesTrain、labelsTrain层,选择);
保存网络,配置audioFeatureExtractor
、和标准化因素集saveSERSystem
来真正的
。
saveSERSystem =假;如果saveSERSystem标准化者。意味着= M;标准化者。StandardDeviation = S;保存(“network_Audio_SER.mat”,“净”,“安全的”,“标准化者”)结束
培训系统验证
提供一个准确的评估在这个示例中,创建的模型训练和验证使用leave-one-speaker-out (LOSO)k倍交叉验证。在这个方法中,您使用的培训 在忽略时扬声器扬声器,然后验证。你重复这个过程k次了。最后验证精度的平均值k折叠。
创建一个变量,其中包含演讲者id。确定褶皱的数量:1每个演讲者。数据库包含的话语从10独特的扬声器。使用总结
显示演讲者id(左列)和话语的数量导致数据库(右列)。
演讲者= ads.Labels.Speaker;numFolds =元素个数(扬声器);总结(扬声器)
03 49 08年58 09年10 38 43 11 55 12 35 13 61 14 69 15 56 16 71
辅助函数HelperTrainAndValidateNetwork执行上述步骤对所有10个折叠并返回真,预测每个折叠标签。调用HelperTrainAndValidateNetwork
与audioDatastore
,增强audioDatastore
,audioFeatureExtractor
。
[labelsTrue, labelsPred] = HelperTrainAndValidateNetwork(广告、adsAug afe);
每叠打印精度和图表绘制10倍混乱。
为2 = 1:元素个数(labelsTrue) foldAcc =意味着(labelsTrue {2} = = labelsPred {2}) * 100;disp (“折”+ 2 +”,精度= "+圆(foldAcc, 2))结束
折叠1精度= 65.31折2精度= 68.97折3,准确性= 79.07折4,精度= 71.05折5,精度= 72.73折6,精度= 74.29折7,准确性= 67.21折8,精度= 85.51折9,准确性10 = 71.43折,准确性= 67.61
labelsTrueMat =猫(1,labelsTrue {:});labelsPredMat =猫(1,labelsPred {:});图厘米= confusionchart (labelsTrueMat labelsPredMat,…Title = (“10倍交叉验证的混淆矩阵”,“平均准确率= "圆的(意味着(labelsTrueMat = = labelsPredMat) * 100, 1)),…ColumnSummary =“column-normalized”RowSummary =“row-normalized”);sortClasses(厘米、类别(emptyEmotions))
金宝app支持功能
数组的特征向量转换为序列
函数[序列,sequencePerFile] = HelperFeatureVector2Sequence(特性、featureVectorsPerSequence featureVectorOverlap)% 2019年版权MathWorks公司。如果featureVectorsPerSequence < = featureVectorOverlap错误(“重叠的特征向量的个数必须小于每个序列的特征向量数。”)结束如果~ iscell(特性)特性={特性};结束hopLength = featureVectorsPerSequence - featureVectorOverlap;idx1 = 1;序列= {};sequencePerFile =细胞(元素个数(特性),1);为2 = 1:元素个数(特性)sequencePerFile{2} =地板((大小({2},2)- featureVectorsPerSequence) / hopLength) + 1;idx2 = 1;为j = 1: sequencePerFile{2}序列{idx1, 1} ={2}特性(:,idx2: idx2 + featureVectorsPerSequence - 1);% #好< AGROW >idx1 = idx1 + 1;idx2 = idx2 + hopLength;结束结束结束
培训和验证网络
函数[trueLabelsCrossFold, predictedLabelsCrossFold] = HelperTrainAndValidateNetwork(变长度输入宗量)% 2019年版权MathWorks公司。如果输入参数个数= = 3广告=变长度输入宗量{1};augads =变长度输入宗量{2};器=变长度输入宗量{3};elseif输入参数个数= = 2广告=变长度输入宗量{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)、[]“所有”)、tallTrain UniformOutput = false);tallFeaturesTrain = cellfun (@ (x)提取(萃取器,x), tallTrain, UniformOutput = false);tallFeaturesTrain = cellfun (@ (x) x ', tallFeaturesTrain, UniformOutput = false);% #好< NASGU >[~,featuresTrain] = evalc (“收集(tallFeaturesTrain)”);%使用evalc压制命令行输出。tallValidation = cellfun (@ x (x) / max (abs (x)、[]“所有”)、tallValidation UniformOutput = false);tallFeaturesValidation = cellfun (@ (x)提取(萃取器,x), tallValidation,“UniformOutput”、假);tallFeaturesValidation = cellfun (@ (x) x ', tallFeaturesValidation, UniformOutput = false);% #好< 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 = false);为2 = 1:元素个数(featuresTrain) idx =找到(isnan (featuresTrain {2}));如果~ isempty (idx) featuresTrain {2} (idx) = 0;结束结束featuresValidation = cellfun (@ (x)(即x m)。/ S, featuresValidation, UniformOutput = false);为2 = 1:元素个数(featuresValidation) idx =找到(isnan (featuresValidation {2}));如果~ isempty (idx) featuresValidation {2} (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 OutputMode =“最后一次”)dropoutLayer (dropoutProb2) fullyConnectedLayer(元素个数(类别(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”,…Verbose = false);% 8。培训网络。网= trainNetwork (sequencesTrain、labelsTrain层,选择);% 9。评估网络。叫分类预测的标签%为每个序列。得到的模式预测的标签%序列预测每个文件的标签。predictedLabelsPerSequence =分类(净,sequencesValidation);trueLabels =分类(adsValidation.Labels);predictedLabels = trueLabels;idx1 = 1;为2 = 1:元素个数(trueLabels) predictedLabels (ii):) =模式(predictedLabelsPerSequence (idx1: idx1 + sequencePerFileValidation {2} - 1:), 1);idx1 = idx1 + sequencePerFileValidation {2};结束trueLabelsCrossFold{我}= trueLabels;% #好< AGROW >predictedLabelsCrossFold{我}= predictedLabels;% #好< AGROW >结束结束
引用
[1]Burkhardt, F。,A. Paeschke, M. Rolfes, W.F. Sendlmeier, and B. Weiss, "A Database of German Emotional Speech." In诉讼Interspeech 2005。葡萄牙里斯本:国际言语交际协会,2005。
另请参阅
bilstmLayer
|trainNetwork
|trainingOptions
|sequenceInputLayer