主要内容

使用音调和MFCC识别说话人

这个例子演示了一种基于从录音语音中提取的特征来识别人的机器学习方法。用于训练分类器的特征是语音的浊音段的音调和mel频率倒频谱系数(MFCC)。这是一个封闭集的扬声器识别:将被测扬声器的音频与所有可用的扬声器模型(有限集)进行比较,并返回最接近的匹配。

简介

本例中用于说话人识别的方法如图所示。

从10个扬声器的语音信号中提取音调和MFCC。这些特征被用于训练k -最近邻(KNN)分类器。然后对需要分类的新语音信号进行相同的特征提取。经过训练的KNN分类器预测10个说话者中哪一个最接近匹配。

用于分类的特征

本节讨论螺距、过零率、短时间能量和MFCC。音调和MFCC是用来对扬声器进行分类的两个特征。通过过零率和短时间能量来确定何时使用基音特征。

球场

语音大致可以分为表达了而且无声的.在发音的情况下,来自肺部的空气被声带调节,并导致准周期性的兴奋。所产生的声音主要由相对低频的振荡所控制,称为球场.在无声说话的情况下,来自肺部的空气通过声道的收缩,成为湍流,噪音般的兴奋。在语音的源-过滤器模型中,激发被称为源,声道被称为过滤器。声源特征化是语音系统特征化的重要组成部分。

作为一个浊音和浊音的例子,考虑单词“two”的时域表示(/T UW/)。辅音/T/(清音)看起来像噪音,而元音/UW/(清音)的特征是强烈的基频。

