Wenet 介紹


參考資料:
感謝出門問問 的奉獻!

1.系統設計

為解決落地問題,同時兼顧簡單、高效、易於產品化等的准則,WeNet 做了如下圖的三層系統設計。

第一層為 PyTorch 及其生態。

TorchScript 用於開發模型,
Torchaudio 用於 on-the-fly 的特征提取,
DistributedDataParallel 用於分布式訓練,
Torch JIT (Just In Time) 用於模型導出,
Pytorch Quantization 用於模型量化,
LibTorch 用於產品模型的推理。

第二層分為研發和產品化兩部分。

模型研發階段,WeNet 使用 TorchScript 做模型開發,以保證實驗模型能夠正確的導出為產品模型。產品落地階段,用 LibTorch Production 做模型的推理。

第三層是一個典型的研發模型到落地產品模型的工作流。

其中:
  • Data Prepare:
數據准備部分,WeNet 僅需要准備 kaldi 風格的 wav 列表文件和標注文件。
  • Training:
WeNet 支持 on-the-fly 特征提取、CTC/AED 聯合訓練和分布式訓練。
  • Decoding:
支持 python 環境的模型性能評估,方便在正式部署前的模型調試工作。
  • Export:
研發模型直接導出為產品模型,同時支持導出 float 模型和量化 int8 模型。
  • Runtime:
WeNet 中基於 LibTorch 提供了雲端 X86 和嵌入式端 Android 的落地方案,並提供相關工具做准確率、實時率 RTF (real time factor), 延時 (latency) 等產品級別指標的基准測試。

2.模型架構

WeNet 中采用的 U2 模型,如圖所示,該模型使用 Joint CTC/AED 的結構,訓練時使用 CTC 和 Attention Loss 聯合優化,並且通過 dynamic chunk 的訓練技巧,使 Shared Encoder 能夠處理任意大小的 chunk(即任意長度的語音片段)。在識別的時候,先使用 CTC Decoder 產生得分最高的多個候選結果,再使用 Attention Decoder 對候選結果進行重打分 (Rescoring),並選擇重打分后得分最高的結果作為最終識別結果。識別時,當設定 chunk 為無限大的時候,模型需要拿到完整的一句話才能開始做解碼,該模型適用於非流式場景,可以充分利用上下文信息獲得最佳識別效果;當設定 chunk 為有限大小(如每 0.5 秒語音作為 1 個 chunk)時,Shared Encoder 可以進行增量式的前向運算,同時 CTC Decoder 的結果作為中間結果展示,此時模型可以適用於流時場景,而在流式識別結束時,可利用低延時的重打分算法修復結果,進一步提高最終的識別率。可以看到,依靠該結構,我們同時解決了流式問題和統一模型的問題。

網絡結構

Wenet 網絡結構設計借鑒 Espnet 的 joint loss 框架,這一框架采取 Conformer Encoder + CTC/attention loss, 利用幀級別的 CTC loss 和 label 級別 attention-based auto-regression loss 聯合訓練整個網絡。 (只看到了encoder的 幀級別ctc loss 和 encoder+decoder 的label級別的 ce loss )

流式 / 非流式的統一結構。

近幾年端到端的流式模型和非流式模型往往采用不同結構,一般流式方案可選用 CTC,RNN-T,Monotonic Attention 等方案,在非流式場景下,則通常使 full-attention encoder decoder 模型,犧牲流式特性的而獲得更好的識別率。但是,在兩種場景下使用兩個結構不同的模型會增加模型訓練和部署維護的成本,因此最近語音識別的一大研究熱點是如何對 流式 / 非流式的模型進行統一.
Wenet 針對工業屆的具體場景需求,兼顧流式響應速度和識別效果,采用了一套兩遍解碼的方案,用一個統一的模型結構同時有效的支持流式和非流式場景。
  • CTC 進行第一遍流式解碼,該結果可作為流式結果實時返回。
  • 多個候選結果再通過 attention-based decoder 做一遍 teacher forcing rescoring,根據得分重新排序。得到更好的識別結果。

對 Conformer 的流式改進

