1. 程式人生 > >文字挖掘深度學習之word2vec的R語言實現

文字挖掘深度學習之word2vec的R語言實現

筆者寄語:2013年末,Google釋出的 word2vec工具引起了一幫人的熱捧,大家幾乎都認為它是深度學習在自然語言領域的一項了不起的應用,各種歡呼“深度學習在自然語言領域開始發力 了”。

基於word2vec現在還出現了doc2vec,word2vec相比傳統,考慮單詞上下文的語義;但是doc2vec不僅考慮了單詞上下文的語義,還考慮了單詞在段落中的順序。

一、word2vec詞向量由來

在word2vec產生前,還有一些語言模型,在自然語言處理 NLP模型中,到達word2vec歷經了一些步驟。但是對於NLP模型中,起到確定性作用的是詞向量(Distributed Representation/word Embedding)的提出,在這之前有一些基礎性的模型如統計語言模型、神經網路概率語言模型。

幾個基於統計的傳統語言模型與word2vec這種直接預測的方法的比較(圖片摘自Stanford CS244)【5】:

1

1、統計語言模型

統計語言模型的一般形式直觀、準確,n元模型中假設在不改變詞語在上下文中的順序前提下,距離相近的詞語關係越近,距離較遠的關聯度越遠,當距離足夠遠時,詞語之間則沒有關聯度。

但該模型沒有完全利用語料的資訊:
1) 沒有考慮距離更遠的詞語與當前詞的關係,即超出範圍n的詞被忽略了,而這兩者很可能有關係的。
例如,“華盛頓是美國的首都”是當前語句,隔了大於n個詞的地方又出現了“北京是中國的首都”,在n元模型中“華盛頓”和“北京”是沒有關係的,然而這兩個句子卻隱含了語法及語義關係,即”華盛頓“和“北京”都是名詞,並且分別是美國和中國的首都。

2) 忽略了詞語之間的相似性,即上述模型無法考慮詞語的語法關係。
例如,語料中的“魚在水中游”應該能夠幫助我們產生“馬在草原上跑”這樣的句子,因為兩個句子中“魚”和“馬”、“水”和“草原”、“遊”和“跑”、“中”和“上”具有相同的語法特性。
而在神經網路概率語言模型中,這兩種資訊將充分利用到。

2、神經網路概率語言模型

神經網路概率語言模型是一種新興的自然語言處理演算法,該模型通過學習訓練語料獲取詞向量和概率密度函式,詞向量是多維實數向量,向量中包含了自然語言中的語義和語法關係,詞向量之間餘弦距離的大小代表了詞語之間關係的遠近,詞向量的加減運算則是計算機在”遣詞造句”。

如今在架構方面有比NNLM更簡單的CBOW模型、Skip-gram模型;其次在訓練方面,出現了Hierarchical Softmax演算法、負取樣演算法(Negative Sampling),以及為了減小頻繁詞對結果準確性和訓練速度的影響而引入的欠取樣(Subsumpling)技術。

2

上圖是基於三層神經網路的自然語言估計模型NNLM(Neural Network Language Model)。NNLM可以計算某一個上下文的下一個詞為wi的概率,即(wi=i|context),詞向量是其訓練的副產物。NNLM根據語料庫C生成對應的詞彙表V。

二、word2vec——詞向量特徵提取模型

先解釋一下詞向量:將詞用“詞向量”的方式表示可謂是將 Deep Learning 演算法引入 NLP 領域的一個核心技術。自然語言理解問題轉化為機器學習問題的第一步都是通過一種方法把這些符號數學化。

詞向量具有良好的語義特性,是表示詞語特徵的常用方式。詞向量的每一維的值代表一個具有一定的語義和語法上解釋的特徵。故可以將詞向量的每一維稱為一個詞語特徵。詞向量用Distributed Representation表示,一種低維實數向量。
例如,NLP中最直觀、最常用的詞表示方法是One-hot Representation。每個詞用一個很長的向量表示,向量的維度表示詞表大小,絕大多數是0,只有一個維度是1,代表當前詞。
“話筒”表示為 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 …] 即從0開始話筒記為3。
但這種One-hot Representation採用稀疏矩陣的方式表示詞,在解決某些任務時會造成維數災難,而使用低維的詞向量就很好的解決了該問題。同時從實踐上看,高維的特徵如果要套用Deep Learning,其複雜度幾乎是難以接受的,因此低維的詞向量在這裡也飽受追捧。
Distributed Representation低維實數向量,如:[0.792, ?0.177, ?0.107, 0.109, ?0.542, …]。它讓相似或相關的詞在距離上更加接近。

