基於PaddlePaddle的詞向量實戰 | 深度學習基礎任務教程系列

pythontab發表於2019-04-19

詞向量是自然語言處理中常見的一個操作,是搜尋引擎、廣告系統、推薦系統等網際網路服務背後常見的基礎技術。

  在這些網際網路服務裡,我們經常要比較兩個詞或者兩段文字之間的相關性。為了做這樣的比較,我們往往把詞表示成計算機適合處理的方式。最自然的方式莫過於向量空間模型(vector space model)。 在這種方式裡,每個詞被表示成一個實數向量(one-hot vector),其長度為字典大小,每個維度對應一個字典裡的每個詞,除了這個詞對應維度上的值是1,其他元素都是0。One-hot vector雖然自然,但是用處有限。比如,在網際網路廣告系統裡,如果使用者輸入的query是“母親節”,而有一個廣告的關鍵詞是“康乃馨”。按照常理,我們知道這兩個詞之間是有聯絡的——母親節通常應該送給母親一束康乃馨;但是這兩個詞對應的one-hot vectors之間的距離度量,無論是歐氏距離還是餘弦相似度(cosine similarity),由於其向量正交,都認為這兩個詞毫無相關性。得出這種與我們相悖的結論的根本原因是:每個詞本身的資訊量都太小。所以,僅僅給定兩個詞,不足以讓我們準確判別它們是否相關。要想精確計算相關性,我們還需要更多的資訊——從大量資料裡透過機器學習方法歸納出來的知識。

  在機器學習領域,透過詞向量模型(word embedding model)可將一個 one-hot vector對映到一個維度更低的實數向量(embedding vector),如:

  embedding(母親節)=[0.3,4.2,−1.5,...];

  embedding(康乃馨)=[0.2,5.6,−2.3,...];

  在這個對映到的實數向量表示中,兩個語義(或用法)上相似的詞對應的詞向量“更像”,這樣如“母親節”和“康乃馨”的對應詞向量的餘弦相似度就不再為零了。

  詞向量模型可以是機率模型、共生矩陣(co-occurrence matrix)模型或神經元網路模型。在用神經網路模型求詞向量之前,傳統的做法是統計一個詞語的共生矩陣X,在對X做矩陣分解,得到了所有詞的詞向量。但是傳統的方法有三大問題:1)由於很多詞沒有出現,導致矩陣極其稀疏;2)矩陣非常大,維度太高;3)需要手動去掉停用詞(如although, a,...),不然這些頻繁出現的詞也會影響矩陣分解的效果。但是基於神經網路的模型不需要計算和儲存一個在全語料上統計產生的大表,而是透過學習語義資訊得到詞向量,因此能很好地解決以上問題。

  本教程旨在展示神經網路訓練詞向量的細節,以及如何用PaddlePaddle訓練一個詞向量模型。

  專案地址:http://paddlepaddle.org/documentation/docs/zh/1.3/beginners_guide/basics/word2vec/index.html

  基於PaddlePaddle訓練一個詞向量模型操作詳情請參照Github:

  https://github.com/PaddlePaddle/book/blob/develop/04.word2vec/README.cn.md

  效果展示

  當詞向量訓練好後,我們可以用資料視覺化演算法t-SNE[4]畫出詞語特徵在二維上的投影(如下圖所示)。從圖中可以看出,語義相關的詞語(如a, the, these; big, huge)在投影上距離很近,語意無關的詞(如say, business; decision, japan)在投影上的距離很遠

https://github.com/PaddlePaddle/book/blob/develop/04.word2vec/image/2d_similarity.png?raw=true

圖1. 詞向量的二維投影

  另一方面,我們知道兩個向量的餘弦值在[−1,1][−1,1]的區間內:兩個完全相同的向量餘弦值為1, 兩個相互垂直的向量之間餘弦值為0,兩個方向完全相反的向量餘弦值為-1,即相關性和餘弦值大小成正比。因此我們還可以計算兩個詞向量的餘弦相似度:

  以上結果可以透過執行calculate_dis.py 載入字典裡的單詞和對應訓練特徵結果得到,我們將在模型應用中詳細描述用法。

  模型概覽

  在這裡我們介紹三個訓練詞向量的模型:N-gram模型,CBOW模型和Skip-gram模型,它們的中心思想都是透過上下文得到一個詞出現的機率。對於N-gram模型,我們會先介紹語言模型的概念,並在之後的訓練模型中,帶大家用PaddlePaddle實現它。而後兩個模型,是近年來最有名的神經元詞向量模型,由 Tomas Mikolov 在Google 研發[3],雖然它們很淺很簡單,但訓練效果很好。

  N-gram neural model

  在計算語言學中,N-gram是一種重要的文字表示方法,表示一個文字中連續的n個項。基於具體的應用場景,每一項可以是一個字母、單詞或者音節。 N-gram模型也是統計語言模型中的一種重要方法,用N-gram訓練語言模型時,一般用每個N-gram的歷史n-1個詞語組成的內容來預測第n個詞。

  Yoshua Bengio等科學家就於2003年在著名論文 Neural Probabilistic Language Models [1]中介紹如何學習一個神經元網路表示的詞向量模型。文中的神經機率語言模型(Neural Network Language Model,NNLM)透過一個線性對映和一個非線性隱層連線,同時學習了語言模型和詞向量,即透過學習大量語料得到詞語的向量表達,透過這些向量得到整個句子的機率。因所有的詞語都用一個低維向量來表示,用這種方法學習語言模型可以克服維度災難(curse of dimensionality)。一句話中第t個詞的機率和該句話的前t−1個詞相關。可實際上越遠的詞語其實對該詞的影響越小,那麼如果考慮一個n-gram, 每個詞都只受其前面n-1個詞的影響,則有:

  給定一些真實語料,這些語料中都是有意義的句子,N-gram模型的最佳化目標則是最大化目標函式:

  其中表示根據歷史n-1個詞得到當前詞的條件機率,R(θ)表示引數正則項。

https://github.com/PaddlePaddle/book/blob/develop/04.word2vec/image/nnlm.png?raw=true

圖2. N-gram神經網路模型

  圖2展示了N-gram神經網路模型,從下往上看,該模型分為以下幾個部分: - 對於每個樣本,模型輸入,輸出句子第t個詞在字典中|V|個詞上的機率分佈。每個輸入詞首先透過對映矩陣對映到詞

  。

  • 然後所有詞語的詞向量拼接成一個大向量,並經過一個非線性對映得到歷史詞語的隱層表示

  其中,為所有詞語的詞向量拼接成的大向量,表示文字歷史特徵;θ、U、和W分別為詞向量層到隱層連線的引數。表示未經歸一化的所有輸出單詞機率,表示未經歸一化的字典中第個單詞的輸出機率。 • 根據softmax的定義,透過歸一化, 生成目標詞的機率為

  • 整個網路的損失值(cost)為多類分類交叉熵,用公式表示為

  其中表示第個樣本第類的真實標籤(0或1),softmax()表示第個樣本第類softmax輸出的機率。

  Continuous Bag-of-Words model(CBOW)

  CBOW模型透過一個詞的上下文(各N個詞)預測當前詞。當N=2時,模型如下圖所示:

https://github.com/PaddlePaddle/book/blob/develop/04.word2vec/image/cbow.png?raw=true

圖3. CBOW模型

  具體來說,不考慮上下文的詞語輸入順序,CBOW是用上下文詞語的詞向量的均值來預測當前詞。即:

  其中為第個詞的詞向量,分類分數(score)向量=∗context,最終的分類採用softmax,損失函式採用多類分類交叉熵。

  Skip-gram model

  CBOW的好處是對上下文詞語的分佈在詞向量上進行了平滑,去掉了噪聲,因此在小資料集上很有效。而Skip-gram的方法中,用一個詞預測其上下文,得到了當前詞上下文的很多樣本,因此可用於更大的資料集。

https://github.com/PaddlePaddle/book/blob/develop/04.word2vec/image/skipgram.png?raw=true