(encoder部分是confomer結構,要想ctc是流式的,需要對confomer進行流式改進)
原始 Conformer 結構中的 self-attention 需要對整個序列進行 attention 運算,不具備流式特點,同時 convolution 層也依賴於右側固定長度上下文,且依賴的長度隨着模型層數增多而增加。因此,都需要進行改進,保證只依賴有限長度的右側上下文,從而支持流式推斷。
對於 self-attention 層,常見流式改進方法有 chunk 法和 windows 法
  • chunk 法:將序列分成多個 chunk,每幀在 chunk 內部做 attention
  • windows 法:每幀和左右固定長度內的幀做 attention,也叫 look ahead 方法 
從左往右:全序列 attention,左側 attention,左側 + chunk 內部分 attention
green means there is a dependency, while white means there is no dependency
Full attention: Full self attention is used in standard Transformer encoder layers, every input at time t depends on the whole inputs,
Left attention: The simplest way to stream it is to make the input t only see itself and the input before t, namely left attention, seeing no right context, as shown in Figure 2 (b), but there is very big degradation compared to full context model. 只能看到左側及當前幀,來計算attention,性能差。
Chunk Attention: we split the input to several chunks by a fixed chunk size C, the dark green is for the current chunk, for each chunk we have inputs [t+1, t+2, ..., t+C], every chunk depends on itself and the all the previous chunks. Then the whole latency of the encoder depends on the chunk size.
Wenet 選擇了 chunk 方案,這種方案可以保證對右側依賴的長度與網絡層數無關。在基於 chunk 的方案中,chunk 的大小會影響着流式最大延時和模型識別率性能,大的 chunk 延時大但性能更好,小的 chunk 延時小但性能會變差。Wenet 使用了一種新的動態 chunk 訓練算法,可以使得模型的 chunk 大小動態可變,在運行時,可根據當前場景延時要求和識別率需求手動調整 chunk 大小,而無需重新訓練模型。而對於 convolution 層,Wenet 使用一個左側卷積,以支持流式推斷。
(對未來信息做mask,來模仿序列的情況。訓練的時候是dynamic chunk,任意大小的chunk都見過了。推理的時候,固定chunk,t+1時刻計算的數量是 t時刻+chunk。chunk 就是多幀一起計算,比如chunk=16,在 t時刻+16幀內,做full attention,在t時刻+16幀之后全部mask,不計算了。)

動態chunk(訓練階段):

流式: 1-25
非流式: max utterance length
下一階段改進的chunk分布:
非流式方式在每個 Epoch 中占據 50% 的比例
剩下 1-25 (40ms-1s)的 chunk 在剩余的 50% 是等比例分布的,用作流式。
 

解碼算法

Wenet 在訓練時同時使用了幀級別 deocder 的 CTC loss 和 label 級別 decoder 的 loss。因此在推斷時可以使用多種不同的解碼方式。目前 Wenet 支持四種解碼算法
  • CTC greedy beam search, 幀級別輸出,解碼過程不合並前綴,最終 n-best 上進行 ctc 序列處理。
(選每一幀概率最高的輸出,然后去重去blank,得到最終的序列輸出)
  • CTC prefix beam search , 幀級別的解碼,合並相同的 ctc 序列前綴。
  • Attention decoder beam search, 基於 cross-attention 的 label 級別解碼。
  • CTC + attention rescoring , 將 CTC decoder 的 n-best 結果,通過 attention decoder 進行重打分
CTC prefix beam search+ attention rescoring 方案可以利用 CTC decoder 的輸出作為流式結果,在損失很小准確率的情況下支持場景的流式需求,並最終利用 rescoring 改進結果,得到一個識別率更高的最終結果。
考慮一個實時字幕上屏的場景,當演講者說話時,可利用 CTC decoder 的實時輸出結果將字幕實時上屏,讓聽眾立刻看到當前演講內容的文本,在一句話結束時,會對文本內容進行重打分糾正,最終顯示和進行歸檔的文本是准確率更高的結果。手機 / 車載等語音助理也同樣適用該模式。

CTC prefix beam search