總之,Distributed Representation是一個稠密、低維的實數限量,它的每一維表示詞語的一個潛在特徵,該特徵捕獲了有用的句法和語義特徵。其特點是將詞語的不同句法和語義特徵分佈到它的每一個維度上去表示。

再來看看結合deep learning的詞向量是如何獲取的。談到word2vec的詞向量,就得提到兩個模型——DBOW以及skip-gram模型。兩個模型都是根據上下文詞,來推斷當前詞發生的概率。可以實現兩個基本目標:這句話是否是自然語句;獲得詞向量。兩個模型的大致結構如下圖所示:

320160505205332513

1、 CBOW加層次的網路結構((Continuous Bag-Of-Words Model,連續詞袋模型))

4

其中第一層,也就是最上面的那一層可以稱為輸入層。輸入的是若干個詞的詞向量,中間在神經網路概率語言模型中從隱含層到輸出層的計算時主要影響訓練效率的地方,CBOW和Skip-gram模型考慮去掉隱含層。實踐證明新訓練的詞向量的精確度可能不如NNLM模型(具有隱含層),但可以通過增加訓練語料的方法來完善。第三層是方框裡面的那個二叉樹,叫霍夫曼樹,W代表一個詞,Wsyn1是非葉節點是一類詞堆,還要繼續往下分。

這個網路結構的功能是為了完成一個的事情——判斷一句話是否是自然語言。怎麼判斷呢?使用的是概率,就是計算一下這句話的“一列詞的組合”的概率的 連乘(聯合概率)是多少,如果比較低,那麼就可以認為不是一句自然語言,如果概率高,就是一句正常的話。

計算的公式是下面的公式:

p(s)=p(w1,w2,?wT)=∏i=1Tp(wi|Contexti)

其中的Context表示的是該詞的上下文,也就是這個詞的前面和後面各若干個詞,這個“若干”(後面簡稱c)一般是隨機的,也就是一般會從1到5之間的一個隨機數。

舉個例子就是:“大家 喜歡 吃 好吃 的 蘋果”這句話總共6個詞,假設對“吃”這個詞來說c隨機抽到2,則“吃”這個詞的context是“大家”、“喜歡”、“好吃”和“的”,總共四個詞,這四個詞的順序可以亂,這是word2vec的一個特點。假設就是計算“吃”這個詞的在“大家”、“喜歡”、“好吃”和“的”這四個詞作為上下文的條件 概率,則

9

其中 σ(x)=1/(1+e?x) ,是sigmoid公式。

這個神經網路最重要的是輸出層的那個霍夫曼樹的葉子節點上的那些向量,那些向量被稱為詞向量,詞向量就是另外一篇博文裡面介紹的,是個好東西。運用上面那個“吃”的例子。

筆者自問自答(以下都是筆者自己的觀點,如有疑問千萬不要找我,哈哈…):

為啥要用霍夫曼樹來儲存詞?

答:可以知道霍夫曼樹可以儲存著語料庫所有的詞,每一個節點就是一個詞(W)或者眾多詞在一起的向量節點(Wsyn1)。但是用這棵樹來儲存詞的方式的確很特別,原因是因為求解詞條件概率時候應用到了神經網路的能量模型:

P(吃︱Context)=p(A|C)=e?E(A,C)∑Vv=1e?E(wv,C)

其中C是這個詞的上下文的詞向量的和(向量的和),V表示語料庫裡面的的詞元(片語的概念)的個數;整個語料庫有W個詞。

這個公式的意思就是在上下文C出現的情況下,中間這個詞是A的概率,為了計算這個概率,肯定得把語料庫裡面所有的 詞的能量都算一次,然後再根據詞A的能量,那個比值就是出現A的概率。

這個概率其實並不好統計,為了算一個詞的的概率,得算上這種上下文的情況下所有詞的能量,然後還計算指數值再加和。所以把語料庫的所有詞分成兩類,分別稱為G類和H類,每類一半,其中詞A屬於G類,那麼下面的式子就可以成立了

p(A│C)=p(A|G,C)p(G|C) =e?E(A,C)∑WGe?E(W,C)×11+e?E(H?G,C)

還是存在E能量難算,又把語料庫切割下去。這個過程就像是建立分支樹的過程。

