GluonNLP 0.3.3 新功能及重現報告

GluonNLP 0.3.3 新功能及重現報告

來自專欄 gluon105 人贊了文章

作者:查晟 Amazon Applied Scientist

GluonNLP 第一彈中煉丹師小 A 的遭遇和深度學習那些坑扎了許多朋友的心,比如知乎網友 RickZ 評論稱 「正在被中文數據預處理教做人??」。在第一彈發布後,我們 GluonNLP 的小哥們馬上又投入到緊張的論文復 (cai) 現 (keng) 工作中。今天,我們新發布的 GluonNLP 0.3.3 為大家帶來了又一批新鮮出爐的模型:

  • 語言模型
    • Cache Language Model by Grave, E., et al. 「Improving neural language models with a continuous cache」. ICLR 2017
  • 機器翻譯
    • Transformer Model by Vaswani, Ashish, et al. 「Attention is all you need」. NIPS 2017
  • 詞向量訓練
    • FastText models by Bojanowski, P., Grave, E., Joulin, A., & Mikolov, T. 20172017. 「Enriching Word Vectors with Subword Information」. TACL, 5, 135-146.
    • Word2Vec by Mikolov, T., Sutskever, I., Chen, K., Corrado, G. S., & Dean, J. 20132013. 「Distributed representations of words and phrases and their compositionality」. NIPS 2014

開發過程中,各位 NLP 小哥堅持踏踏實實踩坑,在哪個坑跌倒就從哪個坑爬起來,終於攢出大招發了這一波模型。下面我們就來聽聽各位 GluonNLP 小哥們從前方發來乾貨滿滿的踩坑報道。

語言模型篇

踩坑小哥: 晨光 @cgraywang (@home)

當時年幼無知的你看到杰倫唱:「就是開不了口,讓她知道」,心裡的潛台詞一定是這樣的:

杰倫究竟為啥開不了口?不行我來,我們感到很生氣(暴露了年齡 orz)。現在做了 GluonNLP 的我終於明白,原來是杰倫的語言模型不行。如果您也有類似癥狀??新版本 GluonNLP V0.3 提供了最先進的治療方案,即目前市面上表現最佳的 Cache 語言模型,了解一下。

這次新發布的 Cache 語言模型為啥用過的都說好?因為效果好,能把 perplexity(PPL)。PPL 從之前最優的 69.74 提升到 54.51(PPL 是公認的語言模型評價指標,越低越好)。本質上 Cache 語言模型是記性更好的深度循環神經網路。要進一步解釋 Cache 語言模型原理,我們就得言歸正傳一下,首先傳統語言模型的正式定義是:給定一系列詞,預測接下來的一個詞。傳統的語言模型是 n 元語言模型,簡單的來說,就是計算給定 n-1 個詞,預測第 n 個詞的概率(沒錯~ 就是條件概率),然後把一個句子中所有的 n-gram 概率相乘,就是整個句子或者語言的概率。例如二元語言模型(bigram)。bigram,就是給定 1 個詞,預測第 2 個詞的概率,然後就能計算出某個句子的語言概率。Cache 語言模型的基本假設是:如果一個詞已經在一篇文章裡面出現過了,那麼這個詞相對於其他詞就更有可能出現在同一篇文章中。例如,老虎這個詞在維基百科上老虎標題的頁面中出現的頻率是 2.8%,而在整個維基百科文章中出現的頻率則是 0.0037%。Cache 語言模型就是通過對語言中存在的詞之間的長關聯進行更好的建模,從而提升語言模型的效果。換句話說,Cache 語言模型有一個叫做 Cache 的記憶單元,其中包含近期出現過的詞(比如同一篇文章,或者某種寬度的窗口中)。簡單從模型的實現細節上來講,Cache 存儲了長短期記憶(LSTM)模型某段的隱狀態(hidden states)與已經看到的詞,然後將這段隱狀態作為查詢關鍵詞,與當前隱狀態進行簡單的向量之間的內積運算,得到已經看到的詞在 Cache 中的概率分布。該概率分布將直接作用到傳統語言模型的概率分布上(例如上面提到的二元語言模型),從而提升語言模型的性能。Cache 語言模型主要有三個好處:

  • 可以幫助把已經在某個領域的數據上訓練好的語言模型直接應用到新的領域;
  • 能夠更好的預測詞典之外的詞(OOV),因為只要是見到一次詞典之外的詞,Cache 就能記住;
  • 對於語言中的長關聯現象有更好的把握。

不過這裡要特別說明一下,因為 Cache 語言模型需要把真實的近期出現過的詞存儲到 Cache 中,所以無法很直接的擴展到生成類的任務(例如,機器翻譯或問答系統)。這是因為生成類任務中往往生成時所依賴的前文也是模型自己生成的,而非真實數據。若我們假設過去出現的真實的詞是能夠很容易拿到的,那麼 Cache 語言模型也就能夠直接用到生成類的任務中。對於拿不到真實上文的模型,GluonNLP 中已經有了其他各種語言模型,例如基於循環神經網路(RNN)的語言模型,以及功能強大的 AWD 語言模型。在這裡做個預告,我們將會在後續的博客中針對語言模型跟大家進行更細緻全面的分享~

於是自從有了 GluonNLP 語言模型後的杰倫,不再開不了口,而是變身詩人(LAOSIJI):

機器翻譯篇

踩坑小哥: 帥哥 @szhengac (@home)

在新的版本里,我們加入了 Transformer 模型,目前我們的 NMT 系統支持 WMT14 和 16 的英文到德文的互譯。Transformer 不同於 RNN 模型,由於整個模型由 Attention 構成,所有的 timestamp 的計算可以同時進行,這個大大的加速了訓練速度。

在訓練 Transformer 的過程中我們踩了很多的坑。首先是數據的不同, WMT14 測試數據 newstest2014 英文到德文的翻譯有 2 個版本,一個有 3003 對樣本,另一個有 2737 對樣本;Batch size 不再指的是 Sentence 的個數而是 token 的個數;再接著是 BLEU 的計算,這個比較複雜,我們在後面細說。

目前 Gluonnlp 支持三種 BLEU 計算:WMT 官方的 BLEU 計算;基於 International Tokenization 的 BLEU;用於重複論文結果的 BLEU 計算。大家看到這裡可能驚訝論文里的 BLEU 計算方式和官方的演算法不一樣。這個是我們踩了很久的一個坑。BLEU 的計算會由於預處理和 tokenization 的不同結果千變萬化,BLEU 的不同可能會有 2 到 3 個值。而這個不同其實並不能反應翻譯的好壞,因為不同來自於標點符號的處理不同。這大大加了重複論文結果的難度,因為我們可能不知道這篇論文是怎麼進行處理的。經過和 T2T 和 Sockeye 的作者溝通以及查閱他們的代碼,我們才了解到論文里是怎麼計算 BLEU 的。按照論文里的計算方式,我們的 Base Transformer 模型在 newstest2014 數據上英文到德文的翻譯可以達到 28.74 的 BLEU。這個已經遠遠超過了論文里報告的 Large Transformer 的 27.3 的 BLEU,甚至超過了 Large Transformer 的 28.4 的 BLEU。而如果按照 WMT 官方的 BLEU 計算方式,BLEU 的值是 26.81。加上 International Tokenization 的結果是 27.65。這裡可以看到結果的變化是巨大的。

詞向量篇

踩坑小哥: Leo @leezu (@home)

翻譯小哥: 查晟

有木有好奇過電腦是怎麼理解自然語言的? 感興趣的話可以看看 GluonNLP 中的 「using pre-trained word embeddings in Gluon NLP「里的介紹。如果已經熟悉其中內容了請繼續看。

對於最基本的情況,GluonNLP 中的 TokenEmbedding 中只保留每個已知單詞的向量表徵。模型在查詢時 TokenEmbedding 像查字典一樣,根據一個詞的完整拼寫來查詢,一個字母都不能錯。但如果一個詞沒有見過腫么辦? 在 v0.3 版以前,GluonNLP 和其他許多深度學習自然語言處理框架一樣,會把這些詞替換成一個特殊值 「<unknown>「,然後把這些沒見過的詞統統假裝是這個特殊值統一來學習。然鵝,這樣做的話會丟失很多信息。已經有許多方法可以為這些沒見過的詞提供更好的表徵,比如 fastText 會用每個詞中不同長度的子序列的表徵累加成一個詞的表徵。v0.3 開始,GluonNLP 支持在遇到生詞時,自動地用包含 fastText 這樣的基於子序列生成插值的模型來產生生詞的詞向量。對於 fastText,用戶只需要在載入已有的 fastText 向量時聲明 loadngrams=True,GluonNLP 包就會自動幫你載入啦。

除此之外,為了讓使用預訓練詞向量更容易,GluonNLP 現在提供詞向量的訓練腳本,用來在用戶自己的數據集上訓練。我們提供了 word2vec 和 fastText 模型,並且直接將他們與已有的 TokenEmbedding 整合。用戶也可以很容易地改動或自己定義模型,從而能快速實驗改善詞向量的新想法。要知道,facebook 提供的 fastText 本來是一個專為 CPU 優化的 C++ 的庫。為了能讓用戶更容易地在 Python 中開發詞向量訓練模型,並且利用 GPU 加快實驗速度,小哥我也做了不少改進工作。下面簡單介紹下:

  1. 批量化 首先,為了能充分利用 GPU 達到快速訓練的目的,我們需要能讓模型做批量化的訓練 BatchingBatching,這與 word2vec 和 fastText 的非同步多線程的處理方式不同。然而,在新模式下直接使用一般詞向量訓練最常用的 SGD 做優化效果並不好,所以在嘗試後,我們使用了 adagrad 而達到了很好的效果。
  2. 哈希函數 fastText 的支持需要使用哈希函數幫助特徵表徵。但是,我們在進行相關工作的時候發現有個小坑,就是原實現中使用的哈希函數的實現方式對不同的編譯器會有行為不同,因而是達不到原作者聲稱的可移植性的。我們因此選擇了最常見的 x86 上最常見的編譯器的默認行為,並且把上面的問題彙報給了原作者們。
  3. 數據管道 與許多深度學習任務不同的是,詞向量訓練時用的 SkipGram 或者 CBOW 訓練目標下使用的淺神經網路計算代價很低,因此我們尤其需要注意數據管道的效率以避免其成為訓練過程的瓶頸。我們在 GluonNLP 中使用了 numba 的 just-in-time(JIT)。JIT 編譯來幫助提高效率。

接下來

看過小哥們的踩坑報告,相信大家對小哥們的(吐槽)功力有了更深的認識。在享受新功能的同時,也記得給小哥們點個贊!

最新的 GluonNLP 發布在 gluon-nlp.mxnet.io。項目開發都在 Github 的 gluon-nlp。我們會持續加入新的特性和模型。如果你也躍躍欲試,歡迎一起來搞事情!

歡迎來 Gluon 社區吐槽: discuss.gluon.ai/t/topi


推薦閱讀:

tensorflow separable_conv2d
如何對比 PyTorch 和 Gluon 的煉丹體驗?
RefineDet 論文解析
mxnet訓練/導出/載入模型並預測(python和C++)
MXNet/Gluon第二課:過擬合,多層感知機,GPU和卷積神經網路筆記

TAG:MXNet | 深度學習DeepLearning |