每次更新的時候,輸出的prefix序列已經是合並過blank和 帶blank的重復序列 。每個prefix包含兩個得分pb和pnb,該prefix最終的得分為pb+pnb
t 時刻 遍歷 beam*beam 個可能,分三種情況,blank、和之前重復、其他情況,分別更新 pb 和 pnb。最后根據這兩個概率和選前 beam 個。

Transformer decoder簡圖:

PS:省略了一些Transformer的基本操作

一個流程示例:

訓練: Forward, encoder 選擇full attention / dynamic chunk 跑完,根據encoder out 和 label text,計算出幀級別的ctc loss,encoder out 和 label text(shifted right)做decoder,得到的predict text 。和label text,計算label 級的ce。最后loss 按權重相加。
推理:CTC + attention rescoring 的情況:
Encoder 使用指定的chunk size 解碼,得到流式的encoder out,使用CTC prefix beam search進行解碼,得到beam 個序列hyps及其得分,encoder out 和hyps(shifted right) 去過decoder ,得到 beam個序列對應對得分(b,l,class ,最后一維做softmax,l個概率相加,得到該序列得分),在和ctc得分按權重相加,再排序。得到最好的輸出結果。
數據流維度演示
 

3.模型訓練

訓練腳本

Wenet 提供了 aishell 和 librispeech 的一鍵 recipe 示例,在 aishell 上可以達到目前業界最好的效果。

特征提取

Wenet 的數據准備非常簡單,只需 wav.scp 和 text 文件,即需要訓練的音頻文件列表和標注文本即可。提取特征在 dataloader 中利用 torchaudio 工具包完成,無需額外的特征提取步驟。
該方案一方面簡化了 pipeline,一方面可以在每個 epoch 動態使用不同的 wav augmentatio 方法.
目前 Wenet 中動態特征提取模式僅使用 fbank 特征。 在語音識別中,對於帶調的語言如中文可加入 pitch 特征,不過在實驗中發現,隨着數據量的增大和使用更好的模型結構,往往僅用 fbank 也可達到很高的性能,
另外,Wenet 也支持使用任意特征的方案,但是這種方案需要額外的特征准備步驟,將特征准備成 kaldi 的 ark 格式。
Wenet 還支持一系列可選的 augmentation 算法,如 speed perturbation,spec aug 等方法。

分布式訓練

Wenet 目前可以支持在單機單卡和單機多卡上訓練,后續會開放多機多卡的功能。

動態 chunk 訓練

Wenet 的提出了一套動態 chunk 的訓練方法,該方法在訓練時,隨機為樣本選擇不同的 chunk 大小,從而允許一個模型可處理不同 chunk 大小的輸入,當場景不需要流式識別是,可以使用整句長度作為 chunk 大小,以獲得最佳識別性能。當場景需要流式識別時,可根據場景的特點自由選擇 chunk 大小。
這種方案,在模型訓練收斂速度上並不比使用全序列 attention 慢,甚至還可以加速模型的收斂。

4.模型部署

模型導出

Wenet 模型全部由 Torchscript 編寫,可以直接導出為支持 libtorch 運行時推斷的模型,在運行時,利用 libtorch 導出的接口完成網絡前向計算,而特征提取和解碼算法則通過 C++ 代碼實現.

模型裁剪

目前 Wenet 使用 dynamic 量化來對模型進行壓縮,該量化方法對代碼結構破壞最小,而且也最為便捷。量化后的模型性能幾乎沒有損失。

實時率

實時率即處理時間 / 語音時長。更低的實時率意味着可以用更少的計算資源處理更多的語音,即能夠為企業帶來更低的服務器運營成本。通過模型量化,Wenet 的實時率在服務器端和手機端均可以達到 0.1 以下。即處理 10 秒音頻需要的時間不超過 1 秒。
Wenet 的實時率可達 0.1 以內

延時性能

語音識別中存在多種延時需要考慮,如流式識別時用戶感知到的實時回顯的延時,如一句話說完后完成整句識別的延時。我們考慮三種延時:
L1: 模型結構帶來的流式延時
L2: 重打分計算部分帶來的延時
L3: 用戶說話,到最終重打分后的結果之間的時間間隔。
Wenet 的演示非常低,其不到 0.4s 的流式延時和 0.14s 的整句延時,使得用戶在使用時幾乎感受不到延時.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM