:從Conformer訓(xùn)練到WFST解碼的完整鏈路)
簡介一套基于深度學(xué)習(xí)的中文語音識別完整實現(xiàn)直接面向語音識別課題、畢業(yè)設(shè)計或相關(guān)競賽場景適合需要搭建中文ASR基線的開發(fā)者與高校學(xué)生。系統(tǒng)同時覆蓋聲學(xué)模型與語言模型兩大核心環(huán)節(jié)聲學(xué)端提供CNN-CTC、GRU-CTC、CNN-RNN-CTC等多種建模方案語言端提供Transformer與CBHG結(jié)構(gòu)并整合thchs30、Aishell、primewords、stc四類中文數(shù)據(jù)集可供對比實驗、消融研究和工程實踐使用。壓縮包共29個文件以Python腳本、文本標(biāo)注文件、Jupyter Notebook教程為主附帶模型權(quán)重、TensorFlow檢查點和說明文檔整體大小約108MB。其中已包含訓(xùn)練完成的迷你識別系統(tǒng)按說明加載數(shù)據(jù)即可直接運(yùn)行test.py體驗識別效果便于核對數(shù)據(jù)預(yù)處理和模型輸出流程。目前已有4100余人學(xué)習(xí)下載對于希望快速理解CTC、注意力機(jī)制與中文語音識別參數(shù)調(diào)試的學(xué)習(xí)者是一份值得收藏的完整代碼參考。1. 從一段中文音頻到文字這套說“完整”的畢業(yè)設(shè)計到底在做什么中文語音識別說白了就是讓機(jī)器把“喂”進(jìn)來的普通話音頻轉(zhuǎn)成漢字串再順手把標(biāo)點、數(shù)字、語氣詞給你規(guī)整好。這個標(biāo)題里掛著的“完整代碼報告畢業(yè)設(shè)計.zip”其實就是一條特別典型的從業(yè)路線不是讓你從零發(fā)明算法而是把一套能跑的聲學(xué)模型、解碼鏈路和訓(xùn)練數(shù)據(jù)組織方法打包給你你拿去改成自己的實驗。別被“完整”兩個字忽悠住真正的價值在于它把“中文”這個前置條件做了很多針對性處理比如拼音建模、多音字消解、熱詞干預(yù)這些拿到英文系統(tǒng)里完全用不上。這篇筆記我會沿著“能跑通的最小命令→參數(shù)怎么調(diào)→坑在哪→怎么變好用”這條線把一個基于深度學(xué)習(xí)的中文識別系統(tǒng)從里到外拆開講適合本科畢設(shè)做到一半發(fā)現(xiàn)跑不通的同學(xué)也適合想把手頭模型換到中文場景的工程師。通常這類項目的核心組件就四塊數(shù)據(jù)清洗腳本、特征提取管線、聲學(xué)模型Acoustic Model和基于詞典/語言模型的解碼器。別指望下載下來就能出完美字幕數(shù)據(jù)集、顯卡和你的耐心決定了最終 CER字錯誤率能壓到多少。下面從選型開始一步步推。2. 中文語音識別為什么難建模單元與聲學(xué)模型選型先搞清楚2.1 從拼音到漢字中文識別的兩級解碼架構(gòu)和英文的本質(zhì)差異很多人把中文識別當(dāng)成“把英文模型換套中文數(shù)據(jù)”就完事這是最大的誤解。英文可以拿字節(jié)對編碼BPE或字符直接建模而中文如果直接對漢字建模幾千個類別加上多音字問題模型收斂速度會非常難看而且對訓(xùn)練數(shù)據(jù)里的生僻字毫無泛化能力。所以你去看這類畢業(yè)設(shè)計項目的代碼結(jié)構(gòu)基本都會走“拼音/聲母韻母中間表示 漢字解碼”的兩級方案。第一級是聲學(xué)模型輸入是梅爾頻譜特征fbank或log-mel輸出是上下文相關(guān)的音子context-dependent phoneme概率分布。第二級是解碼器它拿第一級的概率和語言模型做聯(lián)合搜索把音子序列轉(zhuǎn)成帶聲調(diào)的拼音再按詞典映射到漢字。關(guān)鍵點在于“帶聲調(diào)”中文的“媽/麻/馬/罵”聲母韻母完全相同只靠聲調(diào)區(qū)分如果聲學(xué)模型輸出的音子里不包含聲調(diào)維度后面全得靠語言模型猜CER 基本沒法看。常見做法是在 target 序列里直接拼上 tone id比如m a 3表示 mǎ。這樣聲學(xué)模型既要學(xué)會發(fā)音又要學(xué)會聲調(diào)。損失函數(shù)通常用 CTCConnectionist Temporal Classification或 RNN-T但這倆對中文長句的標(biāo)點恢復(fù)能力有限所以項目里往往會再接一個標(biāo)點預(yù)測小模型或者用基于詞表的 WFST加權(quán)有限狀態(tài)轉(zhuǎn)換器解碼時帶上標(biāo)點符號。整套鏈路在推理時的代碼結(jié)構(gòu)通常是# 推理階段偽代碼實際工程里拆成 preprocess - acoustic - decode 三步 python infer.py \ --audio_path ./test.wav \ --acoustic_model ./checkpoints/epoch_50.pt \ --decoder_type wfst \ --dict_path ./data/dict_with_tone.txt \ --lm_path ./lm/zh_grammar.arpa \ --use_ton_tokens True參數(shù)說明use_ton_tokens這個開關(guān)決定了聲學(xué)模型輸出層有多少個類別開開之后類別數(shù)從幾百漲到一千多CTC 解碼時對應(yīng)路徑搜索空間也變大需要同步調(diào)高 beam size。decoder_type選 wfst 是精度優(yōu)先選 greedy 是速度優(yōu)先。這段代碼的核心邏輯是音頻先進(jìn) VAD 切分再提 fbank再過聲學(xué)模型拿概率矩陣最后解碼器搜出帶聲調(diào)的拼音串。排查問題時先用--decoder_type greedy跑一遍如果拼音串就是錯的問題大概率在聲學(xué)模型如果拼音對但漢字錯問題就在詞典或語言模型。2.2 聲學(xué)模型怎么選從 RNN-T 到 Conformer 的取舍和顯存考量畢設(shè)項目里最常見的聲學(xué)模型是三件套BiLSTM、Transformer、Conformer。選哪個直接決定你訓(xùn)練時間和顯存需求。BiLSTM 對時序建模強(qiáng)、顯存占用低但訓(xùn)練速度慢而且它對長句的上下文捕獲能力不如注意力機(jī)制Transformer 并行度高但直接用在語音上會忽略局部相鄰幀的關(guān)聯(lián)導(dǎo)致發(fā)音細(xì)節(jié)丟失。Conformer 本質(zhì)是在 Transformer 里塞進(jìn)卷積模塊既能抓全局又能保留局部發(fā)音特征是目前開源中文識別項目里的主流選擇。但 Conformer 有個“翻車”點它在跳層連接時會把相對位置編碼加在注意力層里如果你把英文預(yù)訓(xùn)練權(quán)重直接拷到中文任務(wù)上詞表對不上先不說位置編碼的維度也會炸。所以這類畢設(shè)包里的做法一般是要么從零訓(xùn)練一個小號 Conformerencoder layers 12、hidden size 256要么用基于 CTC/Attention 的混合架構(gòu)解碼時兩邊分?jǐn)?shù)加權(quán)拼起來。訓(xùn)練時我一般會這么寫配置# 聲學(xué)模型配置示例按顯存大小調(diào)節(jié) model_config { encoder: conformer, encoder_layers: 12, # 12層在單卡16G下比較穩(wěn)24層需要梯度檢查點 encoder_hidden: 256, num_attention_heads: 4, conv_kernel_size: 31, # 卷積核越大局部發(fā)音建模越細(xì)但訓(xùn)練變慢 ctc_weight: 0.3, # CTC與Attention損失的混合權(quán)重太高會忽略語言模型 predictor: lstm, # 也可換transformer但小數(shù)據(jù)集上lstm更穩(wěn) reduce_factor: 4, # 時間維降采樣倍數(shù)和fbank幀率強(qiáng)相關(guān) }這里最關(guān)鍵的兩個參數(shù)ctc_weight和reduce_factor。ctc_weight設(shè) 0.3 是常見起步值偏 0.5 以上模型會傾向輸出音素級碎片漢字對齊變差設(shè)太低又容易讓注意力部分過擬合訓(xùn)練集。reduce_factor決定模型內(nèi)部對時間軸壓縮的倍數(shù)4 意味著最終每幀代表 4 幀原始特征解碼時要把這個倍數(shù)乘回時間軸才能算出每個漢字的起止時間。如果你的音頻時長普遍在 10 秒以上reduce_factor可以提到 8 來省顯存代價是會丟失短促輔音zh、ch、sh 的持阻段的細(xì)節(jié)。這塊沒有銀彈只能在驗證集上試。3. 數(shù)據(jù)與特征把開源中文語料轉(zhuǎn)成訓(xùn)練集的三條硬經(jīng)驗3.1 數(shù)據(jù)集選用與清洗時長、采樣率、噪聲標(biāo)簽是三個坑標(biāo)題里說“完整代碼報告”你打開數(shù)據(jù)目錄會發(fā)現(xiàn)一般不是原始音頻而是已經(jīng)切好的 wav 列表和文本標(biāo)注。但切好的數(shù)據(jù)不代表能用。第一個坑是采樣率不統(tǒng)一常見中文開源語料有 16k 和 8k 兩種如果你的特征提取代碼默認(rèn)按 16k 讀8k 的音頻會被直接升采樣高頻部分全是噪聲反過來 16k 壓到 8k 會丟信息。我一般會在數(shù)據(jù)預(yù)處理腳本里強(qiáng)制統(tǒng)一# 統(tǒng)一采樣率和聲道避免訓(xùn)練時特征分布漂移 find ./data/raw -name *.wav | parallel -j 8 ffmpeg -i {} -ar 16000 -ac 1 {}.mono.wav第二個坑是標(biāo)注文本里的全角半角混用和空白字符。中文識別和英文不一樣全角空格、不間斷空格、零寬字符都會直接影響 tokenizer 生成字典的質(zhì)量。清洗規(guī)則我通常這樣寫只保留中文、英文字母、數(shù)字和常見標(biāo)點其余一律替換成空格再按字切分。注意“按字切分”不是按詞中文識別系統(tǒng)里詞邊界本來就不明確按字切分最簡單也最穩(wěn)詞級別的信息交給語言模型去補(bǔ)。第三個坑是時長過濾短于 0.3 秒的音頻基本是語氣詞或點擊聲長于 20 秒的音頻容易截斷不完整這兩類直接刪掉不然訓(xùn)練時 loss 會莫名其妙震蕩。最后看一遍標(biāo)簽對齊。如果語料自帶音素級別的對齊文件比如 TextGrid先別急著刪后續(xù)做強(qiáng)制對齊或數(shù)據(jù)增強(qiáng)都用得上。如果沒有也沒關(guān)系直接用語音活動檢測VAD把靜音段切掉再把文本按順序?qū)?yīng)上去。這里容易踩“錯位”坑音頻切了一段文本沒刪對應(yīng)句模型直接學(xué)歪。我習(xí)慣在生成訓(xùn)練列表后隨機(jī)抽 20 條人工聽一遍確認(rèn)“音頻最后一句和標(biāo)簽最后一句”對得上。3.2 特征提取與數(shù)據(jù)增強(qiáng)fbank、SpecAugment 和速度擾動別亂用特征是聲學(xué)模型的“眼”。中文識別里 fbank 比 MFCC 好用因為 MFCC 做了 DCT 去相關(guān)把對發(fā)音有用的細(xì)節(jié)抹掉了而神經(jīng)網(wǎng)絡(luò)恰恰需要保留這些相關(guān)性。特征參數(shù)建議采樣率 16k 時幀長 25ms、幀移 10ms、fbank 維度 80再加一階和二階差分拼成 240 維。有些項目會直接用 80 維不加差分靠 Conformer 的卷積自己學(xué)時域信息這樣也可以但如果你的模型是 BiLSTM差分特征能顯著加速收斂。數(shù)據(jù)增強(qiáng)這塊SpecAugment對梅爾譜圖隨機(jī)遮罩時間和頻率是中文識別里最實用的因為它直接作用在特征上不用改音頻文件。但三個“注意”時間遮罩寬度不能超過 30 幀否則長句里整段韻母被遮掉模型直接亂猜頻率遮罩別連續(xù)遮超過 7 個 bin不然聲調(diào)特征被遮掉訓(xùn)練輪數(shù)不多時比如 20 輪以內(nèi)增強(qiáng)要輕開甚至不開不然欠擬合。速度擾動把音頻變速 0.9/1.0/1.1對中文的聲調(diào)是雙刃劍它會改變音高和時長讓模型對語速更魯棒但也會讓聲調(diào)邊界變模糊。我的經(jīng)驗是先不加速擾動等模型 CER 跌不動了再帶上它做后期微調(diào)而不是一開始就全開。4. 模型訓(xùn)練與解碼鏈路跑通一個最小可用的中文識別系統(tǒng)4.1 從零開始訓(xùn)練的最小命令和 5 個關(guān)鍵訓(xùn)練參數(shù)確認(rèn)數(shù)據(jù)和特征沒問題后訓(xùn)練是最容易“玄學(xué)”的環(huán)節(jié)。別一上來就全量數(shù)據(jù)、大模型先拿 10 小時音頻跑通 pipeline驗證 loss 能降、CER 能算出來再上全量。這是唯一能避免“訓(xùn)練三天發(fā)現(xiàn)字典錯了”的后悔藥。訓(xùn)練啟動命令常見做法是# 單卡訓(xùn)練啟用混合精度節(jié)省顯存并加速 python train.py \ --train_manifest ./data/train_manifest.json \ --val_manifest ./data/val_manifest.json \ --model_type conformer \ --batch_size 32 \ --num_workers 8 \ --max_epochs 60 \ --lr 0.001 \ --warmup_epochs 5 \ --accum_grad 4 \ --use_amp True \ --save_top_k 3參數(shù)說明batch_size按“有效幀數(shù)”算比按“條數(shù)”算更準(zhǔn)。每條約 10 秒的音頻在幀移 10ms 下約 1000 幀顯存吃緊就降到 16。accum_grad是梯度累積倍數(shù)4 表示每 4 個 batch 更新一次權(quán)重相當(dāng)于把 batch_size 翻到 128這是在小顯存上壓大模型最實用的技巧。warmup_epochs對 Transformer/Conformer 必設(shè)5 輪比較中規(guī)中矩太小會導(dǎo)致初始 loss 飛升。max_epochs設(shè) 60 是底線中文數(shù)據(jù)量體積小時40 輪以后 CER 才會進(jìn)入快速下降期。use_amp建議開但開了之后 loss 偶爾出現(xiàn) NaN需要設(shè)--grad_clip_norm 5.0限制梯度范數(shù)。訓(xùn)練時除了盯 loss更重要的是盯驗證集 CER。CER 的計算和解碼強(qiáng)相關(guān)所以建議每 5 個 epoch 就跑一次完整 beam 解碼不要用訓(xùn)練時的 teacher forcing 輸出當(dāng) CER 指標(biāo)那沒意義。具體到代碼邏輯trainer 里一般會同時輸出 CTC loss 和 attention loss如果ctc_weight為 0.3總 loss 就是兩者加權(quán)加和。如果發(fā)現(xiàn) attention loss 降了但 CTC loss 不動常見原因是對齊錯誤導(dǎo)致 CTC 路徑無法收斂優(yōu)先檢查數(shù)據(jù)清洗別調(diào)模型結(jié)構(gòu)。4.2 解碼與后處理beam search、語言模型融合和熱詞干預(yù)訓(xùn)練完模型只是拿到一堆概率把它變成漢字串是解碼器的活。項目里最常用的解碼器是 beam searchbeam size 取 10 到 20 之間太大速度慢且容易出重復(fù)詞太小又把低頻正確詞剪掉。CTC 解碼時有個典型問題連續(xù)重復(fù)字符會被折疊但中文“隱隱約約”這類疊詞會被誤刪成“隱約”所以后處理里一定要加“重復(fù)字還原”邏輯規(guī)則很簡單如果音子序列里同一個漢字連續(xù)出現(xiàn)兩次且中間沒有靜音標(biāo)記就保留兩個。語言模型融合這塊常見做法是把一個 n-gram 語言模型通常用開源中文語料訓(xùn)練4-gram 足夠通過 WFST 和聲學(xué)模型概率做聯(lián)合解碼。權(quán)重設(shè)置有兩個關(guān)鍵參數(shù)lm_weight常見 0.6~1.2和word_ins_penalty常見 0.5~1.5。lm_weight越大句子越通順但容易把生僻專有名詞改成常用詞word_ins_penalty是給每個輸出的詞加懲罰值調(diào)大可減少幻覺詞。實際調(diào)參時我一般是先用 greedy 解碼算一個 CER 基線再開 beamLM如果 CER 反而漲了八成是lm_weight太大直接砍半再試。熱詞干預(yù)是中文場景里最值得做的一步。比如項目面向“智能客服買火車票”那“退改簽”“候補(bǔ)”“學(xué)生票”這些詞必須優(yōu)先出現(xiàn)。具體實現(xiàn)是給語言模型加一個熱詞列表解碼時對命中熱詞的路徑額外加獎勵分?jǐn)?shù)。但即便這樣熱詞長度超過 4 個字時單獨加分?jǐn)?shù)容易斷成兩截需要給詞典里對應(yīng)詞條也加一遍權(quán)重兩邊一致才有效。5. 中文識別訓(xùn)練和部署中繞不開的 5 個坑現(xiàn)象、原因和解決辦法5.1 坑 1訓(xùn)練集 CER 很低驗證集 CER 卻越訓(xùn)練越高典型過擬合還是數(shù)據(jù)泄露現(xiàn)象訓(xùn)練到第 30 個 epoch訓(xùn)練集 CER 已經(jīng)到 3%但驗證集 CER 從 15% 反彈到 25%。原因最常見的是過擬合中文模型參數(shù)量大小數(shù)據(jù)集上很正常另一個隱蔽原因是數(shù)據(jù)集劃分沒做“說話人隔離”同一說話人的不同句子被分到訓(xùn)練和驗證兩組模型記住了音色特征而不是語言內(nèi)容。解決先檢查驗證集里有沒有和訓(xùn)練集完全重復(fù)的句子有就刪掉。模型結(jié)構(gòu)上做三層防護(hù)dropout 開 0.1~0.2SpecAugment 增強(qiáng)強(qiáng)度隨 epoch 遞增early stopping 盯驗證集 CER。如果你發(fā)現(xiàn)驗證集 CER 在某個 epoch 突然跳高又掉回去別急著重訓(xùn)先看看那個 epoch 的 checkpoint 是不是保存了解碼結(jié)果有異常的版本很多項目保存的是 loss 最小而非 CER 最小的模型這個邏輯要改成按 CER 保存。5.2 坑 2長音頻識別時后半段漢字重復(fù)輸出成亂碼現(xiàn)象超過 15 秒的音頻識別結(jié)果后半段出現(xiàn)“你你你你你好好好”這類連續(xù)重復(fù)或直接變成無意義的“嗯嗯唉唉”。原因CTC 的尖峰分布問題。CTC 為了讓對齊路徑最短傾向把概率集中到少數(shù)高置信幀長音頻時這些尖峰之間缺少足夠幀做區(qū)分解碼器識別為同一字符多次。另外也可能是reduce_factor太大時間分辨率不夠。解決多管齊下。把reduce_factor從 8 降到 4給 CTC 加一個尖峰懲罰或者改用 RNN-T。推理側(cè)把長音頻按 VAD 切成 10~15 秒段每段獨立解碼后再按時間戳拼接。這里最容易踩的坑是拼接時直接把兩段文本接在一起沒處理段間標(biāo)點實際該補(bǔ)一個停頓標(biāo)記。我習(xí)慣在拼接邏輯里加一條規(guī)則段間間隔超過 0.5 秒自動補(bǔ)句號超過 1.5 秒補(bǔ)句號并換行。5.3 坑 3更新字庫后原有的模型權(quán)重全部失靈現(xiàn)象為了支持更多生僻字或領(lǐng)域詞你在字典里加了 50 個新字重跑訓(xùn)練后舊的 checkpoint 加載直接報維度不匹配甚至加載成功但解碼全是錯字。原因輸出層softmax 層維度變了舊權(quán)重里對應(yīng)新token id的位置是隨機(jī)初始化的。很多模型沒有把最后一層單獨保存和遷移。解決寫一個權(quán)重遷移腳本加載舊權(quán)重時將 softmax 層裁掉只遷移 encoder 部分權(quán)重新輸出層重新隨機(jī)初始化再把訓(xùn)練集里包含新字的少量數(shù)據(jù)單獨挑出來做 10~20 個 epoch 的微調(diào)。注意微調(diào)時學(xué)習(xí)率要調(diào)低一個數(shù)量級比如從 0.001 降到 0.0001否則會災(zāi)難性遺忘舊字。血淚經(jīng)驗改詞典前先備份原字典和對應(yīng) vocab 文件這是所有翻車?yán)镒钭屓吮罎⒌囊粋€因為項目報告里一般不會寫它。5.4 坑 4訓(xùn)練到一半 loss 變成 NaN之后再也降不下來現(xiàn)象第 3 個 epoch 一切正常第 4 個 epoch 剛開始 loss 突然變成 NaN重跑發(fā)現(xiàn)在同一個地方復(fù)現(xiàn)。原因fp16 混合精度下梯度下溢是罪魁禍?zhǔn)琢硪粋€可能是數(shù)據(jù)里有某個音頻文件是壞的全靜音或采樣率異常導(dǎo)致 log 特征里出現(xiàn)無窮大值。解決先定位是數(shù)據(jù)問題還是精度問題。跑一個數(shù)據(jù)完整性檢查腳本把所有音頻加載后計算能量能量小于閾值的直接歸入“靜音”文件排除。精度問題用三招訓(xùn)練腳本里加--precision 32強(qiáng)制單精度學(xué)習(xí)率調(diào)低 2 倍給優(yōu)化器加eps1e-8Adam 默認(rèn)是 1e-8但有實現(xiàn)里會設(shè)成 1e-9太小了。如果 NaN 還是周期性出現(xiàn)檢查 loss scaling 策略有些 AMP 實現(xiàn)在 loss 過大時會讓 update 失效表現(xiàn)為 loss 陡增但不是 NaN此時把init_scale調(diào)大。這問題有很強(qiáng)的“黑匣子”氣質(zhì)通常不是一句參數(shù)能解決的必須逐個排查。5.5 坑 5解碼速度慢到無法接受一句話要等三秒現(xiàn)象模型精度不錯但推理速度只有 0.3 倍實時1 秒音頻要 3 秒才出結(jié)果部署完全沒法用。原因beam size 太大語言模型在 CPU 上做 WFST 搜索太慢num_workers在推理時沒生效模型用了雙向編碼器導(dǎo)致無法做流式。解決分幾步優(yōu)化。beam size 從 20 降到 8CER 通常只漲 0.5 個點速度能快一倍語言模型用 KenLM 做預(yù)編譯的二進(jìn)制格式比加載 ARPA 文本快一個數(shù)量級如果你明知部署環(huán)境沒有 GPU訓(xùn)練時就不該選大號 Conformer而該選一個 time-depth separable 的變體或者用知識蒸餾把大模型蒸餾到小的 BiLSTM。另外別忽略 VAD 切分的價值它把靜音段過濾掉后有效解碼長度往往縮短 40%這是無痛提速收益最大的一步。最后批量解碼比單條循環(huán)快很多寫推理服務(wù)時一定把請求攢成 batch即使 batch size 只有 4GPU 利用率也能翻倍。6. 從能跑到好用一個「自定義喚醒詞」的落地姿勢模型能出字只是完成了“聽力”畢業(yè)設(shè)計想拿高分或者項目想真正被用起來還得做到“隨時可以喊得應(yīng)”。這一章分享一個不依賴額外模型的自定義喚醒詞方案只用你現(xiàn)有模型的編碼器部分。思路是這樣放棄對整句話解碼而是把聲學(xué)模型的 encoder 當(dāng)成特征提取器輸入一段 3 秒音頻取 encoder 最后一層的平均池化向量作為這句音頻的“聲紋表征”。然后對你的喚醒詞比如“小X同學(xué)”錄 20 條不同人、不同手機(jī)錄制的音頻把每條的 embedding 算出來存成模板向量。推理時計算實時音頻 embedding 和模板向量之間的余弦相似度超過閾值就觸發(fā)喚醒。這樣做的好處是復(fù)用訓(xùn)練好的模型不需要額外訓(xùn)練分類器代碼改動不超過五十行。但有兩個核心注意點一是距離度量用余弦相似度而不用歐氏距離因為不同人發(fā)音時長和音高差異會直接拉大歐氏距離。二是做對抗驗證很重要你得錄 50 條不包含喚醒詞的日常噪聲電視聲、鍵盤聲、走路聲來定閾值否則誤喚醒率會讓你崩潰。實測經(jīng)驗是閾值設(shè) 0.65 時召回高但誤喚醒多設(shè) 0.78 時誤喚醒少但喚醒詞喊三遍才應(yīng)一次通常取 0.7 起步再按“寧可多誤喚醒不可漏喚醒”的原則往低調(diào)。跑通喚醒詞后整個系統(tǒng)的完成度就不一樣了不再是“丟一段 wav 吐出文本”的離線工具而是具備“聽到關(guān)鍵詞才開始識別”能力的完整交互入口。這個能力放進(jìn)畢業(yè)設(shè)計報告里可以占據(jù)一個“系統(tǒng)創(chuàng)新點”章節(jié)篇幅不大但展示出你理解了聲學(xué)模型的中間表征含義而不只是會套開源代碼。最后說一個習(xí)慣任何模型改動先跑固定的 200 條測試音頻算 CER 再定版本不要憑感覺說效果變好了。這套流程我吃過不少虧希望幫到你。本文還有配套的精品資源點擊獲取