:特征提取與分類器全流程)
簡介面向音頻處理與機器學(xué)習(xí)初學(xué)者的MATLAB男聲女聲識別項目基于GUI圖形界面完成性別分類。資源共五個文件包含三段分別用于訓(xùn)練和測試的男女聲音頻、一個GUI布局文件以及一份完整M源碼壓縮包僅1.42MB輕量易部署。項目從讀取音頻、預(yù)處理、傅里葉變換與頻譜分析到MFCC特征提取再到SVM或神經(jīng)網(wǎng)絡(luò)分類器構(gòu)建形成完整識別鏈路界面文件保存了布局源碼實現(xiàn)按鈕回調(diào)、特征計算與結(jié)果展示可直接運行并替換自己的音頻進行驗證。已有3721人學(xué)習(xí)瀏覽既能作為MATLAB信號處理與模式識別課程的實戰(zhàn)練習(xí)也可作為語音性別識別競賽或畢業(yè)設(shè)計的基礎(chǔ)模板。整個項目在純MATLAB環(huán)境下即可完成實驗與驗證適合初學(xué)者快速掌握語音特征分析與分類器訓(xùn)練流程。1. 男女聲音識別不是玄學(xué)MATLAB里的特征與分類兩條線把一段錄音交給計算機判斷說話人是男是女這件事在MATLAB里跑通全流程只需要幾十行代碼但很多人第一次做都會翻車。男聲和女聲的差異本質(zhì)上是生理結(jié)構(gòu)差異在聲學(xué)上的映射聲帶厚薄導(dǎo)致基頻不同聲道長短導(dǎo)致共振峰位置不同。用MATLAB做男女聲音識別核心工作其實是兩條線——特征提取和分類器訓(xùn)練前者決定信息是否夠用后者決定信息怎么被利用。這個項目非常適合語音入門者驗證信號處理流程也適合有數(shù)據(jù)但缺分類思路的從業(yè)者做快速原型驗證。下面從特征參數(shù)講起逐層落到代碼和坑位。2. 特征提取基頻、MFCC與共振峰的參數(shù)怎么設(shè)2.1 基頻男聲85-180Hz、女聲165-255Hz分水嶺在這里基頻是男女聲音識別里最直觀、也最穩(wěn)定的特征。成年男性聲帶厚而長振動頻率大致落在85到180Hz女性聲帶薄而短基頻范圍大約在165到255Hz。兩個范圍有重疊區(qū)間單靠閾值切分會留下誤判但作為特征輸入分類器它貢獻的區(qū)分度非常高。MATLAB從R2019a開始內(nèi)置了pitch函數(shù)不用自己寫自相關(guān)或倒譜法輸入音頻和采樣率就能拿到逐幀基頻序列。[audioIn, fs] audioread(female_01.wav); if size(audioIn, 2) 1 audioIn mean(audioIn, 2); % 雙聲道混成單聲道避免兩個聲道數(shù)據(jù)不同步 end [f0, loc] pitch(audioIn, fs, ... WindowLength, round(fs * 0.05), ... % 幀長50ms OverlapLength, round(fs * 0.025), ... % 幀移25ms Range, [70 300]); % 基頻搜索范圍 f0Median median(f0, omitnan); % 中位數(shù)比均值更抗個別幀的野值這里幾個參數(shù)值得解釋。WindowLength設(shè)50ms而不是語音識別常用的25ms是因為基頻提取需要足夠長的周期數(shù)才能穩(wěn)定估計幀移25ms保證相鄰幀有50%重疊讓基頻軌跡平滑。Range建議鎖在[70 300]而不是默認的[60 300]能過濾掉部分低頻噪聲和咳嗽聲。最后用median而不是mean做匯總統(tǒng)計是因為錄音里經(jīng)常會有個別幀pitch估計失敗返回NaN或極端值中位數(shù)不會被這些離群點帶偏。實際項目里我一般還會把f0Median和std(f0, omitnan)一起作為兩個特征后者反映說話人語調(diào)起伏程度對區(qū)分朗讀和口語也有幫助。2.2 MFCC提取幀長25ms、13個系數(shù)的默認值是哪里來的基頻只描述了聲帶的振動快慢沒有描述聲音在頻域上的形狀。男女聲除了基頻不同聲道傳遞特性也不同——女性聲道短頻譜共振峰整體往高頻偏移。MFCC梅爾頻率倒譜系數(shù)就是用來捕捉這個頻譜包絡(luò)形狀的。MATLAB的mfcc函數(shù)把每幀音頻變換到梅爾域再做離散余弦變換輸出一組系數(shù)。第一維代表幀能量其余各維描述頻譜形狀。[coeffs, ~] mfcc(audioIn, fs, ... WindowLength, round(fs * 0.025), ... % 25ms語音識別事實標準 OverlapLength, round(fs * 0.0125), ... % 12.5ms幀移 NumCoeffs, 13); % 13維前13維保留絕大多數(shù)頻譜形狀信息 mfccMean mean(coeffs(:, 2:end), 1); % 丟掉第1維能量只留MFCC25ms幀長、10ms左右?guī)剖钦Z音領(lǐng)域的經(jīng)驗參數(shù)理論上窗越短時間分辨率越高但頻率分辨率越差25ms是兩者平衡點。NumCoeffs用13是HTK時代的習(xí)慣低維系數(shù)描述頻譜包絡(luò)的整體走向高維系數(shù)描述細節(jié)對性別分類來說細節(jié)部分反而容易帶進說話人個性噪聲所以13夠用。MFCC在幀和幀之間是短時平穩(wěn)的但整個句子里不同位置的音素不同簡單求平均會把音素差異抹掉。我的做法是把mfccMean和std(coeffs(:, 2:end), 0, 1)即每一維的標準差拼接起來這樣既保留平均頻譜形狀又記錄了頻譜隨時間的變化幅度。這一步對短音頻尤其重要后面避坑章節(jié)會細說。2.3 共振峰與短時能量補特征還是補噪聲共振峰是聲道諧振產(chǎn)生的頻譜峰值成年女性由于聲道短前三個共振峰F1-F3平均比男性高20%左右。MATLAB沒有現(xiàn)成的共振峰提取函數(shù)常見做法是用LPC線性預(yù)測系數(shù)求解多項式根來推算。做法不復(fù)雜但共振峰估計對噪聲極敏感真實錄音里一個電話信道就把高頻共振峰壓沒了所以我不建議把它當作主力特征。[ar, ~] lpc(audioIn, 12); % 12階LPC覆蓋4個共振峰左右 rts roots(ar); % 多項式根 rts rts(imag(rts) 0); % 只保留復(fù)平面上半部分 angles atan2(imag(rts), real(rts)); formantHz sort(angles * fs / (2 * pi)); % 換算成頻率這個代碼塊在干凈錄音上能得到相對合理的F1-F3估計但也僅此而已。實戰(zhàn)中我會把共振峰特征作為可選項當數(shù)據(jù)集是麥克風(fēng)近場錄音時加上前三個共振峰頻率能提升一到兩個百分點的準確率當數(shù)據(jù)來源混雜比如一部分是手機錄音、一部分是電話錄音時共振峰引入的噪聲遠大于信息量不加。短時能量同理男聲通常比女聲略低但能量受錄音距離影響太大同一句話遠近各錄一遍能量差異比性別差異還大。特征選取的邏輯是優(yōu)先選物理機制明確且對錄音條件不敏感的特征基頻和MFCC屬于前者共振峰和能量屬于后者。3. 分類器選型SVM、決策樹與kNN的實戰(zhàn)對比3.1 用fitcecoc包SVMRBF核與標準化是默認動作特征提取完后男女聲音識別就是一個典型的二分類問題。在樣本量幾百到幾千這個區(qū)間支持向量機是穩(wěn)定度最高的選擇。MATLAB里直接調(diào)fitcecoc就可以完成多分類封裝二分類時它等價于訓(xùn)練一個標準的SVM。選擇RBF核是因為性別分類的特征邊界不是線性的——基頻和MFCC之間存在交互關(guān)系線性核在這個任務(wù)上表現(xiàn)明顯差一截。svmModel fitcecoc(features, labels, ... Learners, templateSVM(KernelFunction, rbf, ... KernelScale, auto), ... Standardize, true, ... Prior, empirical);KernelScale設(shè)成auto讓MATLAB根據(jù)訓(xùn)練數(shù)據(jù)自動估計RBF核的尺度參數(shù)省去手動調(diào)參。Standardize一定要設(shè)true因為MFCC均值在幾十的量級基頻中位數(shù)只有一百多標準差不一致會導(dǎo)致RBF核的距離計算被大數(shù)值維度主導(dǎo)。Prior設(shè)empirical表示按訓(xùn)練集中男女樣本的比例自動調(diào)整先驗概率這一步對處理不平衡數(shù)據(jù)特別重要后面避坑章節(jié)會展開。這套配置在我的實測里對干凈語音數(shù)據(jù)集通常能拿90%以上的準確率而且基本不需要調(diào)參。3.2 決策樹和kNN什么時候可以替代SVM決策樹的特點是訓(xùn)練極快、結(jié)果可解釋能直接看出模型用了哪些特征、閾值是多少。fitctree在特征維度不高時表現(xiàn)不錯而且對數(shù)據(jù)分布沒有假設(shè)男女樣本重疊嚴重時也沒問題。但它對特征縮放不敏感不需要標準化代價是決策邊界是軸對齊的矩形在特征耦合較強的數(shù)據(jù)上精度上限不如SVM。kNN的思路更樸素——新樣本距離誰近就歸誰。treeModel fitctree(features, labels, ... MaxNumSplits, 20, ... % 限制樹的復(fù)雜度防止深樹過擬合 SplitCriterion, gdi); % 基尼不純度 knnModel fitcknn(features, labels, ... NumNeighbors, 5, ... Distance, cosine); % 余弦距離在高維特征上比歐氏距離更穩(wěn)定MaxNumSplits設(shè)20意味著允許最多20個分支節(jié)點對二分類問題通常夠用。限制深度是一種正則化——決策樹如果不限深會逐幀記住訓(xùn)練集里的噪聲訓(xùn)練準確率接近100%測試集立刻掉回75%。kNN的NumNeighbors設(shè)奇數(shù)在二分類里可以避免平票5是默認起點樣本少時可以降到3樣本多時提到7效果差別不大。kNN在推理時要計算新樣本與所有訓(xùn)練樣本的距離當訓(xùn)練集超過幾千條時單次預(yù)測耗時明顯上升實時性要求高的場景不推薦。3.3 數(shù)據(jù)集劃分與交叉驗證分層抽樣決定結(jié)果可信度分類器選完下一步就是驗證它到底行不行。很多人在這一步犯的錯誤是隨機劃分訓(xùn)練集和測試集導(dǎo)致某個人的語音片段同時出現(xiàn)在兩邊——雖然測試集和訓(xùn)練集來自同一個說話人模型記住了這個人的音色測試準確率虛高到95%以上但換成一個陌生說話人立刻崩盤。正確的做法是分層抽樣并按說話人去切。cv cvpartition(labels, KFold, 5, Stratify, true); for i 1:cv.NumTestSets trainIdx cv.training(i); testIdx cv.test(i); model fitcecoc(features(trainIdx, :), labels(trainIdx), ... Learners, templateSVM(KernelFunction, rbf, KernelScale, auto), ... Standardize, true); pred predict(model, features(testIdx, :)); acc(i) sum(pred labels(testIdx)) / numel(testIdx); end meanAcc mean(acc);KFold設(shè)5代表五折交叉驗證每次用4/5數(shù)據(jù)訓(xùn)練、1/5驗證循環(huán)五次取平均。Stratify必須設(shè)true它保證每一折里男女比例和全量數(shù)據(jù)一致避免某一折全是女聲導(dǎo)致模型在這個fold上直接失分。如果你的數(shù)據(jù)集里有重復(fù)說話人記得先把同一個人的所有語音分到同一折里這需要你手動構(gòu)造分組信息cvpartition本身不知道哪些文件屬于同一個人。SVM在特征經(jīng)過標準化后會有額外開銷但五折交叉驗證的整體耗時通常在幾十秒量級完全可接受。4. 用MATLAB跑通“采集→特征→訓(xùn)練→預(yù)測”全流程4.1 audioDatastore按文件夾批量讀取標簽從目錄名來寫完整流程的第一步是把散落的音頻文件組織成帶標簽的數(shù)據(jù)集。常見做法是建兩個文件夾male目錄放男聲錄音female目錄放女聲錄音然后讓audioDatastore自動掃描子目錄用子目錄名生成標簽。這個方案的好處是后續(xù)只有新增數(shù)據(jù)不用改代碼往文件夾里丟文件就行。ads audioDatastore(data, ... IncludeSubfolders, true, ... LabelSource, foldernames);data目錄下面直接放male和female兩個子文件夾。IncludeSubfolders設(shè)true才會遞歸掃描子目錄。LabelSource設(shè)foldernames告訴MATLAB把文件所在子目錄的名字作為該文件的標簽生成的結(jié)果是categorical類型方便后面直接喂給分類器。錄音格式不限制wav、mp3、m4a都能讀但建議盡量統(tǒng)一成wavMP3經(jīng)過有損壓縮會抹平一部分高頻細節(jié)這些細節(jié)對MFCC的前幾維影響不大但會污染共振峰相關(guān)特征。4.2 批量特征提取與拼接把音頻變成特征矩陣音頻數(shù)據(jù)按batch讀入后要對每條錄音做相同流程的預(yù)處理和特征提取。這里有幾個隱藏細節(jié)每條錄音的長度不同所以MFCC幀數(shù)不同直接用全部幀拼特征會有對齊問題。我的做法是逐條提取特征后在時間維上做聚合統(tǒng)計把每條音頻壓縮成一個固定長度的行向量最后拼成一個大矩陣。allFeatures []; allLabels []; while hasdata(ads) [audioIn, info] read(ads); fs info.SampleRate; if size(audioIn, 2) 1 audioIn mean(audioIn, 2); end audioIn audioIn / max(abs(audioIn)); % 峰值歸一化消除錄音音量差異 f0 pitch(audioIn, fs, ... WindowLength, round(fs * 0.05), ... OverlapLength, round(fs * 0.025), ... Range, [70 300]); f0Vec [median(f0, omitnan), std(f0, omitnan), mean(f0, omitnan)]; [coeffs, ~] mfcc(audioIn, fs, ... WindowLength, round(fs * 0.025), ... OverlapLength, round(fs * 0.0125), ... NumCoeffs, 13); mfccFeat [mean(coeffs(:, 2:end), 1), std(coeffs(:, 2:end), 0, 1)]; featVec [f0Vec, mfccFeat]; % 3 24 27維特征 allFeatures [allFeatures; featVec]; %#okAGROW allLabels [allLabels; info.Label]; %#okAGROW endaudioIn / max(abs(audioIn))這一步很容易被跳過但對真實錄音影響很大——不同設(shè)備錄音的音量差異能到10倍以上不做歸一化的話能量相關(guān)的分量會把分類器帶偏。特征向量一共27維基頻中位數(shù)、基頻標準差、基頻均值再加12維MFCC均值和12維MFCC標準差。std在MFCC上用的是0權(quán)重即除以N-1這也是MATLAB默認。4.3 訓(xùn)練與五折交叉驗證一張混淆矩陣看透結(jié)果特征矩陣和標簽都準備好了接下來進入訓(xùn)練階段。我習(xí)慣先跑一遍五折交叉驗證確認模型穩(wěn)定再在全部數(shù)據(jù)上重新訓(xùn)練最終模型。features allFeatures; labels allLabels; featuresNorm zscore(features); % 全局標準化保存均值和標準差供預(yù)測復(fù)用 rng(42); % 固定隨機種子結(jié)果可復(fù)現(xiàn) cv cvpartition(labels, KFold, 5, Stratify, true); acc zeros(cv.NumTestSets, 1); confMat zeros(2, 2); for i 1:cv.NumTestSets trainIdx cv.training(i); testIdx cv.test(i); model fitcecoc(featuresNorm(trainIdx, :), labels(trainIdx), ... Learners, templateSVM(KernelFunction, rbf, KernelScale, auto), ... Standardize, false); % 已用zscore標準化這里關(guān)掉避免雙重標準化 pred predict(model, featuresNorm(testIdx, :)); acc(i) mean(pred labels(testIdx)); confMat confMat confusionmat(labels(testIdx), pred); end fprintf(平均準確率: %.2f%%\n, mean(acc) * 100);rng(42)固定隨機種子讓交叉驗證的結(jié)果可以復(fù)現(xiàn)這在調(diào)參時很重要——不固定種子的話每次跑結(jié)果都在波動你沒法判斷一個參數(shù)改動是真實提升還是隨機波動。zscore要放在交叉驗證之前做還是放在每折內(nèi)部做其實有講究。嚴格來說應(yīng)該在訓(xùn)練折上計算均值和標準差再應(yīng)用到測試折上避免測試集信息泄漏到標準化里但樣本量大時兩者結(jié)果幾乎無差別這里為了簡化代碼用了全局標準化。如果追求嚴謹把標準化放進循環(huán)內(nèi)部即可。最后的混淆矩陣對角線元素之和除以總樣本數(shù)和平均準確率應(yīng)該一致兩者互為校驗。4.4 單條錄音的預(yù)測上線前的最后一步模型訓(xùn)練完成后實際使用場景是給一條新的錄音輸出一個性別標簽。這中間要做的不是直接調(diào)用predict而是把訓(xùn)練階段那套預(yù)處理和特征提取邏輯原封不動地搬過來否則特征對不上模型預(yù)測毫無意義。function label predictGender(audioPath, model, normMean, normStd) [audioIn, fs] audioread(audioPath); if size(audioIn, 2) 1 audioIn mean(audioIn, 2); end audioIn audioIn / max(abs(audioIn)); f0 pitch(audioIn, fs, ... WindowLength, round(fs * 0.05), ... OverlapLength, round(fs * 0.025), ... Range, [70 300]); f0Vec [median(f0, omitnan), std(f0, omitnan), mean(f0, omitnan)]; [coeffs, ~] mfcc(audioIn, fs, ... WindowLength, round(fs * 0.025), ... OverlapLength, round(fs * 0.0125), ... NumCoeffs, 13); mfccFeat [mean(coeffs(:, 2:end), 1), std(coeffs(:, 2:end), 0, 1)]; featVec [f0Vec, mfccFeat]; featVecNorm (featVec - normMean) ./ normStd; % 用訓(xùn)練集的統(tǒng)計量標準化 label predict(model, featVecNorm); end這個函數(shù)把流程封裝成了一個可復(fù)用的入口。normMean和normStd是訓(xùn)練時zscore返回的均值和標準差必須在訓(xùn)練階段保存下來。要注意這里處理的是單條短音頻如果音頻超過10秒建議切段后逐段預(yù)測再投票因為整段求出均值會把前半段說話、后半段沉默的情況抹平導(dǎo)致特征被拉向中間值。這個細節(jié)在真實場景出現(xiàn)頻率很高下一章詳細展開。5. 避坑五個讓識別模型翻車的常見問題5.1 訓(xùn)練集準確率99%、測試集70%特征里混進了錄音環(huán)境交叉驗證結(jié)果遠低于訓(xùn)練集這是最常見的翻車現(xiàn)場。男女聲音識別里訓(xùn)練集和測試集如果來自不同設(shè)備MFCC特征會把麥克風(fēng)的頻響特性一起學(xué)進去。我遇到過用一套錄音設(shè)備的數(shù)據(jù)訓(xùn)練到另一套設(shè)備上測試準確率直接從92%掉到71%的情況。原因在于MFCC描述的是頻譜包絡(luò)而頻譜包絡(luò)里既有聲道形狀生理特征也有錄音設(shè)備的濾波特性環(huán)境特征SVM無法自動區(qū)分這兩者。解決思路有兩個方向。第一個是數(shù)據(jù)層面訓(xùn)練數(shù)據(jù)盡可能覆蓋多設(shè)備、多場景讓分類器學(xué)到的是聲帶差異而不是麥克風(fēng)差異。第二個是特征層面把MFCC做倒譜均值歸一化CMN減去整段音頻MFCC的均值。MATLAB里手動實現(xiàn)就是coeffs coeffs - mean(coeffs)這能去掉大部分線性信道畸變。兩個做法都做效果最好。5.2 pitch返回一堆NaN搜索范圍和采樣率沒對齊pitch函數(shù)返回的f0里如果出現(xiàn)大量NaN說明你的音頻可能根本不是預(yù)期采樣率或者搜索范圍設(shè)得太窄。我踩過一次某批wav文件標注是44.1kHz實際是16kHz的mp3轉(zhuǎn)碼來的audioread返回的實際Fs就是16kHz代碼里寫的幀長參數(shù)是按44.1kHz算的等效窗長從50ms變成了138ms基頻軌跡亂七八糟。解決方法是每次audioread之后直接用返回的fs計算窗口參數(shù)不要寫死。另外檢查Range——如果錄音里有壓著嗓子的氣聲基頻可能跌到70Hz以下被過濾掉。我的習(xí)慣是先用[50 400]跑一遍看統(tǒng)計分布再決定要不要收窄到[70 300]。調(diào)試時打印sum(isnan(f0)) / numel(f0)如果超過20%就要回頭查數(shù)據(jù)了。5.3 所有測試樣本都判成男聲數(shù)據(jù)不平衡與先驗糾纏模型把測試集里的女聲也判成男聲說明訓(xùn)練集里男聲樣本遠多于女聲SVM的決策邊界被先驗概率推向了女聲一側(cè)。fitcecoc默認假設(shè)類別先驗均勻當實際比例是8:2時模型會在置信度上偏向多數(shù)類。解決方法是顯式設(shè)置Prior參數(shù)。除了empirical讓MATLAB按訓(xùn)練集比例自動估計更穩(wěn)妥的方案是做類別加權(quán)給少數(shù)類更高的權(quán)重讓決策邊界重新居中。數(shù)據(jù)擴充是另一個方向——把女聲樣本做變速和加噪在特征空間里等價于女聲樣本周圍多了合法鄰居SVM的支撐向量會把這部分空間重新劃分。兩者可以疊加使用效果比單方面調(diào)整閾值要好。5.4 mfcc矩陣形狀對不上幀長與音頻時長不匹配當音頻短于一個窗長時mfcc返回空矩陣或行數(shù)極少的矩陣后續(xù)mean(coeffs)直接報錯。這個問題在真實場景比想象中更常見——我用手機錄過長按語音消息生成的文件只有0.3秒整個音頻還不夠一幀MFCC使用。解決思路是設(shè)置最小音頻時長門檻處理前先判斷numel(audioIn) fs * 0.5就跳過該條數(shù)據(jù)或補零到0.5秒。補零會引入假的頻譜形狀所以我傾向直接過濾。另外幀移參數(shù)如果設(shè)成round(fs * 0.0125)短音頻產(chǎn)生的幀數(shù)很少幀與幀之間的統(tǒng)計量方差會非常大這也是短音頻判別結(jié)果不穩(wěn)定的根源。建議少于2秒的錄音不要直接進模型而是先按0.5秒一段切片取多數(shù)投票。5.5 程序跑到一半內(nèi)存爆炸循環(huán)里數(shù)組不斷變長批量特征提取的循環(huán)里用allFeatures [allFeatures; featVec]是可以跑的但樣本量超過幾千以后MATLAB每次拼接都要重新分配整塊內(nèi)存運行速度會以指數(shù)級下降最后直接內(nèi)存溢出。這在純技術(shù)層面是個性能問題在工程層面是數(shù)據(jù)規(guī)模增長必然遇到的瓶頸。兩個常見的優(yōu)化方向。一是預(yù)分配先統(tǒng)計ads里的文件總數(shù)numel(ads.Files)按這個數(shù)預(yù)分配一個大矩陣再用索引填入。二是改用tall數(shù)組或直接寫parfor并行處理每個文件獨立提取特征再合并天然適合并行。我一般會先用預(yù)分配解決90%的場景數(shù)據(jù)量到幾萬條再考慮并行。內(nèi)存問題看起來不起眼但處理一整夜數(shù)據(jù)跑到一半崩潰的體驗真的很痛。6. 進階說話人歸一化與數(shù)據(jù)增強把準確率再往上推一檔6.1 說話人歸一化去掉個性留性別共性基線模型能到90%左右以后再往上提就進入精調(diào)階段。男女聲音識別有一個獨特優(yōu)勢基頻的絕對值其實混合了“性別信息”和“個人音色”兩個因素。一個嗓門粗的女低音和一個聲線高的男聲單看基頻中位數(shù)可能完全重疊。說話人歸一化的思路是把每條音頻的基頻軌跡除以該條音頻的基頻中位數(shù)把絕對頻率變成相對變化模式。f0Norm f0 / median(f0, omitnan); f0StatNorm [std(f0Norm, omitnan), iqr(f0Norm), mean(f0Norm)];歸一化后保留了語調(diào)起伏的相對模式抹掉了說話人本身的絕對音高這在跨說話人場景下能顯著提升泛化能力。代價是如果測試時輸入只有一句話、音高變化范圍太小歸一化后的特征會變得不穩(wěn)定所以這種方法在長音頻上效果好于短音頻。前后對比可以用五折交叉驗證正確率來評判提升通常在1到3個百分點之間。6.2 數(shù)據(jù)增強三件套變速、加噪、音量抖動數(shù)據(jù)集只有幾十條語音時模型再調(diào)也就那樣。擴大訓(xùn)練集最便宜的方式不是去網(wǎng)上找數(shù)據(jù)而是對已有數(shù)據(jù)做增強。語音領(lǐng)域最常用的三件套是變速、加噪和音量抖動。變速保持基頻不變、時長變化模擬說話快慢差異加噪讓模型見過不干凈的環(huán)境音量抖動模擬不同錄音距離。MATLAB里變速用shiftPitch或者audioread后重采樣再插值都可以最簡單的實現(xiàn)是把音頻用resample插值后播放長度變化但音高也變了其實這已經(jīng)足夠破壞掉一部分設(shè)備特征達到增強目的。對MFCC類特征來說只要增強了頻譜形狀和基頻的多樣性模型的魯棒性就會提升具體增強倍數(shù)建議每類數(shù)據(jù)翻三倍左右再多容易過擬合到噪聲模式上。6.3 驗證方法留一個陌生說話人出來交叉驗證能防止隨機波動但它測不出模型的真實泛化能力。我最后都會做一個留出性驗證把所有訓(xùn)練文件按說話人分組隨機挑出兩個陌生說話人的所有音頻不參與訓(xùn)練只做測試。這個測試模擬的是真實使用場景——來的永遠是沒見過的新說話人。這里有一個很容易被忽略的點同一個人的不同音頻在交叉驗證里會被分到不同折模型實際上已經(jīng)“見過”這個人了準確率偏樂觀。按說話人做分組交叉驗證才接近真實水平。如果這個準確率能穩(wěn)定在85%以上這個模型才算真正可以落地。我最早做這個項目時沒有按說話人分組模型在見過的人上表現(xiàn)優(yōu)秀一換陌生人立刻掉到75%。后來把說話人信息顯式編碼到交叉驗證分組里才看到真實水平。希望這個驗證方法能幫你少走一段彎路。本文還有配套的精品資源點擊獲取