主要内容

使用GRU网络分类性别

此示例显示如何使用深度学习对演讲者的性别进行分类。该示例使用门控复发单元(GRU)网络和γ谱系齐系数(GTCC),俯仰,谐波比和几种光谱形状描述符。

介绍

基于语音信号的性别分类是许多音频系统的重要组成部分,例如自动语音识别,扬声器识别和基于内容的多媒体索引。

此示例使用GRU网络,一种复发性神经网络(RNN)非常适合研究序列和时间序列数据。GRU网络可以在序列的时间步长之间学习长期依赖性。

这个例子用γ倒频谱系数序列(GTCC.)、音高估计(沥青),谐波比(harmonicRatio)和几种光谱形状描述符(光谱描述符)。

要加速培训过程,请在带GPU的计算机上运行此示例。如果您的机器有GPU和并行计算工具箱™,那么Matlab©自动使用GPU进行培训;否则,它使用CPU。

用预先训练的网络分类性别

在详细进入培训过程之前,您将使用预先训练的网络在两个测试信号中对扬声器的性别进行分类。

下载预先训练的网络。

URL =.“http://ssd.mathworks.com/万博1manbetxsupportfiles/audio/GenderClassification.zip”;downloaddnetfolder = tempdir;netfolder = fullfile(downloadnetfolder,'性别分类');如果〜存在(NetFolder,'dir')解压缩(URL,DownloadNetFolder)结束

加载预先训练的网络和预先计算的用于特征归一化的向量。

matfilename = fullfile(netfolder,'genderidnet.mat');负载(matFileName“genderIDNet”“米”“年代”);

用男性扬声器加载测试信号。

[audioIn, Fs] = audioread ('malespeech.flac');声音(audioIn Fs)

隔离信号中的语音区域。

边界= detectSpeech (audioIn, Fs);audioIn = audioIn(边界(1):边界(2));

创建一个audioFeatureExtractor从音频数据中提取特征。您将使用相同的对象提取特征进行训练。

器= audioFeatureExtractor (......“采样率”,fs,......“窗口”,汉明(圆形(0.03 * fs),“周期”),......“OverlapLength”,圆形(0.02 * fs),............“GTCC”,真的,......“gtccDelta”,真的,......“gtccdeltadelta”,真的,............“spectraldescriptorinput”“melSpectrum”......“Spectralcentroid”,真的,......“spectralentropy”,真的,......“spectralflux”,真的,......“spectralslope”,真的,............“节”,真的,......“harmonicRatio”,真的);

从信号中提取特征并使它们标准化。

特点=提取(萃取器,audioIn);=(功能特性。“- M)。/ S;

分类信号。

性别=分类(genderIDNet,特性)
性别=分类男性

将另一个女性说话者的信号分类。

[audioIn, Fs] = audioread ('femaleSpeech.flac');声音(audioIn Fs)
边界= detectSpeech (audioIn, Fs);audioIn = audioIn(边界(1):边界(2));特点=提取(萃取器,audioIn);=(功能特性。“- M)。/ S;分类(genderIDNet特性)
ans =分类

预处理训练音频数据

本例中使用的GRU网络在使用特征向量序列时效果最好。为了演示预处理管道,本示例将遍述单个音频文件的步骤。

读取包含语音的音频文件的内容。发言人性别是男性。

[audioIn, Fs] = audioread (“Counting-16-44p1-mono-15secs.wav”);标签= {'男性'};

绘制音频信号,然后使用它侦听声音命令。

TimeVector =(1 / FS)*(0:尺寸(AudioIn,1)-1);图绘图(TimeVector,AudioIn)Ylabel(“振幅”)Xlabel(“时间(s)”) 标题(“样本音频”) 网格

声音(audioIn Fs)

语音信号具有静音片段,不包含与扬声器的性别有关的有用信息。用检测找到音频信号中的语音段。

语音indices =检测echech(AudioIn,FS);

创建一个audioFeatureExtractor从音频数据中提取特征。语音信号在性质中是动态的,随时间变化。假设语音信号在短时间比例上静止,并且它们的处理通常在20-40毫秒的窗口中进行。使用20毫秒重叠指定30毫秒的窗口。