有了這個霍夫曼樹,怎麼得出詞向量?

答:假如“吃”這個字在最右邊的W,那邊他要經過的步驟是:Wsyn1(1)→Wsyn1(2.2)→W。每分開一次節點,就有一次節點選擇,這個選擇就是一個Logistic函式,可能Wsyn1(1)→Wsyn1(2.2)左右的概率分別是[0.6,0.4],Wsyn1(2.2)→W的概率是[0.3,0.7],那麼W“吃”就可以表示為[0.4,0.7]。

5

其中提到的logistic regression模型,是因為

P(吃︱Context)=∏k=1Kp(dk|qk,C)=∏k=1K((σ(qk?C))1?dk?(1?σ(qk?C))dk)

這個公式是把p(A│C)=p(A|G,C)p(G|C) 中的語料庫切割無數次之後得到的最終函式形式。那麼求解函式,就得到了以下的似然函式,最後通過數學等式得到了如圖所示的公式。

6

dk表示樹枝的左右向,dk=1向左分,dk=0向右分。

word2vec就是這麼考慮的,把在霍夫曼樹向左的情況,也就是dk=0的情況認為是正類,概率就可以算出來是σ(qijk?Contextij),而負向的(dk=1)就是1-σ(qijk?Contextij)。

每個葉子節點都產生一個樣本,這個樣本的label(也就是屬於正類或者負類標 志)可以用霍夫曼編碼來產生,前面說過了,向左的霍夫曼編碼dk=0,所以很自然地可以用1-dk表示每個樣本label。霍夫曼編碼也變成了一個詞向量之前很重要的東西。

2、Skip-gram模型(Skip-Gram(Continuous Skip-GramModel))

7

詞Wi與huffman樹直接連線,沒有隱藏層的。使用方法依然與cbow加層次的相似。在判斷“大家 喜歡 吃 好吃 的 蘋果”這句話是否自然語言的時候,是這麼來的,同樣比如計算到了“吃”這個詞,同樣隨機抽到的c=2,對吃這個詞需要計算的東西比較多,總共要計算的概率 是p(大家|吃),p(喜歡|吃),p(好吃|吃)和p(的|吃)總共四個。

P(吃︱Context)=p(大家|吃)×p(喜歡|吃)×p(好吃|吃)×p(的|吃)  其中p(大家│吃)=(1-σ(A?D))?σ(B?D)?σ(C?D)…(還有三個)

把一整句話的所有詞的概率都計算出來後進行連乘,得到的就是這句話是自然語言的概率。這個概率如果大於某個閾值,就認為是正常的話;否則就認為不是自然語言,要排除掉【3】。

有一個比較簡易的解讀見【4】Skip-gram表示“跳過某些符號”。例如句子“中國足球踢得真是太爛了”有4個3元片語,分別是“中國足球踢得”、“足球踢得真是”、“踢得真是太爛”、“真是太爛了”,句子的本意都是“中國足球太爛”,可是上面4個3元組並不能反映出這個資訊。

此時,使用Skip-gram模型允許某些詞被跳過,因此可組成“中國足球太爛”這個3元片語。如果允許跳過2個詞,即2-Skip-gram,那麼上句話組成的3元片語為:

8

由上表可知:一方面Skip-gram反映了句子的真實意思,在新組成的這18個3元片語中,有8個片語能夠正確反映例句中的真實意思;另一方面,擴大了語料,3元片語由原來的4個擴充套件到了18個。
語料的擴充套件能夠提高訓練的準確度,獲得的詞向量更能反映真實的文字含義。

完成了兩大目標:考慮距離更遠的詞語與當前詞的關係;生成充分的語料庫,並且有正確的詞意詞元。

三、一些應用案例word2vec

1、廣告推薦:佈置在ANSJ上進行新聞關鍵詞提取,抽調googlecode.com包,得到了計算每個詞與最接近詞之間的距離(distance)、還可以執行聚類【利用word2vec對關鍵詞進行聚類】。

2、網路語料庫包的訓練實踐:從網路的一些有名的語料包進行訓練、在cygwin(因為word2vec需要linux環境,所有首先在windows下安裝linux環境模擬器),抽調googlecode.com,並詳細解釋了函式係數。【Windows下使用Word2vec繼續詞向量訓練

3、興趣挖掘的必要性。利用word2vec給廣告主推薦使用者,只是簡單分析沒有實操,但是提到了論文《網際網路廣告綜述之點選率系統》中的一些方法。【深度學習 word2vec 筆記】

