1. 程式人生 > >Gensim進階教程:訓練word2vec與doc2vec模型

Gensim進階教程:訓練word2vec與doc2vec模型

本篇部落格是Gensim的進階教程,主要介紹用於詞向量建模的word2vec模型和用於長文字向量建模的doc2vec模型在Gensim中的實現。

Word2vec

Word2vec並不是一個模型——它其實是2013年Mikolov開源的一款用於計算詞向量的工具。關於Word2vec更多的原理性的介紹,可以參見我的另一篇部落格:word2vec前世今生

在Gensim中實現word2vec模型非常簡單。首先,我們需要將原始的訓練語料轉化成一個sentence的迭代器;每一次迭代返回的sentence是一個word(utf8格式)的列表:

class MySentences(object):
    def __init__(self, dirname):
        self.dirname = dirname

    def __iter__(self):
        for fname in os.listdir(self.dirname):
            for line in open(os.path.join(self.dirname, fname)):
                yield line.split()

sentences = MySentences('/some/directory') # a memory-friendly iterator

接下來,我們用這個迭代器作為輸入,構造一個Gensim內建的word2vec模型的物件(即將原始的one-hot向量轉化為word2vec向量):

model = gensim.models.Word2Vec(sentences)

如此,便完成了一個word2vec模型的訓練。

我們也可以指定模型訓練的引數,例如採用的模型(Skip-gram或是CBoW);負取樣的個數;embedding向量的維度等。具體的引數列表在這裡

同樣,我們也可以通過呼叫save()load()方法完成word2vec模型的持久化。此外,word2vec物件也支援原始bin檔案格式的讀寫。

Word2vec物件還支援online learning。我們可以將更多的訓練資料傳遞給一個已經訓練好的word2vec物件,繼續更新模型的引數:

model = gensim.models.Word2Vec.load('/tmp/mymodel')
model.train(more_sentences)

若要檢視某一個word對應的word2vec向量,可以將這個word作為索引傳遞給訓練好的模型物件:

model['computer']  # raw NumPy vector of a word

Doc2vec

Doc2vec是Mikolov在word2vec基礎上提出的另一個用於計算長文字向量的工具。它的工作原理與word2vec極為相似——只是將長文字作為一個特殊的token id引入訓練語料中。在Gensim中,doc2vec也是繼承於word2vec的一個子類。因此,無論是API的引數介面還是呼叫文字向量的方式,doc2vec與word2vec都極為相似。

主要的區別是在對輸入資料的預處理上。Doc2vec接受一個由LabeledSentence物件組成的迭代器作為其建構函式的輸入引數。其中,LabeledSentence是Gensim內建的一個類,它接受兩個List作為其初始化的引數:word list和label list。

from gensim.models.doc2vec import LabeledSentence
sentence = LabeledSentence(words=[u'some', u'words', u'here'], tags=[u'SENT_1'])

類似地,可以構造一個迭代器物件,將原始的訓練資料文字轉化成LabeledSentence物件:

class LabeledLineSentence(object):
    def __init__(self, filename):
        self.filename = filename
        
    def __iter__(self):
        for uid, line in enumerate(open(filename)):
            yield LabeledSentence(words=line.split(), labels=['SENT_%s' % uid])

準備好訓練資料,模型的訓練便只是一行命令:

from gensim.models import Doc2Vec
model = Doc2Vec(dm=1, size=100, window=5, negative=5, hs=0, min_count=2, workers=4)

該程式碼將同時訓練word和sentence label的語義向量。如果我們只想訓練label向量,可以傳入引數train_words=False以固定詞向量引數。更多引數的含義可以參見這裡的API文件

注意,在目前版本的doc2vec實現中,每一個Sentence vector都是常駐記憶體的。因此,模型訓練所需的記憶體大小同訓練語料的大小正相關。