器= audioFeatureExtractor (......“采样率”,fs,......“窗口”,汉明(圆形(0.03 * fs),“周期”),......“OverlapLength”,圆形(0.02 * fs),............“GTCC”,真的,......“gtccDelta”,真的,......“gtccdeltadelta”,真的,............“spectraldescriptorinput”“melSpectrum”......“Spectralcentroid”,真的,......“spectralentropy”,真的,......“spectralflux”,真的,......“spectralslope”,真的,............“节”,真的,......“harmonicRatio”,真的);

从每个音频段提取特征。输出从audioFeatureExtractor是A.numFeatureVectors-经过-numfeatures.大批。这sequenceInputlayer.在本例中使用的时间需要沿第二个维度。排列输出数组,使时间沿第二个维度。

featurevectorssegment = {};ii = 1:size(speech hindices,1) featureVectorsSegment{end+1} = (extract (extractor,audioIn(speech hindices (ii,1):speech hindices (ii,2))))';结束numSegments =大小(featureVectorsSegment)
numsegments =1×21 11
[NumFeatures,NumFeatureVectorsSegment1] =大小(FeatureVectorsSegment {1})
numfeatures = 45.
NumFeatureVectorsSegment1 = 124.

复制标签,使它们与段一对一的对应关系。

Labels = Repelem(标签,大小(语音indices,1))
标签=1×11单元{“男性”}{‘男性’}{‘男性’}{‘男性’}{‘男性’}{‘男性’}{‘男性’}{‘男性’}{‘男性’}{‘男性’}{‘男性’}

当使用一个sequenceInputlayer.,使用长度一致的序列通常是有利的。将特征向量数组转换为特征向量序列。每个序列使用20个特征向量,其中5个特征向量重叠。

featurevectorspersequence = 20;featurevectoroverlap = 5;hoplength = featurevectorspersequence  -  featurevectorovelap;IDX1 = 1;featurestrain = {};severnpersegment = zeros(numel(featurevectorsse),1);ii = 1:numel(featureVectorsSegment) sequencePerSegment(ii) = max(floor((size(featureVectorsSegment{ii},2) - featureVectorsPerSequence)/hopLength) + 1,0);IDX2 = 1;j = 1:sequencePerSegment(ii) featuresTrain{idx1,1} = featureVectorsSegment{ii}(:,idx2:idx2 + featureVectorsPerSequence - 1);+ 1 = 1;idx2 = idx2 + hopLength;结束结束

有关简洁,请求功能HelperFeatureVector2sequence.封装上述处理,并在示例的其余部分中使用。

复制标签,以便它们与培训集一对一的对应关系。

标签= Repelem(标签,序列);

预处理管道的结果是numsequence.-by-1单元格数组numfeatures.-经过-FeatureVectorsPerSequence矩阵。标签是一个numsequence.-by-1阵列。

NumSequence =元素个数(featuresTrain)
NumSequence = 27
[NumFeatures,FeatureVectorsPersequence] =尺寸(FeatureStrain {1})
NumFeatures = 45
FeatureVectorsPerSequence = 20
numsequence = numel(标签)
NumSequence = 27

该图提供了每个检测到的语音区域使用的特征提取的概述。

创建培训和测试数据存储

此示例使用Mozilla公共语音数据集的子集[1].DataSet包含48 kHz的主题录制短句。下载DataSet和Untar下载文件。集pathtodatabase.到数据的位置。

URL =.“http://ssd.mathworks.com/万博1manbetxsupportfiles/audio/commonvoice.zip”;downloaddatasetfolder = tempdir;datafolder = fullfile(downloaddatasetfolder,“无法推进”);如果~存在(dataFolder'dir')disp('下载数据集(956 MB)......')解压缩(URL,DownloadDatasetFolder)结束
下载数据集(956 MB)......

audioDatastore创建培训和验证集的数据存储。用可阅读读取与音频文件关联的元数据。

loc = fullfile(datafolder);adstrain = audiodatastore(fullfile(loc,'火车'),'insertumbfolders',真的);MetadataTrain = Readtable(FullFile(FullFile(Loc,'火车'),“火车.TSV”),“文件类型”“文本”);adstrain.labels = MetadataTrain.Cender;adsvalidation = audiodataStore(fullfile(loc,“验证”),'insertumbfolders',真的);MetAdatavalidation = ReadTable(FullFile(FullFile(Loc,“验证”),“验证.TSV”),“文件类型”“文本”);ADSValidation.Labels = MetAdataValidation.gender;

counteanceLabel.检查培训和验证集的性别分解。

countEachLabel (adsTrain)
ans =.2×2表标签数______ _____ female 1000 male 1000
CountAckeLabel(ADSValidation)
ans =.2×2表标签数______ _____女性200男性200

为了用整个数据集来训练网络,并达到尽可能高的精度,设置逃守血统.要快速运行此示例,请设置逃守血统真的

depentataset = false;如果逃守血统%将训练数据集减少20倍adstrain = splitheachlabel(adstrain,round(numel(adstrain.files)/ 2/20));ADSValidation = SpliteachLabel(ADSValidation,20);结束

创建培训和验证集

确定数据集中的音频文件的采样率,然后更新音频特征提取器的采样率,窗口和重叠长度。

[〜,Adsinfo] =读(adstrain);FS = Adsinfo.Sampleate;Extractor.Samplere = FS;Extractor.Window =汉明(圆形(0.03 * FS),“周期”);Extractor.overlaplength = round(0.02 * fs);

加快处理,分发多个工人的计算。如果您有并行计算工具箱™,则示例将数据存储区分区,以便在可用工人上并行发生特征提取。确定系统的最佳分区数。如果您没有并行计算工具箱™,则该示例使用单个工人。

如果~ isempty(版本('平行'))&&〜oderataset pool = gcp;numpar = numpartitions(adstrain,pool);别的numPar = 1;结束
使用“本地”配置文件启动并行池(Parpool)连接到并行池(工人数:6)。

在一个循环:

  1. 从音频数据存储读取。

  2. 检测语言区域。

  3. 从语音区域提取特征向量。

复制标签,使它们与特征向量一对一的对应关系。

labelsTrain = [];featureVectors = {};%循环通过最佳分区数parfor2 = 1: numPar%分区数据存储subds = partition(adstrain,numpar,ii);%预先配置featurevectorsinsubds = {};segmentsperfile = zeros(numel(subds.files),1);循环遍历分区数据存储中的文件jj = 1:元素个数(subds.Files)%1.在单个音频文件中读取audioIn =阅读(再分);%2.确定与语音相对应的音频区域语音indices =检测echech(AudioIn,FS);% 3。从每个语音片段中提取特征segmentsperfile(JJ)=大小(语音indices,1);特征=单元格(SegmentsPerfile(JJ),1);kk = 1:size(语音indices,1)特征{kk} =(提取器(提取器,Audioin(Speepindices(KK,1):语音indices(kk,2))))';结束featureVectorsInSubDS = (featureVectorsInSubDS;特性(:));结束featureVectors = [featureVectors; featureVectorsInSubDS];%复制标签,使它们处于一对一的通勤具有特征向量的百分比。RepedLabels = Repelem(Subds.Labels,SegmentsPerfile);labelstrain = [labelstrain; RepedLabels(:)];结束

在分类应用中,将所有特征归一化,使其具有零均值和统一的标准差是很好的做法。

计算每个系数的均值和标准偏差,并使用它们来标准化数据。

AllFeatures = Cat(2,FeatureVectors {:});所有种(Isinf(Allfeatures))= Nan;m =均值(全部,2,'omitnan');s = std(全部,0,2,'omitnan');featureVectors = cellfun (@ (x)(即x m)。/ S, featureVectors,'统一输出',错误的);II = 1:numel(featurevectors)idx = find(iSnan(featurevectors {ii}));如果〜isempty(idx)featurevectors {II}(IDX)= 0;结束结束

将特征向量缓冲到具有10个重叠的20个特征向量的序列中。如果序列具有少于20个特征向量,请将其丢弃。

[FeatureStrain,TrainSequencePersegment] = HelperFeatureVector2序列(FeatureVectors,FeatureVectorsPersequence,FeatureVectoroverlap);

复制标签,使它们与序列一对一的对应关系。

LabelStrain = Repelem(Labelstrain,[训练序列{:}]);LabelStrain =分类(Labelstrain);

使用与创建训练集相同的步骤创建验证集。

labelsvalidation = [];featureVectors = {};valsegmentsperfile = [];parforII = 1:numpar subds = partition(ADSValidation,NumPar,II);featurevectorsinsubds = {};valsegmentsperfileinsubds = zeros(numel(subds.files),1);JJ = 1:NUMEL(SUBDS.FILES)AUDION =读取(SUBDS);语音indices =检测echech(AudioIn,FS);numsegments = size(语音indices,1);特点= Cell(ValSegmentsPerfileInsubds(JJ),1);kk = 1:numsgments特征{kk} =(提取器(提取器,AudioIn(keighindices(kk,1):语音indices(kk,2))))';结束featureVectorsInSubDS = (featureVectorsInSubDS;特性(:));valSegmentsPerFileInSubDS (jj) = numSegments;结束RepedLabels = Repelem(Subds.Labels,ValSegmentsPerfileInsubds);LabelSvalidation = [LabelsValidation; RepedLabels(:)];featureVectors = [featureVectors; featureVectorsInSubDS];valsegmentsperfile = [valsegmentsperfile; valsegmentsperfileinsubds];结束featureVectors = cellfun (@ (x)(即x m)。/ S, featureVectors,'统一输出',错误的);II = 1:numel(featurevectors)idx = find(iSnan(featurevectors {ii}));如果〜isempty(idx)featurevectors {II}(IDX)= 0;结束结束[特征过修,valsequencePersegment] = HelperFeatureVector2序列(FeatureVectors,FeatureVectorsPersequence,FeatureVectoroverlap);LabelSvalidation = Repelem(LabelsValidation,[ValequencePersegment {:}]);LabelSvalidation =分类(LabelSvalidation);

定义GRU网络架构

GRU网络可以在序列数据的时间步长之间学习长期依赖性。这个例子用途gruLayer从正反两个方向看序列。

指定输入大小为大小的序列numfeatures..指定具有75的输出大小并输出序列的GRU层。然后,指定具有75的输出大小的GRU层,并输出序列的最后一个元素。该命令指示GRU层将其输入到75个功能映射到75个功能,然后为完全连接的图层准备输出。最后,通过包括完全连接的大小2层来指定两个类,然后是Softmax层和分类层。

层= [......sequenceInputLayer(大小(featuresTrain {1}, 1)) gruLayer(75年“outputmode”“顺序”)GRULAYER(75,“outputmode”“最后的”)全连接层(2)SoftMaxLayer分类层];

接下来,为分类器指定训练选项。集maxepochs.4因此,网络使4通过培训数据进行4。集小匹匹匹匹配在256中,网络一次看128个训练信号。指定绘图作为“培训 - 进展”当迭代次数增加时,生成显示培训进度的地块。集verb要禁用对应于图中所示的数据的表输出。指定洗牌作为“每个时代”在每个阶段开始时打乱训练顺序。指定学习宿舍“分段”每次通过一定数量的时期(1)都通过指定因子(0.1)减少学习率。

此示例使用自适应时刻估计(ADAM)求解器。亚当利用经常性的神经网络(RNN)更好地表现出比默认的随机梯度下降相似,而具有动量(SGDM)求解器。