——————————————————————————————————————————

一、tmcn.word2vec包

R語言中word2vec包,目前看到有一個叫tmcn.word2vec。該包真是一個草率、任性的包,寫於2014年9月21日。

而且貌似後期也沒有維護,真是可惜啊!!!

該包有兩個函式,第一個函式是word2vec,第二個函式計算單詞之間cos距離。

1、word2vec介紹

其中train_file代表輸入訓練語料庫,以及output_file輸出位置。

word2vec <- function (train_file, output_file, 
                      binary=1,                                # output format, 1-binary, 0-txt
                      cbow=0,                                  # skip-gram (0) or continuous bag of words (1) 
                      num_threads = 1,                         # num of workers 
                      num_features = 300,                      # word vector dimensionality 
                      window = 10,                             # context / window size 
                      min_count = 40,                          # minimum word count 
                      sample = 1e-3,                           # downsampling of frequent words
                      classes = 0
                      ) 
  
  # The parameters: 
  #                binary       - output format of the model; 
  #
  #                cbow         - which algorithm to use for training or skip-gram bag of words (cbow). 
  #                               Skip-gram is slower but produces a better result on the rare words; 
  #
  #                num_threads  - Processor number of threads involved in the construction of the model;
  #
  #                num_features - the dimension of words (or a vector for each word), it is recommended from tens to hundreds; 
  #
  #                window       - as many words from the context of the training algorithm should be taken into account; 
  #
  #                min_count    - limits the size of a boost word dictionary. 
  #                               Words that are not found in the text more than the specified number are ignored. 
  #                               Recommended value - from ten to one hundred; 
  #
  #                sample       - the lower limit of the frequency of occurrence of words in the text, 
  #                               it is recommended from .00001 to .01.

以下關於引數的解釋是來源於linux環境模擬器,cygwin中操作,用Java來呼叫的,發現R中這個包也跟這個函式引數,大同小異,而且解釋很清楚,所以非常感謝作者的細心翻譯[1]。

引數解釋:
-train_file 訓練資料
-output_file 結果輸入檔案,即每個詞的向量
-cbow 是否使用cbow模型,0表示使用skip-gram模型,1表示使用cbow模型,預設情況下是skip-gram模型,cbow模型快一些,skip-gram模型效果好一些
-num_features 表示輸出的詞向量維數
-window 為訓練的視窗大小,8表示每個詞考慮前8個詞與後8個詞(實際程式碼中還有一個隨機選視窗的過程,視窗大小<=5)
-sample 表示 取樣的閾值,如果一個詞在訓練樣本中出現的頻率越大,那麼就越會被取樣
-binary 表示輸出的結果檔案是否採用二進位制儲存,0表示不使用(即普通的文字儲存,可以開啟檢視),1表示使用,即vectors.bin的儲存型別
————————————-
除了上面所講的引數,還有:
-alpha 表示 學習速率
-min-count 表示設定最低頻率,預設為5,如果一個詞語在文件中出現的次數小於該閾值,那麼該詞就會被捨棄
-classes 表示詞聚類簇的個數,從相關原始碼中可以得出該聚類是採用k-means

模型訓練完成之後,得到了.bin這個詞向量檔案,檔案的儲存型別由binary引數覺得,如果為0,便可以直接用編輯器開啟,進行檢視.其中word2vec中提供了distance求詞的cosine相似度,並排序。也可以在訓練時,設定-classes引數來指定聚類的簇個數,使用kmeans進行聚類。

2、disttance函式

由於word2vec計算的是餘弦值,距離範圍為0-1之間,值越大代表這兩個詞關聯度越高,所以越排在上面的詞與輸入的詞越緊密[2]。

distance(file_name, word)
file_name;Path of the modle file.
word;The search word.

整個包就這樣結束了。。

——————————————————————————————————————————

二、text2vec包

該包寫於2016年3月21日,全名是Fast Text Mining Framework for Vectorization and Word Embeddings,向量化詞向量文字挖掘模型。

關於這個包,有待研究。

參考部落格:

《Word2vec的核心架構及其應用 · 熊富林,鄧怡豪,唐曉晟 · 北郵2015年》
《Word2vec的工作原理及應用探究 · 周練 · 西安電子科技大學2014年》
《Word2vec對中文詞進行聚類的研究 · 鄭文超,徐鵬 · 北京郵電大學2013年