[audioIn,fs] = audioread(“Counting-16-44p1-mono-15secs.wav”);twoStart = 110e3;twoStop = 135e3;audioIn = audioIn(twoStart:twoStop);timeVector = linspace(twoStart/fs,twoStop/fs, nummel (audioIn));sound(audioIn,fs) figure plot(timeVector,audioIn) axis([(twoStart/fs) (twoStop/fs) -1 1]) ylabel(“振幅”)包含(“时间(s)”)标题(“话语-二”

语音信号本质上是动态的,随时间而变化。我们假设语音信号在短时间尺度上是静止的,它们的处理在20-40毫秒的窗口内完成。这个例子使用了一个30毫秒的窗口,重叠了25毫秒。使用球场函数来查看音高如何随时间变化。

windowLength = round(0.03*fs);overlapLength = round(0.025*fs);f0 = pitch(audioIn,fs,WindowLength= WindowLength,OverlapLength= OverlapLength,Range=[50,250]);图subplot(2,1,1) plot(timeVector,audioIn) axis([(110e3/fs) (135e3/fs) -1]) ylabel(“振幅”)包含(“时间(s)”)标题(“话语-二”) subplot(2,1,2) timeVectorPitch = linspace(twoStart/fs,twoStop/fs, nummel (f0));情节(timeVectorPitch f0,“*”)轴([(110e3/fs) (135e3/fs) min(f0) max(f0)])“球场(Hz)”)包含(“时间(s)”)标题(“轮廓”

球场函数估计每一帧的间距值。然而,音高只是发声区域的音源的特征。区分沉默和说话最简单的方法是分析短时间能量。如果帧中的能量高于给定的阈值,则将该帧声明为语音。

energyThreshold = 20;[segments,~] = buffer(audioIn,windowLength,overlapLength,“nodelay”);ste = sum((segment .*hamming(windowLength,“周期”)) ^ 2, 1);isSpeech = ste(:) >能量阈值;

区分浊音和浊音最简单的方法是分析过零率。大量的过零点意味着没有主要的低频振荡。如果帧的过零率低于给定的阈值,则将其声明为语音。

zcrThreshold = 0.02;zcr = zerocrossrate(audioIn,WindowLength= WindowLength,OverlapLength= OverlapLength);isvoices = zcr < zcrThreshold;

结合isSpeech而且isVoiced以确定帧是否包含语音。

voicedSpeech = isSpeech & isvocal;

从音高估计和图中删除不对应语音的区域。

f0(~voicedSpeech) = NaN;图subplot(2,1,1) plot(timeVector,audioIn)轴([(110e3/fs) (135e3/fs) -1 1])轴ylabel (“振幅”)包含(“时间(s)”)标题(“话语-二”) subplot(2,1,2) plot(timeVectorPitch,f0,“*”)轴([(110e3/fs) (135e3/fs) min(f0) max(f0)])“球场(Hz)”)包含(“时间(s)”)标题(“轮廓”

梅尔频率倒谱系数(MFCC)

MFCC是从语音信号中提取的常用特征,用于识别任务。在语音的源滤波器模型中,MFCC被理解为代表滤波器(声道)。声道的频率响应相对平稳,而浊音的来源可以建模为脉冲序列。结果是,声道可以通过语音段的频谱包络来估计。

MFCC的激励思想是基于对耳蜗的理解,将声道的信息(平滑频谱)压缩成少量的系数。

虽然没有计算MFCC的硬性标准,但图中概述了基本步骤。

mel滤波器组对前10个三角形滤波器进行线性间隔,并对其余滤波器进行对数间隔。每个波段的权重为均匀的能量。该图代表了一个典型的梅尔滤波器组。

这个例子使用了mfcc来计算每个文件的MFCC。

数据集

这个例子使用了来自Mozilla的Common Voice数据集的一个子集[1].该数据集包含48千赫的受试者说短句的录音。本节中的helper函数组织下载的数据并返回audioDatastore对象。数据集使用1.36 GB内存。

如果数据集不存在,请下载数据集并将其解压缩到tempdir

downloadFolder = matlab.internal.examples.download万博1manbetxSupportFile(“音频”“commonvoice.zip”);dataFolder = tempdir;如果~ datasetExists (dataFolder) +(字符串“无法推进”)解压缩(downloadFolder dataFolder);结束

提取10位演讲者(5位女性和5位男性)的演讲文件,并将其放入一个audioDatastore使用commonVoiceHelper函数。数据存储使您能够收集文件格式的必要文件并读取它们。当您打开此示例时,该函数将放置在当前文件夹中。

ads = commonVoiceHelper
ads = audioDatastore属性:Files:{'…\AppData\Local\Temp\commonvoice\train\clips\common_voice_en_116626.wav';’……\ AppData \当地\ Temp \无法推进\ \培训\剪辑common_voice_en_116631.wav”;\AppData\Local\Temp\commonvoice\train\clips\common_voice_en_116643.wav…{'C:\Users\jblock\AppData\Local\Temp\commonvoice\train\clips'}标签:[3;3;3.和172更分类]AlternateFileSystemRoots: {} OutputDataType: 'double' SupportedOutputFor万博1manbetxmats: ["wav" "flac" "ogg" "opus" "mp4" "m4a"] DefaultOutputFormat: "wav"

splitEachLabel的函数audioDatastore将数据存储拆分为两个或多个数据存储。生成的数据存储具有来自每个标签的指定比例的音频文件。在本例中,数据存储被分成两部分。每个标签80%的数据用于训练,剩下的20%用于测试。的countEachLabel的方法audioDatastore用于计算每个标签的音频文件数量。在本例中,标签标识说话者。

[adsTrain,adsTest] = splitEachLabel(ads,0.8);

显示数据存储和列车数据存储中的扬声器数量。

adsTrain
adsTrain = audioDatastore属性:Files:{'…\AppData\Local\Temp\commonvoice\train\clips\common_voice_en_116626.wav';’……\ AppData \当地\ Temp \无法推进\ \培训\剪辑common_voice_en_116631.wav”;\AppData\Local\Temp\commonvoice\train\clips\common_voice_en_116643.wav…{'C:\Users\jblock\AppData\Local\Temp\commonvoice\train\clips'}标签:[3;3;3.和136更分类]AlternateFileSystemRoots: {} OutputDataType: 'double' SupportedOutputFor万博1manbetxmats: ["wav" "flac" "ogg" "opus" "mp4" "m4a"] DefaultOutputFormat: "wav"
traindatastocount = countEachLabel(adsTrain)
trainDatastoreCount =10×2表标签计数_____ _____ 1 14 10 12 2 12 3 18 4 14 5 16 6 17 7 11 8 11 9 14

显示测试数据存储中的数据存储和扬声器的数量。

adsTest
adsTest = audioDatastore属性:Files:{'…\AppData\Local\Temp\commonvoice\train\clips\common_voice_en_116761.wav';’……\ AppData \当地\ Temp \无法推进\ \培训\剪辑common_voice_en_116762.wav”;\AppData\Local\Temp\commonvoice\train\clips\common_voice_en_116769.wav…{'C:\Users\jblock\AppData\Local\Temp\commonvoice\train\clips'}标签:[3;3;3.和33个更分类]AlternateFileSystemRoots: {} OutputDataType: 'double' SupportedOutputFo万博1manbetxrmats: ["wav" "flac" "ogg" "opus" "mp4" "m4a"] DefaultOutputFormat: "wav"
testdatastocount = countEachLabel(adsTest)
testDatastoreCount =10×2表标签计数_____ _____ 1 4 10 3 2 3 3 4 4 4 5 4 6 4 7 3 8 3 9 4

要预览数据存储的内容,请读取示例文件并使用默认音频设备播放它。

[sampleTrain,dsInfo] = read(adsTrain);声音(sampleTrain dsInfo.SampleRate)

从train数据存储中读取将推入读指针,以便可以遍历数据库。重置train数据存储以将读指针返回到下面特征提取的起始点。

重置(adsTrain)

特征提取

从训练数据存储中对应语音的每一帧中提取音调和MFCC特征。音频工具箱™提供audioFeatureExtractor这样你就可以快速有效地提取多个特征。配置一个audioFeatureExtractor提取沥青、短时间能量、zcr和MFCC。

fs = dsInfo.SampleRate;windowLength = round(0.03*fs);overlapLength = round(0.025*fs);afe = audioFeatureExtractor(SampleRate=fs,...窗口=汉明(windowLength,“周期”), OverlapLength = OverlapLength,...zerocrossrate = true, shortTimeEnergy = true, = true, mfcc = true);

的提取函数audioFeatureExtractor,所有特征都被连接起来,并以矩阵的形式返回。您可以使用info函数来确定矩阵的哪些列对应于哪些特征。

featureMap = info(afe)
featureMap =带字段的结构:mfcc: [1 2 3 4 5 6 7 8 9 10 11 12 13] pitch: 14 zerocrossrate: 15 shortTimeEnergy: 16

从数据集中提取特征。

Features = [];标签= [];energyThreshold = 0.005;zcrThreshold = 0.2;keepLen = round(length(sampleTrain)/3);hasdata(adsTrain) [audioIn,dsInfo] = read(adsTrain);使用每个记录的第一部分来加快代码的速度。audioIn = audioIn(1: keepplen);feat = extract(afe,audioIn);isSpeech = feat(:, featumap . shorttimeenergy) > energyThreshold;isvoices = feat(:, featumap .zerocrossrate) < zcrThreshold;voicedSpeech = isSpeech & isvocal;feat(~voicedSpeech,:) = [];feat(:,[featumap .zerocrossrate, featumap . shorttimeenergy]) = [];label = repelem(dsInfo.Label,size(feat,1));特征=[特征;壮举];标签=[标签,标签];结束

Pitch和MFCC不在同一个音阶上。这将使分类器产生偏差。通过减去平均值和除以标准差来归一化特征。

M = mean(features,1);S = std(特征,[],1);features = (features- m)./S;

训练分类器

现在你已经收集了所有10个扬声器的特征,你可以基于它们训练一个分类器。在本例中,使用k -最近邻(KNN)分类器。KNN是一种自然适用于多类分类的分类技术。最近邻居分类器的超参数包括最近邻居的数量,用于计算到邻居的距离的距离度量,以及距离度量的权重。选择超参数是为了优化测试集上的验证精度和性能。在这个例子中,邻居的数量被设置为5,所选距离的度量是平方-反加权欧几里得距离。有关分类器的更多信息,请参见fitcknn(统计和机器学习工具箱)

训练分类器并打印交叉验证精度。crossval(统计和机器学习工具箱)而且kfoldLoss(统计和机器学习工具箱)用于计算KNN分类器的交叉验证精度。

指定所有分类器选项并训练分类器。

trainedClassifier = fitcknn(特征,标签,...距离=“欧几里得”...NumNeighbors = 5,...DistanceWeight =“squaredinverse”...规范= false,...一会=独特(标签);

执行交叉验证。

K = 5;组=标签;c = cvpartition(group,KFold=k);% 5倍分层交叉验证partitionedModel = crossval(trainedClassifier,CVPartition=c);

计算验证精度。

validationAccuracy = 1 - kfoldLoss(partitionedModel,LossFun=“ClassifError”);流('\n验证精度= %.2f%%\n', validationAccuracy * 100);
验证精度= 97.69%

将困惑图表形象化。

validationforecasts = kfoldPredict(partitionedModel);图(单位=“归一化”,Position=[0.4 0.4 0.4 0.4]“验证准确性”...ColumnSummary =“column-normalized”RowSummary =“row-normalized”);

你也可以使用分类学习者(统计和机器学习工具箱)应用程序尝试并比较各种分类器与您的特征表。

测试分类器

在本节中,您将使用来自10个说话者中的每个人的语音信号测试训练好的KNN分类器,看看它在使用未用于训练的信号时表现如何。

读取文件,从测试集中提取特征,并规范化它们。

Features = [];标签= [];numVectorsPerFile = [];hasdata(adsTest) [audioIn,dsInfo] = read(adsTest);每次记录的第一部分相同,以加快代码的速度。audioIn = audioIn(1: keepplen);feat = extract(afe,audioIn);isSpeech = feat(:, featumap . shorttimeenergy) > energyThreshold;isvoices = feat(:, featumap .zerocrossrate) < zcrThreshold;voicedSpeech = isSpeech & isvocal;feat(~voicedSpeech,:) = [];numVec = size(feat,1);feat(:,[featumap .zerocrossrate, featumap . shorttimeenergy]) = [];label = repelem(dsInfo.Label,numVec);numVectorsPerFile = [numVectorsPerFile,numVec]; features = [features;feat]; labels = [labels,label];结束features = (features- m)./S;

通过呼叫预测每个帧的标签(扬声器)预测trainedClassifier

预测=预测(trainedClassifier,feature);预测=分类(字符串(预测));

将困惑图表形象化。

图(单位=“归一化”,Position=[0.4 0.4 0.4 0.4]) confusichart (labels(:),prediction,title=测试精度(每帧)...ColumnSummary =“column-normalized”RowSummary =“row-normalized”);

对于给定的文件,对每一帧进行预测。确定每个文件的预测模式,然后绘制混淆图。

r2 =预测(1:数字(adsTest.Files));Idx = 1;ii = 1:numel(adsTest.Files) r2(ii) =模式(预测(idx:idx+numVectorsPerFile(ii)-1));idx = idx + numVectorsPerFile(ii);结束图(单位=“归一化”,Position=[0.4 0.4 0.4 0.4])标签,r2,标题=测试精度(每个文件)...ColumnSummary =“column-normalized”RowSummary =“row-normalized”);

在测试的所有文件中,预测的扬声器与预期的扬声器相匹配。

参考文献

[1]Mozilla通用语音数据集