【NLP】doc2vec原理及實踐
- 2019 年 10 月 7 日
- 筆記
點擊上方,選擇星標或置頂,每天給你送乾貨
閱讀大概需要7分鐘 跟隨小部落客,每天進步一丟丟
作者: Johnson0722
鏈接:https://blog.csdn.net/John_xyz/article/details/79208564
1.「句向量」簡介
word2vec提供了高品質的詞向量,並在一些任務中表現良好。
關於word2vec的原理可以參考這幾篇論文:
https://arxiv.org/pdf/1310.4546.pdf
https://arxiv.org/pdf/1301.3781.pdf
關於如何使用第三方庫gensim訓練word2vec可以參考這篇部落格:
http://blog.csdn.net/john_xyz/article/details/54706807
儘管word2vec提供了高品質的辭彙向量,仍然沒有有效的方法將它們結合成一個高品質的文檔向量。對於一個句子、文檔或者說一個段落,怎麼把這些數據投影到向量空間中,並具有豐富的語義表達呢?過去人們常常使用以下幾種方法:
- bag of words
- LDA
- average word vectors
- tfidf-weighting word vectors
就bag of words而言,有如下缺點:1.沒有考慮到單詞的順序,2.忽略了單詞的語義資訊。因此這種方法對於短文本效果很差,對於長文本效果一般,通常在科研中用來做baseline。
average word vectors就是簡單的對句子中的所有詞向量取平均。是一種簡單有效的方法,但缺點也是沒有考慮到單詞的順序
tfidf-weighting word vectors是指對句子中的所有詞向量根據tfidf權重加權求和,是常用的一種計算sentence embedding的方法,在某些問題上表現很好,相比於簡單的對所有詞向量求平均,考慮到了tfidf權重,因此句子中更重要的詞佔得比重就更大。但缺點也是沒有考慮到單詞的順序
LDA模型當然就是計算出一片文檔或者句子的主題分布。也常常用於文本分類任務,後面會專門寫一篇文章介紹LDA模型和doc2vec的本質不同
2. doc2vec原理
doc2vec是google的兩位大牛Quoc Le和Tomas Mikolov在2014年提出的,原始論文地址如下:
https://cs.stanford.edu/~quocle/paragraph_vector.pdf
Doc2Vec 或者叫做 paragraph2vec, sentence embeddings,是一種非監督式演算法,可以獲得 sentences/paragraphs/documents 的向量表達,是 word2vec 的拓展。學出來的向量可以通過計算距離來找 sentences/paragraphs/documents 之間的相似性,可以用於文本聚類,對於有標籤的數據,還可以用監督學習的方法進行文本分類,例如經典的情感分析問題。
在介紹doc2vec原理之前,先簡單回顧下word2vec的原理
word2vec基本原理
熟悉word2vec的同學都知道,下圖是學習詞向量表達最經典的一幅圖。在下圖中,任務就是給定上下文,預測上下文的其他單詞。

其中,每個單詞都被映射到向量空間中,將上下文的詞向量級聯或者求和作為特徵,預測句子中的下一個單詞。一般地:給定如下訓練單詞序列

,目標函數是

當然,預測的任務是一個多分類問題,分類器最後一層使用softmax,計算公式如下:

這裡的每一個

可以理解為預測出每個word的概率。因為在該任務中,每個詞就可以看成一個類別。計算

的公式如下:

這裡U和b都是參數,h是將

級聯或者求平均。
因為每個單詞都是一類,所以類別眾多,在計算softmax歸一化的時候,效率很低。因此使用hierarical softmax加快計算速度,其實就是huffman樹,這個不再贅述,有興趣的同學可以看word2vec的paper。
doc2vec基本原理
1. A distributed memory model
訓練句向量的方法和詞向量的方法非常類似。訓練詞向量的核心思想就是說可以根據每個單詞

的上下文預測

,也就是說上下文的單詞對

是有影響的。那麼同理,可以用同樣的方法訓練doc2vec。例如對於一個句子s: i want to drink water,如果要去預測句子中的單詞want,那麼不僅可以根據其他單詞生成feature, 也可以根據其他單詞和句子ss來生成feature進行預測。因此doc2vec的框架如下所示:

每個段落/句子都被映射到向量空間中,可以用矩陣DD的一列來表示。每個單詞同樣被映射到向量空間,可以用矩陣WW的一列來表示。然後將段落向量和詞向量級聯或者求平均得到特徵,預測句子中的下一個單詞。
這個段落向量/句向量也可以認為是一個單詞,它的作用相當於是上下文的記憶單元或者是這個段落的主題,所以我們一般叫這種訓練方法為Distributed Memory Model of Paragraph Vectors(PV-DM)
在訓練的時候我們固定上下文的長度,用滑動窗口的方法產生訓練集。段落向量/句向量 在該上下文中共享。
總結doc2vec的過程, 主要有兩步:
- 訓練模型,在已知的訓練數據中得到詞向量W, softmax的參數U和b,以及段落向量/句向量D
- 推斷過程(inference stage),對於新的段落,得到其向量表達。具體地,在矩陣D中添加更多的列,在固定WW,UU,bb的情況下,利用上述方法進行訓練,使用梯度下降的方法得到新的D,從而得到新段落的向量表達。
2. Paragraph Vector without word ordering: Distributed bag of words
還有一種訓練方法是忽略輸入的上下文,讓模型去預測段落中的隨機一個單詞。就是在每次迭代的時候,從文本中取樣得到一個窗口,再從這個窗口中隨機取樣一個單詞作為預測任務,讓模型去預測,輸入就是段落向量。如下所示:

我們稱這種模型為 Distributed Bag of Words version of Paragraph Vector(PV-DBOW)
在上述兩種方法中,我們可以使用PV-DM或者PV-DBOW得到段落向量/句向量。對於大多數任務,PV-DM的方法表現很好,但我們也強烈推薦兩種方法相結合。
3. 基於gensim的doc2vec實踐
我們使用第三方庫gensim進行doc2vec模型的訓練
# -*- coding: utf-8 -*- import sys import logging import os import gensim # 引入doc2vec from gensim.models import Doc2Vec curPath = os.path.abspath(os.path.dirname(__file__)) rootPath = os.path.split(curPath)[0] sys.path.append(rootPath) from utilties import ko_title2words # 引入日誌配置 logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) # 載入數據 documents = [] # 使用count當做每個句子的「標籤」,標籤和每個句子是一一對應的 count = 0 with open('../data/titles/ko.video.corpus','r') as f: for line in f: title = unicode(line, 'utf-8') # 切詞,返回的結果是列表類型 words = ko_title2words(title) # 這裡documents里的每個元素是二元組,具體可以查看函數文檔 documents.append(gensim.models.doc2vec.TaggedDocument(words, [str(count)])) count += 1 if count % 10000 == 0: logging.info('{} has loaded...'.format(count)) # 模型訓練 model = Doc2Vec(documents, dm=1, size=100, window=8, min_count=5, workers=4) # 保存模型 model.save('models/ko_d2v.model')
接下來看看訓練好的模型可以做什麼
def test_doc2vec(): # 載入模型 model = doc2vec.Doc2Vec.load('models/ko_d2v.model') # 與標籤『0』最相似的 print(model.docvecs.most_similar('0')) # 進行相關性比較 print(model.docvecs.similarity('0','1')) # 輸出標籤為『10』句子的向量 print(model.docvecs['10']) # 也可以推斷一個句向量(未出現在語料中) words = u"여기 나오는 팀 다 가슴" print(model.infer_vector(words.split())) # 也可以輸出詞向量 print(model[u'가슴'])
以上都是一些比較常見的用法,更多的用法請參https://radimrehurek.com/gensim/models/doc2vec.html
python方向有很多:機器學習、深度學習,python,情感分析、意見挖掘、句法分析、機器翻譯、人機對話、知識圖譜、語音識別等。