gensim學習筆記


1、詞向量建模的word2vec模型和用於長文本向量建模的doc2vec模型

  在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)

  我們也可以指定模型訓練的參數,例如采用的模型(Skip-gram或是CBoW);負采樣的個數;embedding向量的維度等。

  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是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以固定詞向量參數,傳入參數訓練可用

model.train(sentense)

 

2、ldamodel LDA主題聚類模型

  首先介紹下ldamodel的幾個屬性和方法。
  • num_terms:獲取字典中詞的個數,一般就是訓練樣本中所有不同詞的個數;num_topics:獲取主題的個數,一般是訓練時自己設的,默認值是100;num_updates:獲取文檔的個數,字面上是獲取更新的次數,在這里,每一個文檔都是一次更新,所以就是文檔個數。
  • get_topic_terms(topicid, topn=10):獲取某個主題下的前topn個詞語,越相關的在前面,topicid是要顯示主題的id值;
  • get_term_topics(word_id, minimum_probability=None):獲取某個詞最有可能的主題列表,word_id為詞id值,minimum_probability為閾值;
  • get_document_topics(bow, minimum_probability=None, minimum_phi_value=None, per_word_topics=False):per_word_topics為False時獲取某個文檔最有可能具有的主題列表,per_word_topics為True時還得到文檔中每個詞屬於的主題列表,bow為文檔,minimum_probability確定主題的閾值,minimum_phi_value判斷詞屬於主題的閾值。

  如果用get_term_topics(word_id),只會獲得在整個樣本下,某個詞屬於某些主題的可能性,而並不是針對特定文檔的某個詞屬於某些主題的可能性。顯然,使用get_document_topics(bow, per_word_topics=True)可以得到,比如:

  整個返回是個元組,形式為([a],[b],[c]),上圖中第一行為a列表,顯示的內容是可能性大於minimum_probability的主題及其可能性;第二行為b列表,顯示每個詞及其可能屬於的主題,且其可能性大於minimum_phi_value;第三行為c列表,顯示每個詞及其可能屬於的主題以及可能性。如果只使用get_document_topics(bow)那么只會顯示第一行數據。
算法部分,確實主題是根據上下文有變化的,在gensim包中,應用的是EM算法,但卻不是原始論文中使用的變分EM算法,當然主要思想是一致的。就像批最優化與隨機最優化的關系,哈夫曼的算法中,沒有將所有文檔整體帶入進行迭代計算,而是對每一篇文檔進行迭代計算,使得當前文檔具有最優的doc-topic和topic-word分布,直至所有文檔迭代完。所以在計算新文檔時,只需對新文檔再進行一次迭代更新(這也是為什么num_updates等於文檔數的,因為每個文檔都會更新一次)就可獲得新文檔相應的分布。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM