當前位置:
首頁 > 知識 > 博客 Word2Vec 學習心得

博客 Word2Vec 學習心得

好嘛博主食言了。不過本文沒什麼乾貨,主要是前後看了大概一個星期,反覆去讀源碼和解讀文章,終於感覺這東西不那麼雲山霧罩了。同時也發現網上很多材料有點扯淡,99% 的博文不過是把別人的東西用自己的話說一下,人云亦云。好多人自己理解錯了而不自知,實在是誤人誤己。

我也不敢說理解得有多深,下面的內容甚至可能有自相矛盾的地方,所以閱讀本文時請一定擦亮眼睛,認真思考。

源碼才是根本,作者那兩篇論文感覺參考價值也不高。說到底,Machine Learning/Deep Learning 的價值在於實踐,而實際開發的應用中經過大量的 tricks 之後,代碼跟論文推導、實驗可能相去甚遠。

Data Mining 是一門實驗科學,編程實現、實驗所用的數據集都可能對假設和結論產生無法預知的影響,希望各位時刻牢記。


0 一段前言

個人覺得學 Word2Vec 有幾種路徑。如果你代碼能力足夠,建議直接讀作者的原始論文和 Rong Xin 的解釋篇,然後找一些比較高質量的源碼解析作為輔助,這樣效率比較高。如果不行,那就得多讀一些東西,比如來斯為的博文和博士論文、網上中文的英文的詳解博客,建立一組整體概念,然後對照源碼來看。

前者的典型見:

http://www.cnblogs.com/neopenx/p/4571996.html

後者的典型是皮果提的「Word2Vec 數學原理」系列。正如前者所說,數學熟練如皮果提也在理解 Skip-Gram 時犯了先入為主的錯誤;而強如 Physcal 也會一時疏忽把 Huffman 樹記成了滿二叉樹。

所以再三強調,要批判地看本文和網上一切的解讀文章。感慨一下,我因為這個東西看了不下三十篇中文的英文的博文,皮果提的「數學原理」頗有誇大其詞之嫌,但已經算是相當有深度的,像其他一些所謂解讀不過是把論文的圖複製過來然後用自己的理解隨便說兩句,所以你能看到大量相關博文介紹 CBOW、Skip-Gram 倆模型但往往淺嘗輒止。

理解到 Physcal 博文即 http://www.cnblogs.com/neopenx/p/4571996.html 這篇程度的人恐怕不足千分之一,包括但不限於皮果提、網易的w2v筆記和國外一些看起來很好看的博文。大多數人只是簡單看了一下論文,好一點兒的如來斯為的博文和博士論文,也只是做了發展梳理和一些後續實驗,感覺並沒有結合代碼本身對論文的提法做一些重構。

那篇「秒懂詞向量」的文章也不過是剛入門的程度,感覺比我強不到哪兒去……

對了,蘇劍林的科學空間建議看一下,我覺得這位在 NLP 方面的理解也很厲害,可能跟數學出身有關吧。

本文將根據自己的理解,把 Word2Vec 這款開源工具做一點梳理,可能更適合釐清一些誤解而不適合新手入門。有需要可以參考上面的說明自己找資料學習,文中不會過多解釋。


1 幾個概念

1.1 Word2Vec

Word2Vec 是 Google 開源的一款詞向量訓練工具,特點是效率高,據稱可」單機在一天內訓練完一個包含 16 億單詞的訓練集」。它是對以往的 NNLM 的改進,相關內容可參考來斯為的博客和博士論文,介紹比較詳細。

但 Word2Vec 並不是最佳的詞向量訓練工具,它流行的原因是 Google 光環加成和相對高效。更新的 FastText 速度更快,而且論文也有去了 FB 的 Mikolov 掛名。

實際上就「詞的分散式表示(DR)」問題有三類模型,據來斯為的博士論文,包括:

基於矩陣的DR,包括 tf-idf based LSA,GloVe 等

基於聚類的DR,如布朗聚類

基於NN的DR即 Word Vector,可以對上下文、上下文與目標詞關係進行建模

「分布表示(distributional representation)」意為「通過上下文表示語義」。根據實驗,三類模型之間不存在誰好誰壞,參數不同、語料不同時表現(「精確程度」的各類衡量指標和訓練速度)相差很大。而且三類模型之間存在一定的聯繫,如來斯為證明了 Skip-gram + Negtive Sampling 與 Glove 的等價性。可以說不同的演算法更多是對不同的指標的權衡,應當根據實際情況選擇合適的方案。希望讀者不要忘記這一點。

1.2 CBOW & Skip-gram

完整的 NNLM 最早由 Bengio(2003) 提出,可以看作四層網路。由於隱藏層有非線性、輸出層是 Softmax (輸出到詞表大小),計算量非常大。

Mikolov 提出的 CBOW 、 Skip-Gram 兩個模型,是對過去 NNLM 的大幅簡化,除輸出仍為 Softmax 外,只有一層線性連接。Hierarchical Softmax 和 Negative Sampling 則是進一步加速訓練的方法。總之 Mikolov 取勝的最主要因素就是訓練速度,在給出過得去的準確度的情況下使用很多激進方法加速。這方面網上也有很多對比,不再贅述。

另外參見 Physcal 的文章,Skip-Gram 不是 CBOW 的對稱模型,而是一個精度更高的版本。「CBOW 是上下文預測當前詞、Skip-Gram 是當前詞預測上下文」的說法並不準確,只是一種曖昧的形容而非實事。作為專業人士要盡量避免「用簡單形容來概括複雜操作/概念」的嘗試,用來向外行人解釋或者加強自己的記憶尚可,當了真就不對。想知道真實情況,應該去讀源碼。

來斯為的博士論文里提了一句大意是「實際上兩個模型都是根據上下文預測當前詞」,只不過他的解釋是「兩種模型都要遍歷全文」,我也沒看懂到底哪個解釋更高明些……

word2vec.c 中,CBOW 是 422-482 行,SG 是 482-530 行。

可以看到,CBOW 是先在一個窗口內把 Context(w) 算完(求和-平均)做 FF 、BP,更新窗口詞的參數,而 Skip-Gram 在窗口內則是逐個更新【目標詞和窗口中某個詞】組成的詞對,每個詞對更新一次參數。兩段代碼對比著看會更明顯。

也就是說, CBOW 的 FF 和 BP 都是一把梭,窗口裡的詞算完 FF 再算 BP;而 Skip-Gram 更小心,一個【詞對】算一次 FF 和 BP。這就是 SG 比 CBOW 要慢得多得多的原因。效果如何呢?網上一般的黑盒經驗就是所謂大語料用 CBOW,小語料用 SG 或者 CBOW 對高頻詞友好、 SG 對低頻詞友好了。說白了還是數據說話,試了才知道。

我覺得更合適的類比是,和兩個模型代表兩種訓練方法:CBOW 像 mini-batch,SG 像 online。這樣精度更高的含義好像就不難理解了吧?

Negative Sampling、Hierarchical Softmax 兩種模式的計算量看起來差不多,但由於 HS 採用了 Huffman 編碼,高頻詞路徑更短,所以對一般語料(大量高頻詞)的訓練速度會更快一些。

再用 Physcal 的話解釋一遍:CBOW 直接把上下文平均輸入進去更新目標詞,相當於把幾個詞看成了一個詞;而 Skip-Gram 仍然以詞對的形式將窗口內的詞逐個更新。

所以,雖然 Mikolov 論文里畫的圖是對稱的,兩個模型實際並非鏡像。Skip-gram 的圖畫成 1 對 n 是結果的一種呈現而不是計算過程的說明。

1.3 詞向量 & 詞嵌入

本條參考 Wikipedia。「詞嵌入是NLP中語言模型和表徵技術的統稱,概念上它是把一個維數為詞庫大小的高維空間嵌入維數較低的連續向量空間中,每個單詞或片語被映射為實數域上的向量。」 Word2Vec 是詞嵌入技術的一種。

而詞向量是詞或片語在向量空間中的具體表示形式。

NNLM 通常可以看成三層網路:input-hidden/projection-output。Input 層填入詞的 one-hot 表示,hidden/projection 層最初是 tanh 函數、Word2Vec 中簡化為線性運算,output 層沒爭議,就是 Softmax 輸出到詞表。

通常,在語料上訓練得到 NNLM 後,input-projection 層的權重作為 DNN 的 embedding layer 使用。此時輸入的依然是 one-hot 。

考慮 one-hot 的運算特性不難看出,(根據表示方法不同)每個詞對應的「詞向量」就是權重矩陣/ embedding layer 相應行/列的參數向量。


2 兩條錯誤

前面說到,網上很多資料是有問題的。第一個錯誤在上文中已經指出,第二個錯誤與 one-hot 表示有關。這一點由蘇劍林(https://spaces.ac.cn/archives/4122)指出。

很多資料指出/複製他人的觀點認為 one-hot 的原罪在於其巨大二值稀疏矩陣效率低下。這種說法是有問題的。比如上文中蘇劍林說的,詞向量並沒有提升計算效率,輸入仍為 one-hot 形式,但多了嵌入層之後 one-hot 通過查表操作把長長的 0-1 表示變換到緊密的實數域向量上去了。

但蘇劍林其實說的也不全對。另一半答案可以看這篇博客,依然是 Physcal 的:

http://www.cnblogs.com/neopenx/p/4570648.html

推薦本文讀者多讀幾遍 Physcal 的兩篇博文,作者的理解層次還是挺高的。

問題:維度過高

通常一個詞庫的大小是10^5,如果繼續用二進位編碼。那麼一個句子的維度是10^5。

要知道,AlexNet的一張圖片維度才256*256=65536, 就得拿GPU算好久,10^5基本得完蛋了。

實際上,10^5里,大部分都是維度都是廢的,真正有用的特徵就藏在那麼幾個維度中。

這說明,One-hot Representation表達的特徵維度過高,需要降維。然而,這還不是最坑爹的缺陷。

Bengio在2003年的A neural probabilistic language model中指出,維度過高,導致每次學習,都會強制改變大部分參數。

由此發生蝴蝶效應,本來很好的參數,可能就因為一個小小傳播誤差,就改的亂七八糟。

實際上,傳統MLP網路就是犯了這個錯誤,1D全連接的神經元控制了太多參數,不利於學習到稀疏特徵。

CNN網路,2D全連接的神經元則控制了局部感受野,有利於解離出稀疏特徵。

1.3中已經提過,在深度學習 NLP 任務中,文本依然以 one-hot 的形式輸入網路。

解釋得很清楚了。

one-hot 表示可以看作最粗糙但無損失的詞表示方法,它的缺點並不是稀疏,而是無法表達詞與詞之間的關係,即所謂語義鴻溝。在大規模語料上訓練 NNLM,可以利用 NN 學習到語料給出的語義信息、詞間關係,從而克服實踐中 one-hot 的缺點。

前兩天跟同學聊天也提到了這個事情。NNLM 僅僅是詞嵌入的一種工具,在實踐中不見得哪都有效。他們在做的事情就是想辦法用 CNN +貝葉斯直接在 one-hot 上訓練網路。據說騰訊 AI 的 Boss 張潼之前做過這個工作。但根據上面的說法我對這種思路表示懷疑……


3 一點想法

3.1 學習體會

看皮果提的博文可以發現,雖然論文里基本沒有理論的證明推導,但訓練網路實際需要很多計算,數學都在 Hierarchical Softmax 和 Negative Sampling 的 BP 上了。想知道的話可以看他的博文和 Rong Xin 的 Word2Vec 參數解釋,步驟詳盡。

源碼的編程技巧也不是我能講的,事實上理解以上內容就已經十分吃力了。什麼內存對齊、Huffman 樹構建,完全搞不定。

Word2Vec 不是一切,雖然它幾乎可以稱為標配——速度快、省內存。此外 GloVe 和 FastText 也各有長短,後者同樣以速度著稱。

就 DR 這個問題來說,很多人認為一個最大的難點在於如何衡量詞表示的好壞。對不同任務和數據集來說,各方法的結果表現差別很大,這裡面水就深了。

有人好奇 Word2Vec 有沒有其他實現版本。有。Tensorflow 官方有一個,但據說效率比 C 版差;Gensim 有一個基於 Python 的實現,用了 Cython + BLAS 加速,號稱遠超原版,但據說出來的結果跟原版不一樣;國內有大佬搞了 HanLP,並加入了自己的 Java 實現,據說比原版快一倍但精度稍差(http://www.hankcs.com/nlp/word2vec.html)。

最後,有問題去讀源碼、讀源碼、讀源碼。

要說三遍。

3.2 word2vec 的缺陷(update)

上面說過,word2vec 通過精簡原 NNLM 中的非線性提升效率,得到的結果非常不錯,所謂的

vec(king)?vec(man)+vec(woman)≈vec(queen)

說明訓練出的 wordvec 之間竟然具有類似線性的關係。這是之前沒有想到的。

通過大量類似的簡化,Word2Vec 在保證還不錯的準確度的前提下,具備了極高的效率。但問題也隨之而來,簡化是有代價的。Bengio 模型中,輸入是窗口詞拼接而來的,保留了先後次序,而 CBOW 和 Skip-Gram 對窗口內的詞一視同仁,也就忽略了它們之間的次序關係。

另外,NNLM 本質是利用神經網路去搜索和記憶數據中的有效統計信息。比如 https://zhuanlan.zhihu.com/p/29364112 文提到的微博語料訓練出的有害詞模型,輸入「垃圾」,與之相關度最高的依次是:

辣雞

拉圾

臘雞

狗屎

廢物

渣子

sb

表明這些詞在原文中與「垃圾」的距離最近(在前在後),或者具有相近的含義。但這裡的「含義」並不表示模型理解語義,而只是在訓練中發現這些詞在語句中是可以互相替換的——罵人的時候有用「垃圾」的,有用「辣雞」的。這兩點上文均有提及:相似的句子,相似位置/成分的詞更接近;實際距離更近的詞更接近。

這樣的結果也是由網路的訓練過程決定的。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 AI研習社 的精彩文章:

用 OpenCV 檢測圖像中各物體大小
文本分類又來了,用 Scikit-Learn 解決多類文本分類問題

TAG:AI研習社 |