本文介紹了作者所在團隊為了實現語音識別領域的“ImageNet 時刻”所做的努力,以及相關研究成果。這些成果只需要比較少的投入和資源就可以應用在實際生產環境,與傳統學術研究相比更接地氣。
語音轉文本(STT),也稱為自動語音識別(ASR),這項技術由來已久,並在過去十年中取得了驚人的進步。如今在業界,人們一般認為只有像谷歌、Facebook 和百度(在俄羅斯境內則是政府支持的那些本地壟斷企業)之類的大公司才能提供可部署的“接地氣”的解決方案。這主要是出於以下幾個原因:
- 研究論文中普遍存在的海量計算需求,是在人為地設置較高的入門門檻;
- 由於詞彙、講話人和壓縮技術都是多種多樣的,語音數據量非常龐大;
- 拋棄較為實用的解決方案,轉而採用不切實際但技術上更前沿的方案(SOTA)的心態很普遍。
這篇文章介紹了我們為緩解這些矛盾而針對各國語言(包括俄語)所做的各種努力:
- 引入了 20,000 小時的 OpenSTT 多樣性數據集,基於 CC-NC-BY 許可證分享;
- 證明了只使用兩塊在市面上隨處可見的消費級 GPU,就可以獲得頗具競爭力的成果;
- 給出了不同的設計模式,幫助廣大人工智能研究人員和從業者進入語音識別領域。
簡介
隨著計算機視覺技術的蓬勃發展和廣泛普及(也就是所謂的“ImageNet 時刻”,具體來說就是在硬件需求下降、產品上市時間縮短、數據集規模也儘量縮減之後,可部署產品開始紛紛湧現),一個合理的展望就是機器學習(ML)技術在其他分支領域也很快會大放異彩。唯一的問題是,其他領域中這樣的轉折點何時會到來,其前提條件都有哪些?
我們認為,一個 ML 分支領域中的 ImageNet 時刻出現時會有以下表現:
- 能夠解決 95%的標準“實用”任務所需的架構和模型構建塊,已成為標準化和經過驗證的開源框架模塊得到了廣泛應用;
- 多數流行的模型都提供了預訓練的權重;
- 成功將預訓練模型標準任務上獲得的知識應用在多種多樣的日常任務中;
- 與初期在論文中報告的計算需求(在 STT 領域一般是 100-1000 個 GPU 日)相比,訓練日常任務模型所需的計算量控制在了很低的水平(例如在 STT 領域中只需 1-10 個 GPU 日);
- 小型獨立公司和研究小組也有能力使用大型預訓練模型來處理計算任務。
如果上述條件都能滿足,那麼從業者就能夠以合理的成本來開發新的實用性的應用。行業中的民主化也會隨之而來:人們不必再依賴像谷歌這樣的大公司作為行業中的唯一真相來源。
這篇文章將介紹我們為了邁向 STT 領域中的 ImageNet 時刻所做的工作。到目前為止這一轉折點尚未出現,在俄語範圍尤其如此。我們的主要目標是在有限的計算資源預算限制內,儘快構建和部署實用的模型,並共享我們的努力成果,希望其他人可以基於我們的發現,為 STT 領域實現 ImageNet 時刻而攜手前進。
為什麼我們不以學術論文的形式發表?這並不是傳統的經過同行評審的研究論文,而是對我們結合現有思想和技術,向有用和實用的 STT 邁進的務實努力的總結。我們決定以這種形式來分享,而不是在會議或 arxiv 上以論文的形式發表,這樣我們的發現就能得到更廣泛的傳播。雖說用來確保技術正確性的同行評審是有意義的,但由於我們使用了很多現有的構想,外加我們得出的經驗結果支持,所以我們對自己的主張充滿信心。我們將專門討論,為什麼我們認為當前的同行評審和企業支持的研究並不是促進整個社會進步的最快途徑。簡單來說,儘管這些有缺陷的系統長期來看是能發展起來的,但從短期來看有更快的方法可以取得進展。簡而言之,本文介紹的想法確實可以應用在生產環境中,並且已經在其他領域接受過了驗證。更重要的是——它們中的大多數都很接地氣,不需要昂貴的硬件或成噸的代碼。我們歡迎大家提出反饋和批評意見——[email protected]
相關工作和啟發
在實驗中我們選擇了以下技術:
- 用於聲學建模的前饋神經網絡(主要是基於 squeeze-and-excitation 和 transformer 模塊的分組 1D 卷積);
- 連接主義時間分類損失(CTC 損失);
- 由字素(即字母)組成的複合詞,作為建模單位(與音素相對);
- 使用預訓練語言模型(LM)作為解碼器進行束搜索。
STT 有很多方法可用,這裡就不具體展開了。本文所介紹的是主要使用字素(即字母)和神經網絡的端到端方法。
簡而言之——要訓練一個端到端字素模型,你只需大批帶有對應文本的小型音頻文件即可,也就是 file.wav 和 transcription.txt。你還可以使用 CTC 損失來降低對同步註釋的需求(否則你需要自己提供一個同步表,或在網絡中學習同步方式)。一種常見的 CTC 損失替代方法是帶有注意力的標準分類交叉熵損失,但它訓練起來很慢,而且一般是和 CTC 損失並用的。
選擇這個技術棧主要原因如下:
- 可擴展性。添加 GPU 即可擴展計算能力;
- 不會過時。如果出現了新的主流神經網絡模塊,僅需要幾天時間就可以進行集成和測試,遷移到另一個框架也很容易;
- 簡單易用。因為用的是 Python 和 PyTorch,所以你可以專心做實驗;
- 靈活性。新特徵只需花幾天時間用 Python 寫好代碼就可以測試了;
- 不在解碼器、音素或遞歸神經網絡中使用注意力模型,所以收斂速度更快,模型的維護需求也更少。
開放語音轉文本(俄語)
據瞭解,目前所有公開可用的有監督英語數據集都少於 1,000 小時,並且可變性非常有限。 DeepSpeech 2 這篇深度 STT 論文建議,至少需要 10,000 小時的註釋才能構建一套不錯的 STT 系統。1,000 小時也能入門,但是考慮到泛化差距,你需要大約 10,000 小時的分佈在不同域中的數據。
典型的學術數據集有以下缺點:
- 過於理想。與真實場景相比音質太好;
- 域太窄。STT 的難度遵循以下簡單公式:噪音水平詞彙量說話者人數;
- 一般只有英文音頻數據。儘管像 Common Voice 這樣的項目一定程度上解決了這個麻煩,但是除德語和英語以外,其他語言很難找到大量可用數據。另外 Common Voice 可能更適合說話者識別任務,因為它們的文本不夠多樣化;
- 壓縮方式不同。Wav 文件幾乎沒有壓縮,但現實世界中的音頻文件可能存在多種壓縮算法。
我們決定收集併發佈一個前所未有的俄語口語語料數據集。我們一開始的目標是 10,000 小時,這個數據集的大小在英語語料庫中也很罕見。
最近我們發佈了這套數據集的 1.0-beta 版本。它包括以下域:
我們的數據收集過程如下:
- 收集一些數據,然後用啟發式方法清理;
- 訓練一些模型,並使用這些模型進一步清理數據;
- 收集更多數據,並對齊文本與音頻;
- 訓練更好的模型,並使用這些模型進一步清理數據;
- 收集更多數據並手動標註一些數據;
- 重複所有步驟。
我們的語料庫在此,也可以在這裡支持我們的數據集。
雖說成果不錯,但我們還沒有完成。我們的短期計劃是:
- 做一些整理,進一步清理數據,並清理一些舊代碼;
- 遷移到.ogg,以在保持質量的前提下儘量節省空間;
- 添加幾個新域(法庭記錄、醫學講座和研討會、詩歌)。
實現出色的語音轉文本模型
一個出色的 STT 模型需要具備以下特徵:
- 快速推斷;
- 參數高效;
- 易於維護和改進;
- 訓練時不需要大量計算資源,一臺 2x1080 Ti 的機器就足夠了;
這些是我們的目標,下面介紹我們如何實現這些目標。
總體進展
模型收斂曲線展示了語音識別領域從簡單的 Wav2Letter 模型到更優化模型的進步。GPU 小時是計算時間乘以所用 GPU 的數量。每次只引入一項架構更改,所有其他設置、超參數和數據集均保持不變。
我們從 PyTorch 的 Deep Speech 2 分支開始。原始的 Deep Speech 2 模型基於深度 LSTM 或 GRU 遞歸網絡,速度較慢。上圖展示了我們可以添加到原始管道中的優化。具體來說,我們能夠在不損害模型性能的前提下做到以下幾點:
- 將模型大小減小到約 20%;
- 將收斂速度提高 5-10 倍;
- 最終模型的小版本(25M-35M 個參數)可以在 2 塊 1080 Ti GPU 上訓練;
- 大型模型仍需要 4 塊 1080 Ti,但與小版本相比最終 CER 值要低一點(降低 1-1.5 個百分點)。
上面的圖中只有卷積模型,我們發現它們比循環模型快得多。我們獲取這些結論的過程如下:
- 使用一個 Deep Speech 2 的現有實現;
- 在 LibriSpeech 上進行實驗,注意到 RNN 模型與卷積模型相比往往很慢;
- 添加了一個簡單的 Wav2Letter 啟發模型,但對於俄語語料來說,模型參數不足,因此我們增加了模型大小;
- 發現模型效果尚可,但是訓練起來很慢,於是嘗試優化訓練時間。
接下來我們嘗試了以下想法來做改進:
想法 1:模型步幅
我們的第一步優化是修改模型步幅。這實際上是一個非常簡單的想法。在分析 Wav2Letter 模型的擴展版本(步幅為 2)的輸出時(在短時傅立葉變換之後),我們注意到有用的輸出詞與空白詞的比率大約在 2 比 1 和 3 比 1 之間。那麼何不在卷積編碼器中增加步幅呢?
想法 2:緊湊正則網絡
如前所述,針對移動設備高度優化的網絡可能無法用作架構決策的理想參考,但是從中可以總結出很好的經驗:
- 使用可分離卷積,因為它們會大大減少模型中的參數數量,而不會犧牲模型性能;
- 向深度 CNN 添加跳躍連接,可以加快收斂,並能訓練更深的模型;
- 在模型的卷積部分中添加併發空間、通道擠壓和激勵模塊,或基於風格的再校準模塊等注意力機制,因為它們往往只需很小的計算開銷就能提升模型性能;
此外,小型正則化網絡更易訓練,因為它們的擬合度較低。不利的一面是較小的網絡需要更多的迭代才能收斂(也就是說每個批次更快,但需要的批次更多)。一個簡單的經驗法則表明(實際情況可能更復雜些),如果網絡的大小減少到 1/3 至 1/4,其他所有條件都相同,要訓練出和較大網絡相同的性能水平則需要 3-4 倍的迭代數。但是較小的網絡將快 2-3 倍。
另一個想法也很有價值,如果你使用 IdleBlocks,即在沒有任何操作的情況下通過模型傳遞一些卷積通道,則可以使用一半的參數和更大的感受野來構建更深、更具表現力的網絡。
想法 3:使用字節對編碼
根據這篇文章我們嘗試了幾種分詞方法,結果發現:
- 字節對編碼(BPE)是使用整體步幅大於 4 的模型的必要條件,否則詞 (token) 就不夠了。
- 基於字素的 BPE 優於基於音素的 BPE 模型。
- 在我們的情況下,即使只有非常簡單的解碼器的模型也可以充當語言模型,並且與基線模型相比 WER(字錯誤率)大幅降低。請記住,最好使用在較大文本語料庫上單獨訓練的模型來解碼。我們的 BPE 模型與基線模型相比取得了相似甚至更好的 CER(字符錯誤率)性能;
- BPE 詞彙量越大,AM 就更像 LM。我們不希望 AM 過擬合已知詞彙表,因此需要找到一個平衡點。我們運行了多個模型,其 BPE 詞彙量從小到大(300、1,000、3,000 和 10,000),總結出的經驗是最多 1,000 的 BPE 詞彙量可以在改善聲學模型的 WER,而不會損害其 CER。當詞彙量大於 1,000 時,我們開始看到 CER 開始下降,這表明模型與口語語料庫的詞彙表過擬合了;
我們使用了流行的 sentencepiece 分詞器,做了少許調整以適合 ASR 領域。
想法 4:更好的編碼器
這裡的基本思想是使用更具表現力的編碼器 / 解碼器架構。縮減到 1/8 比例的卷積編碼器非常快,因此你可以使用更復雜的解碼器。
現在人們已經普遍認同一點,那就是在 NLP 領域,transformer 模塊的建模能力比之前的頂尖模型要強很多。
總體而言,這種設置下的模型所需的計算資源十分少,在生產中部署時甚至都不需要 GPU。聲學模型在每 GPU 秒內可以輕鬆處理 500-1000 秒的音頻(實際上的速度很可能受 I/O 限制),而每 CPU 秒則可以處理 2-3 秒的音頻(EX51-SSD-GPU服務器上的單 CPU 核心),同時不影響性能。注意這裡的估算值僅包含聲學模型,並可以通過模型量化和最小化(即修剪、教師蒸餾等)獲得進一步改進。
想法 5:平衡容量,不再使用 4 個 GPU
通過在模型的各個部分中平衡容量和計算需求,可以得到一個僅需兩塊 1080 Ti 即可快速訓練的模型!而且比需要 4 個甚至 8 個 GPU 的模型節約很多天的訓練時間。
我認為這是迄今為止最令人印象深刻的成就。
想法 6:在各個域中穩定訓練成果,平衡泛化
語音識別模型中的一大問題是災難性遺忘。根本問題在於,就連正則化網絡(具有可分離的卷積)在適應大批新數據時也會開始忘記舊的域。這在生產環境中是尤其無法接受的。另一個問題是,ASR 論文往往會在整個 Librispeech 數據集上訓練 50 至 500 個 epoch。樣本效率非常低,無法擴展到現實數據上。
我們發現可以使用課程學習來減少將模型擬合到新數據上所需的迭代數,並想出了一些辦法來應對災難性遺忘。使用這種方法,我們可以將迭代總數減少到數據集大小的 5-10* 以下。
關鍵思想是:
- 使用課程學習,也就是根據某種質量指標(我們使用 CER)從數據集中採樣樣本數據,這樣你就可以從較簡單的樣本開始,隨著訓練的進行逐漸引入越來越難的樣本。一般不宜對太容易的樣本進行太長時間的採樣(這將導致過擬合併降低魯棒性),或太早開始採樣太困難的樣本(這將導致欠擬合)。在實驗中我們發現保持 10%的 CER(在訓練過程中引入更難或更容易的樣本)是最合適的。
- 學習新的域時,需要從以前訓練過的域中採樣新增數據,以減少災難性遺忘;
- 在現實生活中,來自不同域的數據可能嚴重失衡。為了解決這個問題,你可以用不同的概率採樣不同域的數據,從而為模型提供所需的特徵。例如對於最佳模型而言,我們對所有域都分配了相同的概率,但是我們將各個域定義為來自相似的源域(也就是具有相似的噪聲、詞彙量和主題)。
- 有些域可能有更高或更低的信噪比,因此對於某些域而言,最佳 CER 可能會降低到 5%;
想法 7:打造快速解碼器
這超出了本文的範圍,不過簡單說一下,有兩個用於後期處理的選項:
- 序列到序列網絡;
- 具有語言模型的束搜索解碼器;
在我們的測試中,序列到序列網絡不會明顯減慢我們的推理速度,而束搜索則慢了 10 倍。讓序列到序列模型超越束搜索是下一步研究的一個要點,但我們已經使用了 KenLM 的束搜索實現,達到了每 CPU 內核秒約 25 秒音頻的處理速度,同時沒有犧牲精確度。
模型基準測試和泛化差距
在現實生活中,如果模型在一個域上訓練,則可以預期它在另一個域上存在巨大的泛化差距。但是泛化差距是先天存在的嗎?如果答案是肯定的,那麼域之間的主要區別是什麼?是否能訓練出一種模型,可以在許多實用的域上都以良好的信噪比正常工作嗎?
泛化差距是存在的,你甚至可以推斷出哪些 ASR 系統在哪些域上訓練過。此外,根據之前的想法,你可以訓練出一個模型,讓它在未見的域上也能表現出色。
根據我們的觀察,以下是導致域之間泛化差距的主要因素:
- 總體噪音水平;
- 詞彙和發音;
- 用於壓縮音頻的編解碼器或硬件;
說明:
- 所有速度基準測試都是在 EX51-SSD-GPU 服務器上完成的:4 核 CPU+GTX 1080;
- 該基準測試包括聲學模型和語言模型。聲學模型在 GPU 上運行,對結果累加;語言模型後處理在多個 CPU 上運行;
- 測試成績是將數據集中音頻的總音頻時間除以應用聲學模型和語言模型後處理所花費的總時間來得出的。對於這些測試,這一指標的範圍從 125 到 250,這是非常快的。但這並不代表實際的生產使用速度。
模型測試結果分析
人們在對比不同系統的表現時往往會有很多不良習慣:
- 將 2019 年新研發的模型與競爭對手 2018 年的模型做對比;
- 對結果進行精心挑選以符合某些論點;
- 忽略了實際情況、計算需求或維護方面的問題;
我們自己也沒法完全避免這類傾向,所以你至少應該嘗試:
- 進行數據集外(ood)驗證;
- 在乾淨和嘈雜的數據上驗證;
- 嘗試創建適合實際使用的通用模型。顯然,有些公司為多個域提供多種模型是有原因的,但是創建一個通用模型比為一個狹窄的域創建模型要困難得多;
- 將模型與明顯不同的其他方法進行比較——至少在黑匣子級別上對比;
根據上一節中的測試成績對比可以得出一些結論(請注意,這些測試是在 2019 年底 /2020 年初進行的):
- 通過使用 OpenSTT,我們成功地訓練了一個通用模型,該模型的性能與業內最優秀的通用模型相當,並且在數據集外測試中不會落後太多。
- 除了我們的模型外,沒有其他模型可以在所有驗證集上都表現出色,同時還不會顯著犧牲某些域的性能(即 WER>50%);
- 我們可以清楚地看到,在多數數據集中都能找出幾個性能最出色的系統,它們具有明顯的普遍性能優勢;
- 出人意料的是,雖然谷歌在現實通話測試中給出了最佳表現,但它在某些領域仍然嚴重落後。我們無法判斷這是不是因為某個內部置信度閾值偏高而造成的,但從數據看來,谷歌的 STT 在自己不確定時直接跳過了輸出,這在某些應用中是難以接受的,而對於其他應用場景來說則是默認的行為;
- Kaldi 可能接受過有聲讀物或類似域的訓練;
- 雖然在簡單的領域(例如旁白或有聲讀物)上 Tinkoff 的模型的表現極佳,但它在其他領域的性能甚至比沒有 LM 的模型還要差。同樣,他們最有可能在有聲讀物和 Youtube(也可能有旁白或簡短命令)上訓練自己的模型;
- 令人驚訝的是,Yandex 並不像人們普遍認為的那樣是所有領域中表現最好的;
- 儘管 Kaldi 在簡單域的簡單詞彙設置中表現良好,但在有噪音的域上卻落後了。
生產應用
我們已經證明,在幾乎零人工註釋和有限的硬件預算(2-4x1080 Ti)條件下,也可以訓練出魯棒且可擴展的聲學模型。但一個顯而易見的問題是:要部署這個模型還需要多少數據、計算量和工作?模型的實際表現如何?
談到性能,我們認為顯而易見的標準就是在所有驗證數據集上擊敗谷歌。但問題在於谷歌在某些域(比如電話錄音)上的性能出色,而在其他域上的平均性能卻很差。因此在本節中,我們決定採用俄羅斯企業 SpeechPro 的最佳模型的結果,該模型通常被稱為市場上的“最佳”解決方案。
如上表,我們發現除電子商務電話和有聲讀物之外,我們的模型在所有類別中都優於 SpeechPro Calls(他們有很多模型,但是隻有一個模型在所有域上都表現良好)。此外我們發現,為模型增加更多容量和訓練更多數據,可以極大地改善我們在大多數域中的結果,並且 SpeechPro 僅在電子商務電話中優於我們改進的模型。
為了獲得這些結果,我們額外獲取了 100 小時的帶有人工標註的電話錄音、大約 300 個小時的具有各種自動標註的電話錄音、以及 10,000 個小時的類似 OpenSTT 的未公開數據。我們還將模型解碼器的容量增加到了約 65M 參數。如果你說俄語,可以在此處測試我們的模型。
其他問題則要複雜一些。顯然,你需要一個語言模型和一個後處理管道,這裡不再討論。為了只部署在 CPU 上,最好做一些進一步的縮小或量化,但這不是必需的。每個 CPU 內核每秒可以處理 2-3 秒的音頻(在較慢的處理器上是這樣,在更快的處理器內核上可以達到 4-5 秒左右)就足夠了,但最新的解決方案聲稱它們的成績約為 8-10 秒(在更快的處理器上)。
未來展望
下面是我們嘗試過的一些想法(其中一些想法甚至是可行的),但我們最後認為它們過於複雜,提供的好處卻不見得有那麼多:
- 擺脫梯度裁剪。梯度裁剪佔批處理時間的 25%至 40%。我們嘗試了各種方法來擺脫它,但是如果不降低收斂速度就無法做到這一點。
- ADAM、Novograd 和其他有前途的新興優化器。根據我們的經驗,他們只在較簡單的非語音領域或迷你數據集上有效果;
- 序列到序列解碼器和雙重監督。這些想法是行之有效的。採用分類交叉熵損失(而非 CTC)的基於注意力的解碼器是非常慢的(因為在已經很繁重的對齊任務中還要加入語音解碼任務)。混合網絡的性能提升並不足以彌補其複雜性的缺陷。這可能只是意味著混合網絡需要大量的參數微調。
- 基於音素和音素增強的方法。儘管這些方法幫助我們規範化了一些過參數化的模型(100-150M 參數),但事實證明它們對較小的模型不是很有用。由谷歌發起的一項分詞研究得出了類似的結果;
- 逐漸增加寬度的網絡。這種網絡在計算機視覺中是一種常見的設計模式,其收斂速度較慢。
- 使用 IdleBlocks 。初看上去這是行不通的,也許需要更多時間才能找出合適的途徑。
- 嘗試使用某種類型的可調濾波器代替 STFT。我們嘗試了可調 STFT 濾波器和 SincNet 濾波器的各種實現,但是在大多數情況下,使用這類濾波器甚至無法穩定訓練過程。
- 訓練具有不同步幅的金字塔形模型。我們在這裡沒有取得任何進展;
- 使用模型蒸餾和量化來加快推理速度。當我們在 PyTorch 中嘗試進行原生量化時,它仍處於 beta 版本,尚不支持我們的模塊;
- 加入更多優化,例如立體聲或降噪。降噪起了點作用,但事實證明它的價值不是很大。
關注我並轉發此篇文章,私信我“領取資料”,即可免費獲得InfoQ價值4999元迷你書!