minibatchsize = 256;验证频率=地板(Numel(Labelstrain)/小匹匹匹匹配);选项=培训选项(“亚当”......“maxepochs”,4,......“迷你atchsize”,小匹马,......“阴谋”“培训 - 进展”......“详细”,错误的,......“洗牌”“每个时代”......“Learnrateschedule”“分段”......“学习ropfactor”, 0.1,......“学习ropperiod”,1,......'vightationdata',{特点过验证,labelsvalidation},......'验证职业',验证职权;

训练GRU网络

使用指定的训练选项和层结构对GRU网络进行训练Trainnetwork..因为训练集很大,培训过程可能需要几分钟。

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

训练进度图的顶部子图代表训练精度,即每个小批上的分类精度。当训练顺利进行时,这个值通常会增加到100%。底部的子图显示了训练损失,即每个小批处理上的交叉熵损失。当训练进展顺利时,这个值通常会减少到零。

如果训练不收敛,图可能会在值之间振荡,而不是在某个向上或向下的方向。这种振荡意味着训练精度没有提高,训练损耗没有减少。这种情况可能发生在训练开始时,或者在训练准确度有了一些初步的提高之后。在很多情况下,改变训练选择可以帮助网络实现收敛。减少小匹匹匹匹配或减少initiallearnrate.可能会导致更长的训练时间,但它可以帮助网络更好地学习。

可视化训练准确性

计算培训准确性,这表示分类器对培训的信号的准确性。首先,对训练数据进行分类。

预测=分类(净,featuresTrain);

绘制混乱矩阵。使用列和行摘要显示两个类的精度并回忆。

图CM = ConfusionChart(分类(Labelstrain),预测,“标题”'训练准确性');cm.columnsummary =“column-normalized”;厘米。RowSummary ='行标准化';

可视化验证准确性

计算验证精度。首先,对训练数据进行分类。

[预测,概率] =分类(网络,特征过验证);

绘制混乱矩阵。使用列和行摘要显示两个类的精度并回忆。

图CM = ConfusionChart(分类(标签(LabelSvalidation),预测,“标题”'验证设置精度');cm.columnsummary =“column-normalized”;厘米。RowSummary ='行标准化';

示例生成来自每个训练语音文件的多个序列。通过考虑对应于同一文件的所有序列的输出类,以及应用“最大规则”决定,可以选择更高的准确度,并且选择具有最高置信度分数的段的类。

确定验证集中每个文件生成的序列数。

sequencerfile = zeros(尺寸(valsegmentsperfile));valseencepersegmentmat = Cell2mat(瓦斯QuenceSegment);Idx = 1;ii = 1:numel(valSegmentsPerFile) sequencePerFile(ii) = sum(valSequencePerSegmentMat(idx:idx+valSegmentsPerFile(ii)-1));idx = idx + valSegmentsPerFile(ii);结束

通过考虑从同一文件生成的所有序列的输出类来预测每个培训文件中的性别。

numfiles = numel(adsvalidation.files);ActualGENDER =分类(ADSValidation.Labels);predigedgender = amancegender;得分=细胞(1,NumFiles);计数器= 1;猫=独特(实际);index = 1:numfiles得分{index} =概率(计数器:counter + sequencerfile(索引) -  1,:);m = max(均值(分数{index},1),[],1);如果m(1) >= m(2) predictedGender(index) = cats(1)别的预测性(指数)=猫(2);结束计数器=计数器+ sequencerfile(索引);结束

将多数规则预测的混淆矩阵形象化。

图CM = ConfusionChart(ActualGender,PredigeGender,“标题”'验证设置精度 -  max规则');cm.columnsummary =“column-normalized”;厘米。RowSummary ='行标准化';

参考文献

[1]Mozilla常见的语音数据集

万博1manbetx支持功能

功能[序列,sequencePerSegment] = HelperFeatureVector2Sequence(特性、featureVectorsPerSequence featureVectorOverlap)如果featurevectorspersequence <= featurevectoroverlap错误(“重叠特征向量的个数必须小于每个序列的特征向量个数。”结束hoplength = featurevectorspersequence  -  featurevectorovelap;IDX1 = 1;序列= {};severnpersegment = cell(numel(特征),1);II = 1:NUMER(特征)SERMERPERSEGERMENT {II} = MAX(楼层((特征{II},2) -  FeatureVectorsPersequence)/ HopLength)+ 1,0);IDX2 = 1;j = 1:sementpersegment {ii}序列{idx1,1} =特征{ii}(:, idx2:idx2 + featurevectorspersequence  -  1);%#OK + 1 = 1;idx2 = idx2 + hopLength;结束结束结束