論文地址
百度的 DeepSpeech2 是語音識別業界非常知名的一個開源項目。
本博客主要對論文內容進行翻譯,開源代碼會單獨再寫一篇進行講解。
這篇論文發表於2015年,作者人數非常多,來自於百度硅谷AI實驗室語音技術組。
論文下載地址:https://arxiv.org/pdf/1512.02595.pdf (28頁)
http://proceedings.mlr.press/v48/amodei16.pdf (10頁,本文主要介紹10頁的這個版本)
開源項目地址:https://github.com/PaddlePaddle/DeepSpeech
0. 摘要
端到端的技術的優勢是,可以用深度神經網絡替代傳統的流水線式的手工方法,使得語音識別系統可以在噪音、口音、多語言等情況下通用。
摘要主要是講 DeepSpeech2 采用了端到端的 ASR 技術,通過 HPC 技術等提高了訓練速度,可以在幾天內完成,因此可以快速迭代,從而發現更好的算法或架構。
DeepSpeech2 在一些任務上達到了 benchmark,可以與人工轉錄的結果相當。
此外,還可以在GPU上做批處理,從而可以較為容易地實現部署,可以服務大量用戶,而且延時較低。
1. 介紹
端到端的語音識別技術,是使用一個深度神經網絡去替換掉多個工程模塊,比如 bootstrapping / alignment / clustering / HMM 等,而且也可以達到SOTA的效果。
對此,可以嘗試很多深度學習的技術,需要獲取更大的訓練集,可以利用算力去訓練更大的模型,而且要有條理地去調整網絡結構。
這篇論文詳細介紹了我們對於模型結構、標注數據集、計算規模方面做的工作。包括對於模型結構的廣泛調研,以及獲取比通常的語音識別系統更多訓練數據的方法。
為了達到媲美人類水平的語音識別性能,我們在多個公開測試集上達到了benchmark。
最后,我們還在多個數據集的說話人數據間做了對比。我們發現我們最好的中文模型在轉錄簡短的語音查詢上,效果超過了一般的中文轉錄員。
本文其余部分:
第2節:對深度學習、端到端語音識別和可伸縮性的相關工作進行回顧,
第3節:介紹了模型對於體系結構和算法的改進,
第4節:介紹了如何高效地做計算,
第5節:討論了訓練數據和為進一步擴大訓練集而采取的步驟,
第6節:展示了英語和普通話的測試結果。
第7節:介紹了如何將該語音識別系統部署到實際應用環境。
2. 相關工作(隱去了參考文獻索引)
前饋神經網絡FNN的聲學模型早在二十多年前就提出了,當時RNN和CNN也被應用在了語音識別上。目前深度學習已經成為了語音識別SOTA論文的標配。
CNN在聲學模型上效果很好,RNN也部署在了SOTA的模型中,並且和CNN在特征提取上效果很好。
端到端的語音識別是目前一個熱門的研究方向,對於DMM-HMM和standalone的輸出打分效果很顯著。
結合注意力機制的RNN編碼解碼器在預測phonemes或graphemes時表現很好。
CTC損失函數與RNN對於時間信息建模,在按字符輸出的端到端的語音識別系統上效果顯著。
CTC-RNN模型在預測phonemes時表現也很好,雖然在這種情況下依然要使用語音詞典(lexicon)。
到目前為止,計算規模依然是深度學習效果提升的關鍵。在GPU上訓練可以提高性能,而當GPU數量增加時,性能也幾乎會線性提升。
GPU效率的提高,對於低層網絡基元有用。模型並行和數據並行可以用於創建一個高速的、可伸縮的系統,用於深度RNN網絡訓練語音識別。
數據也是成功的關鍵,有人用7000小時的標注數據進行了訓練。數據增強在CV及ASR領域都非常有效。
現有的語音識別系統也可以引導新數據生成,比如可以用於對齊及過濾數千小時的語音圖書。
我們受這些數據生成及增強的方法啟發,以增加我們系統的有效標注數據量。
3. 模型結構
圖1是我們的網絡結構,其中列出了的可交換組件會在下文討論。
我們系統的核心是,若干個CNN輸入層加一個RNN,后接多個單向或雙向的RNN層,及一個全連接層,一個softmax層。
我們用的是CTC損失函數,可以直接從輸入語音預測字符序列。(對於雙向RNN,使用ReLU,σ(x) = min{max{x,0}, 20} 作為激活函數)
網絡的輸入是一個指數歸一化的語音片的對數頻譜序列,窗口大小為20ms。輸出是某種語言的一些字符。
在每個輸出時間步,RNN做了預測\(p(l_t|x)\),其中\(l_t\)是字符表中的字符或者空白符。
在英語中,就是{a, b, c, ...,z,space, apostrophe, blank},我們在其中添加空格來划分單詞邊界。對於中文則是漢字。
在推斷時,CTC模型與在大規模文本上訓練得到的語言模型結合。我們使用專門的beam search來最大化 \(Q(y) = log(p_{RNN}(y|x)) + αlog(p_{LM}(y)) + β_{wc}(y)\)
其中\(wc(y)\)是轉錄文本中的字符數或者單詞數。\(\alpha\)用於調整語言模型和CTC網絡的權重。\(\beta\)允許比詞表中更多的字。這些參數可以通過在開發集上用held out留出法來調。
3.1 深度RNN網絡的batch normalization(批歸一化)
為了在擴大訓練集時有效地利用數據,我們通過添加RNN層增加了網絡的深度。但是隨着網絡大小和深度的增加,使用梯度下降也變得比較困難。
已經證實可以使用批歸一化來更快地訓練深度網絡。最近的研究表明,BatchNorm可以加快RNN訓練的收斂速度,盡管並不是總能改善泛化誤差。
相比之下,我們發現在大數據集上使用非常深的RNN網絡時,除加速訓練外,我們使用BatchNorm的變種還大大改善了最終的泛化誤差。
RNN的公式:\(h_t^l = f(W^l h^{l-1}_t + U^l h^l_{t-1} + b)\)
其中,在時間步t的l層的激活值是通過將同一時間步t的前一層\(h^{l-1}_t\)的激活值與在當前層的前一個時間步t-1的\(h^l_{t-1}\)的激活值相結合來計算的。
有兩種方式可以將BatchNorm應用到RNN操作中。
一種很自然的方式是在每次非線性操作前加上一個BatchNorm的轉換\(B(.)\)。
\(h_t^l = f(B(W^l h^{l-1}_t + U^l h^l_{t-1}))\)
但這樣的話,均值和方差在一個時間步的小批次上是累加的,這沒有效果。
另外一種方法是按序列歸一化(sequence-wise normalization),僅對垂直連接進行批量歸一化。
\(h_t^l = f(B(W^l h^{l-1}_t) + U^l h^l_{t-1})\)
對於每個隱藏單元,我們計算整個序列中小批量中所有項的均值和方差。
圖2顯示了這種方法收斂地很快。
表1顯示了按順序歸一化的性能改進隨網絡深度的增加而增加,最深層網絡的性能差異為12%。我們存儲訓練期間收集的神經元的均值和方差的移動平均值,並將其用於評估階段。
3.2 SortaGrad
即使使用批處理歸一化,我們發現使用CTC進行訓練有時還是不穩定的,尤其是在早期階段。為了使訓練更加穩定,我們嘗試了一個訓練機制,該機制可以訓練地更快,有更好的泛化性能。
從頭開始訓練非常深的網絡(或具有很多步的RNN)可能會在訓練初期失敗,因為輸出和梯度必須經過許多未調好參數的網絡層傳播。
除了梯度爆炸外,CTC經常將接近零的概率賦值給非常長的轉錄文本,從而造成梯度消失。
對於這一現象,有一種叫SortaGrad學習策略:我們將語音的長度用來衡量復雜度,並首先訓練較短(更容易)的語音。
具體來說,在第一輪訓練中,我們按minibatch中最長語音的長度,從小到大遍歷訓練集中的批次。經過第一輪之后,重新回到隨機順序。
表1比較了在具有7個循環層的9層模型上有無SortaGrad的訓練成本。
SortaGrad改善了訓練的穩定性,並且在沒有BatchNorm的網絡中,這種效果尤其明顯,因為這些網絡的數值穩定性更低。
3.3 vanilla RNN和GRU的比較(vanilla就是simple的意思,朴素,簡單)
目前我們使用的是簡單的RNN模型,用了ReLU激活方法。不過一些更復雜的RNN變種,如LSTM,GRU在一些類似任務上也是效果很好。
我們用GRU來實驗(因為在小數據集上,同樣參數量的GRU和LSTM可以達到差不多的准確率,但GRU可以訓練地更快且不易發散),
表1的最后兩列顯示,對於固定數量的參數,GRU體系結構可在所有網絡深度上實現更低的WER。
3.4 時序卷積
時序卷積是語音識別中常用的一種方法,它可以有效地建模變長語音的時序平移不變性。
與大型全連接網絡相比,時序卷積嘗試更簡潔地建模由於說話人引起的頻譜變化。
我們嘗試添加一到三層卷積。這些都在時頻域(2D)和僅時間域(1D)中。在所有情況下,我們都使用“相同”卷積。
在某些情況下,我們會跨兩個維度指定步幅(下采樣),從而減小輸出的大小。
我們展示了兩個數據集的結果:一個包括2048條語音的開發集(“ Regular Dev”)和一個噪聲更大的2048條語音的數據集(“ Noisy Dev”),這些數據是從CHiME 2015開發集中隨機采樣的。
我們發現多層的一維卷積效果一般。2D卷積可顯着改善嘈雜數據的結果,而對純凈數據卻沒有多少提升。從一層一維卷積到三層二維卷積的改變使噪聲開發集上的WER提高了23.9%。
3.5 lookahead卷積和單向模型
雙向RNN模型很難部署到實時、低延遲的環境中,因為當用戶的聲音到來時,它無法實現流式處理。
僅具有前向循環的模型通常比同類的雙向模型性能差,這意味着一定數量的下文對於效果提升至關重要。
一種可能的解決方案是延遲系統產生預測結果的時間,直到它具有更多上下文為止,但我們發現很難在模型中實現這種行為。
為了構建一個沒有損失精度的單向模型,我們開發了一種特殊的網絡層,叫做lookahead convolution。如圖3所示。
該層學習權重以線性組合每個神經元的激活時間步長\(\tau\),從而使我們能夠控制所需的下文的量。
lookahead由參數矩陣\(W∈R^{(d,τ)}\)定義,其中d是上一層中的神經元數量。在時間步t對新層的激活\(r_t\)為:
\(r_{t,i} = \sum^{τ+1}_{j=1}W_{i,j}h_{t+j−1,i},\) for 1 ≤ i ≤ d.
我們將lookahead卷積放在所有循環層之上。這使我們能夠以更精細的粒度在lookahead卷積以下做流式計算。
3.6 適配普通話
要將傳統的語音識別流水線移植到另一種語言,通常需要大量新的基於語言的開發。
例如,人們經常需要手工設計一個聲學模型。我們可能還需要明確建模基於語言的發音特征,例如普通話的音調。
由於我們的端到端系統直接預測字符,因此不再需要這些費時的工作。這使我們只需要稍微調整,就能夠使用上述方法快速創建端到端的普通話語音識別系統(輸出漢字)。
我們對網絡所做的唯一結構更改來自於字符集。該網絡輸出大約6000個字符的概率,其中包括羅馬字母,因為中英文混合轉錄很常見。
如果有字符不在表里,則會產生OOV的錯誤。不過這不要緊,因為我們的測試集僅有0.74%的字符是OOV的。
我們在普通話中使用字符級語言模型,因為通常文本沒有做分詞。
在第6.2節中,我們證明了我們的普通話語音模型在架構變化方面的改進與英文語音模型大致相同,這表明來自一種語言的建模知識可以很好地遷移給其他語言。
4. 系統優化
我們的網絡具有數以千萬計的參數,而一次訓練實驗需要幾十的單精度exaFLOPs。(exa:艾,10^18, 百億億)
由於我們評估數據和模型假設的能力取決於訓練速度,因此我們基於高性能計算(HPC)架構創建了高度優化的訓練系統(集群的每個節點有8張NVIDIA Titan X,理論峰值可提供48單精度TFLOP/s)。
盡管存在許多用於在並行計算機上訓練深度網絡的框架,但我們發現,我們良好的擴展能力通常會被未優化的例程所困擾。因此,我們專注於精心優化用於訓練的最重要例程。
具體來說,我們為OpenMPI創建了自定義的All-Reduce代碼,以求和多個節點上各個GPU上的梯度,開發了針對GPU的CTC的快速實現,並使用了自定義內存分配器。
綜合起來,這些技術使我們能夠在每個節點上維持理論峰值性能的45%。
我們的訓練使用同步SGD,將數據分配到多個GPU上並行計算,其中每個GPU復制一份模型到本地來處理當前的小批量,然后與其他所有的GPU交換計算出的梯度。
我們更喜歡同步SGD,因為它具有可重現性,這有助於發現和修復回歸。但在此模式下,GPU必須在每次迭代時快速通信(使用“all-reduce”操作),以避免浪費計算周期。
以前論文的工作已經在使用異步更新來緩解此問題。相反,我們專注於優化全減少操作本身,使用減少特定工作負載的CPU-GPU通信的技術實現了4到21倍的加速。
同樣,為了增強整體計算能力,我們使用了來自Nervana Systems和NVIDIA的高度優化的內核,這些內核針對我們的深度學習應用進行了調整。
我們同樣發現,自定義內存分配例程對於最大程度地提高性能至關重要,因為它們減少了GPU和CPU之間的同步次數。
我們還發現,CTC成本計算占運行時間的很大一部分。由於沒有開源的針對CTC進行優化的代碼,因此我們開發了一種快速的GPU實施方案,將總體訓練時間減少了10-20%。(后期會開源)
5. 訓練數據
大型深度學習系統需要大量的帶標簽的訓練數據。
為了訓練我們的英語模型,我們使用11940個小時的標記語音,包含800萬條語音,而普通話模型,使用了9400個小時的標記語音,包含1100萬條。
5.1 數據集構建
英文和普通話數據集的一部分,是從原始數據中獲取的長音頻片段,這些片段的轉錄帶有噪音。為了將音頻分割成幾個長片段,我們將語音與轉錄對齊。
對於給定的音頻-轉錄對(x, y),計算最可能的alignment:
\(l^*=argmax_{l∈Align(x,y)}\prod^T_tp_{ctc}(l_t|x;\theta)\)
這是用CTC訓練的RNN模型找到的Viterbi alignment。
由於CTC損失函數計算了所有的alignment,因此這並不能確定一個正確的alignment。然而我們發現當使用雙向RNN時,是可以產生正確的alignment的。
為了過濾出轉錄不佳的片段,我們構建了一個具有以下特征的簡單分類器:
CTC cost,音頻序列長度歸一化的CTC成本,轉錄文本長度歸一化的CTC成本,序列長度與轉錄長度之比,轉錄文本中的單詞數和字符數。
為了構建這個數據集,我們使用了大量的標簽。
對於英語數據集,我們發現filter將WER從17%降低到5%,同時保留了超過50%的樣本。
此外,我們通過給每個epoch添加SNR在0dB到30dB之間的獨立噪聲,來動態擴展數據集。
5.2 數據縮放
我們在表3中顯示了增加標注訓練數據量在WER上的效果。
這是通過在訓練之前對整個數據集進行隨機抽樣來完成的。
對於每個數據集,模型進行多達20輪epoch的訓練,並根據在開發集留出部分(驗證集)上的錯誤率使用早停機制,以防止過擬合。
訓練集大小每增加10倍,WER就會降低約40%。
我們還發現,常規數據集和嘈雜數據集之間的WER相對差距(相對值約為60%),這意味着數據量的增多對這兩種情況都有用。
6. 結果
為了更好地評估我們的語音系統在現實場景中的適用性,我們在各種測試集上進行了評估。我們使用了幾個公開可用的基准以及內部收集的幾個測試集。
所有模型都在第5節中所述的完整的英語數據集或完整的普通話數據集上訓練了20個epoch。
我們對於每個有512條聲音的小批量使用了具有Nesterov動量的隨機梯度下降法。如果梯度的范數超過閾值400,則會將其重新縮放為400。
我們選擇在訓練階段在驗證集上表現最好的模型進行評估。
在[\(1×10^{-4}\), 6×\(10^{-4}\)]范圍里選擇學習率,以達到最快的收斂速度,並在每個epoch之后以常數因子1.2進行退火。我們對所有模型都使用0.99的動量。
6.1 英語
最好的英語模型有2層2D卷積,然后是3層單向遞歸層,每個層有2560個GRU單元,然后是由BatchNorm和SortaGrad訓練的τ= 80的超前卷積層。
我們並不能使模型滿足測試集中的所有語音條件。語言模型解碼參數在留出的開發集中設置一次。
我們提供我們語音識別系統在多個測試集上的結果以及對人工轉錄的准確率的估計。
我們通過讓Amazon Mechanical Turk的工作人員手動轉錄所有測試集,以此來評估人工轉錄的准確率。
眾包工作者不如專門訓練有素的轉錄員那么准確。
之前有工作通過:根據錯誤率對轉錄員進行額外獎勵,對於打字及拼寫自動糾錯,以及讓轉錄委員會審核,在WSJ-Eval92集上達到了接近1%的人工轉錄WER。
我們采用以下沒有獎勵及自動糾錯的機制,對標競品“ASR綠野仙蹤”。
每個音頻由兩名隨機的工作人員轉錄,每個轉錄音頻平均約5秒。然后,我們將兩次轉錄中較好的一個用於最終WER計算。
大多數工作人員都位於美國,被允許多次收聽音頻,平均每次轉錄花費27秒。
人工轉錄的結果與現有的ground truth進行比較,以產生WER估計值。
盡管現有的ground truth轉錄也有一些標簽錯誤,但在大多數數據集上它都小於1%。
6.1.1 benchmark結果
具有高信噪比的閱讀語音可以說是大詞匯量連續語音識別中最簡單的任務。
我們以《華爾街日報》(WSJ)閱讀新聞文章的語料庫和由有聲讀物構建的LibriSpeech語料庫兩個測試集為基准對我們的系統進行了測試。
表4顯示,在4個測試集中,有3個測試系統的性能優於人工眾包。
我們還使用VoxForge(http://www.voxforge.org)數據集測試了系統對常見口音的魯棒性。該測試集包含多個不同口音的人的朗讀語音。
我們將這些口音分為四類:美國-加拿大口音,印度口音,英聯邦(英國、愛爾蘭、南非、澳大利亞、新西蘭)口音和歐洲(英語不是第一語言的國家)口音。
我們從VoxForge數據中構造了一個測試集,其中每種口音有1024個樣本,總共4096個樣本。我們的系統只在印度口音上超過了人工結果。
最后,我們使用來自最近結束的第3次CHiME競賽的測試集對我們在嘈雜語音上的表現進行了測試。
該數據集使用WSJ測試集的語音數據,在實際嘈雜環境中收集,而且帶有人為添加的噪聲。
使用CHiME音頻的全部6個聲道可以顯着提高性能。由於尚未普及使用多聲道音頻,因此我們對所有模型都使用一個聲道。
相比給清晰的語音添加噪音,在來自真實嘈雜環境的數據上,我們的語音識別系統與人類水平的差距更大。
6.2 普通話
在表5中,我們比較了幾種,在2000條語音的開發集和1882條嘈雜語音樣本的測試集上,對普通話進行訓練的網絡結構。
此開發集還用於調整解碼參數。我們看到,具有2D卷積和BatchNorm的最深的模型相對於淺層RNN的性能要高48%。
對於表6的兩個數據集,我們最好的普通話語音識別系統相比於人工轉錄可以更好地轉錄簡短的語音查詢。
7. 模型部署
雙向模型不是為實時轉錄而設計的:由於RNN具有多個雙向層,因此轉錄語音要求將整個語音輸入給RNN。
而且由於我們使用beam search進行解碼,因此beam search成本會很高。
為了增加部署的可擴展性,同時仍提供低延遲的轉錄,我們構建了一個名為Batch Dispatch的批處理調度程序。
該批處理調度程序將來自用戶請求的數據流組合成批進行處理,然后對這些批處理執行RNN前向傳播。
使用此調度程序,我們可以在增加批處理大小從而提高效率,和增加延遲之間進行取舍。
我們使用一個貪心的批處理方案,該方案會在上一個批處理完成后立即進行下一個批處理,而不管此時准備完成多少工作。
該調度算法平衡了效率和延時,達到了相對較小的動態批次大小(每批次至多10個樣本),服務器負載與批次大小的中位數線性相關。
我們在表7中看到,當系統加載10個並發流時,系統的中位數延遲為44ms,98百分位的延遲為70ms。該服務器使用一個NVIDIA Quadro K1200 GPU對RNN進行評估。
按此設計,隨着服務器負載能力的提高,批處理調度程序將以更大的批進行數據處理,而延遲依然保持在很低的水平。
我們的部署系統使用半精度計算評估RNN,這對精度沒有影響,但可以顯着提高效率。
我們為此任務編寫了自己的16位矩陣乘法例程,從而大大提高了相對較小批次的吞吐量。
使用beam search需要在n-gram語言模型中進行重復查找,其中大部分都是直接從內存而非緩存讀取的。
為了降低這些查找的成本,我們采用啟發式方法:僅考慮累積概率至少為p的少量字符。
在實踐中,我們發現p = 0.99效果很好,此外,我們將搜索限制為40個字符。
這樣的話,總體的普通話語言模型查找時間快了150倍,並且對CER的影響可以忽略不計(相對值0.1-0.3%)。
7.1 生產環境下的深度學習語音技術
深度學習的語音方法已經集成到面向用戶的SOTA的語音產品線中。
我們發現了一些關鍵點,這些關鍵點會影響我們端到端的深度學習模型的部署。
首先,即使使用了大量的通用語音數據用於訓練,少量基於應用場景的訓練數據也是非常寶貴的。
例如,雖然我們使用超過10,000小時的普通話語音用於訓練,但是僅有500小時的基於特定應用的數據也可以顯着提高實際應用的性能。
同樣,基於應用的語言模型對於達到高准確率也很重要,並且我們在DeepSpeech系統中使用了強大的預訓練n-gram模型。
最后,由於我們的系統是從大量帶標簽的訓練數據中訓練出來的,是直接輸出字符的,而具體的應用場景會有轉錄的特殊要求,這些需要做后處理(例如數字格式規范化)。
因此,盡管我們的模型消除了許多復雜性,但端到端的深度學習方法仍有待進一步研究,尤其是對於其適應性及基於應用場景的研究。
8. 總結
隨着數據及算力的持續增加,對於語音識別系統的提高,端到端的深度學習展現出了令人驚喜的效果。由於該方法有高度的通用性,我們可以將其應用到新的語言上。
我們構建英文及普通話這兩個性能優良的語音識別系統並沒有借助任何語言方面的專家知識。最后,我們還說明了如何將其部署到GPU上供很多用戶請求,為用戶使用端到端的深度學習技術鋪平了道路。
為了達到這一目標,我們嘗試了很多網絡結構,發現了很多有用的技術:使用Sorta Grad、批歸一化、單向模型的超前卷積來增強數值優化。
這些嘗試是在一個經過優化的、高性能計算系統上實現的,該系統使我們能夠在短短幾天之內對大型數據集進行全量的訓練。
綜上所述,我們的結果證明了端到端的深度學習技術在對於多種場景下的價值。我們相信這些技術會得到更廣泛的應用。