圖4. Skip-gram模型

  如上圖所示,Skip-gram模型的具體做法是,將一個詞的詞向量對映到個詞的詞向量(表示當前輸入詞的前後各個詞),然後分別透過softmax得到這個詞的分類損失值之和。

  資料準備

  資料介紹

  本教程使用Penn Treebank (PTB)(經Tomas Mikolov預處理過的版本)資料集。PTB資料集較小,訓練速度快,應用於Mikolov的公開語言模型訓練工具[2]中。其統計情況如下:

  資料預處理

  本教程訓練的是5-gram模型,表示在PaddlePaddle訓練時,每條資料的前4個詞用來預測第5個詞。PaddlePaddle提供了對應PTB資料集的python包paddle.dataset.imikolov,自動完成資料的下載與預處理,方便大家使用。

  預處理會把資料集中的每一句話前後加上開始符號以及結束符號。然後依據視窗大小(本教程中為5),從頭到尾每次向右滑動視窗並生成一條資料。

  如"I have a dream that one day" 一句提供了5條資料:

  最後,每個輸入會按其單詞次在字典裡的位置,轉化成整數的索引序列,作為PaddlePaddle的輸入。

  模型結構

  本配置的模型結構如下圖所示:

https://github.com/PaddlePaddle/book/blob/develop/04.word2vec/image/ngram.png?raw=true

圖5. 模型配置中的N-gram神經網路模型

  首先我們先載入所需的包

  然後,定義引數

  更大的BATCH_SIZE將使得訓練更快收斂,但也會消耗更多記憶體。由於詞向量計算規模較大,如果環境允許,請開啟使用GPU進行訓練,能更快得到結果。在新的Fluid版本里,我們不必再手動計算詞向量。PaddlePaddle提供了一個內建的方法fluid.layers.embedding,我們就可以直接用它來構造 N-gram 神經網路。

  現在,我們來定義我們的 N-gram 神經網路結構。這個結構在訓練和預測中都會使用到。因為詞向量比較稀疏,我們傳入引數 is_sparse == True, 可以加速稀疏矩陣的更新。

  基於以上的神經網路結構,我們可以如下定義我們的訓練方法

  現在我們可以開始訓練啦。我們有現成的訓練和測試集:paddle.dataset.imikolov.train()和paddle.dataset.imikolov.test()。兩者都會返回一個讀取器。paddle.batch 會讀入一個讀取器,然後輸出一個批次化了的讀取器。我們還可以在訓練過程中輸出每個步驟,批次的訓練情況。

  train_loop將會開始訓練。期間列印訓練過程的日誌如下:

  預測下一個詞的配置

  我們可以用我們訓練過的模型,在得知之前的 N-gram 後,預測下一個詞。

  由於詞向量矩陣本身比較稀疏,訓練的過程如果要達到一定的精度耗時會比較長。為了能簡單看到效果,教程只設定了經過很少的訓練就結束並得到如下的預測。我們的模型預測 among a group of 的下一個詞是the。這比較符合文法規律。如果我們訓練時間更長,比如幾個小時,那麼我們會得到的下一個預測是 workers。預測輸出的格式如下所示:

  其中第一行表示預測詞在詞典上的機率分佈,第二行表示機率最大的詞對應的id,第三行表示機率最大的詞。

  整個程式的入口很簡單:

  總結

  在本教程中,我們最開始先介紹了詞向量、語言模型和詞向量的關係、以及如何透過訓練神經網路模型獲得詞向量。在資訊檢索中,我們可以根據向量間的餘弦夾角,來判斷query和文件關鍵詞這二者間的相關性。在句法分析和語義分析中,訓練好的詞向量可以用來初始化模型,以得到更好的效果。在文件分類中,有了詞向量之後,可以用聚類的方法將文件中同義詞進行分組,也可以用 N-gram 來預測下一個詞。希望大家在閱讀完本教程能夠自行運用詞向量進行相關領域的研究。

  參考文獻

  [1]Bengio Y, Ducharme R, Vincent P, et al. A neural probabilistic language model[J]. journal of machine learning research, 2003, 3(Feb): 1137-1155.

  [2]Mikolov T, Kombrink S, Deoras A, et al. Rnnlm-recurrent neural network language modeling toolkit[C]//Proc. of the 2011 ASRU Workshop. 2011: 196-201.

  [3]Mikolov T, Chen K, Corrado G, et al. Efficient estimation of word representations in vector space[J]. arXiv preprint arXiv:1301.3781, 2013.

  [4]Maaten L, Hinton G. Visualizing data using t-SNE[J]. Journal of Machine Learning Research, 2008, 9(Nov): 2579-2605.


相關文章