Python學習筆記-gensim初識Word2Vec、Doc2Vec

安裝依賴工具包:

pip install -U gensim

安裝過程中出現已經安裝過的工具包衝突可以uninstall或刪除Lib目錄下相關包或使用:

pip install -U gensim --ignore-installed scipy

Word2Vec、Doc2Vec原理可以參考鏈接:

https://blog.csdn.net/mpk_no1/article/details/72458003

簡單操作代碼如下:

# -*- coding:utf-8 -*-

import os
import sys
import jieba
import logging
import pymongo
from gensim.models.doc2vec import TaggedDocument, Doc2Vec
from gensim.models.word2vec import Text8Corpus, LineSentence, Word2Vec


default_encoding = 'utf-8'
if sys.getdefaultencoding() != default_encoding:
    reload(sys)
    sys.setdefaultencoding(default_encoding)


logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', level=logging.INFO)


# 網上隨便爬取一些新聞存入數據庫
client = pymongo.MongoClient(host='192.168.0.1', port=27017)
db = client['news']

# 停用詞
chinese_stop_words_file = os.path.abspath(os.getcwd() + os.sep + '..' + os.sep + 'static' + os.sep + 'dic' + os.sep + 'chinese_stop_words.txt')
chinese_stop_words = [line.strip() for line in open(chinese_stop_words_file, 'r').readlines()]

total_cut_word_count = 0


# 句子分割
def sentence_segment(sentence):
    global total_cut_word_count
    result = []
    cut_words = jieba.cut(sentence)
    for cut_word in cut_words:
        if cut_word not in chinese_stop_words:
            result.append(cut_word)
            total_cut_word_count += 1
    return result


# 準備語料庫
def prepare_word_corpus():
    datas = db['netease_ent_news_detail'].find({"create_time": {"$ne": None}}).sort('create_time', pymongo.ASCENDING)
    print datas.count()
    corpus = ''
    for data in datas:
        if data['title'] is not None and data['content'] is not None:
            sentence = str(data['title']).strip()
            corpus += ' '.join(sentence_segment(sentence)) + '\n'
    with open('word_corpus.txt', 'wb') as f:
        f.write(corpus)


# 準備語料庫
def prepare_doc_corpus():
    datas = db['netease_ent_news_detail'].find({"create_time": {"$ne": None}}).sort('create_time', pymongo.ASCENDING)
    print datas.count()
    for i, data in enumerate(datas):
        if data['title'] is not None and data['content'] is not None:
            title = str(data['title']).strip()
            content = str(data['content']).strip()
            yield TaggedDocument(sentence_segment(title), [data['_id']])


# 訓練模型
def train_word_model():
    prepare_word_corpus()
    # sentences: 要分析的語料,可以是一個列表或者從文件中遍歷讀出。對於大語料集,建議使用BrownCorpus, Text8Corpus或lineSentence構建。
    # size: 詞向量的維度,默認值是100。這個維度的取值一般與我們的語料的大小相關,視語料庫的大小而定。
    # alpha: 初始的學習速率,在訓練過程中會線性地遞減到min_alpha。
    # window: 詞向量上下文最大距離,skip - gram和cbow算法是基於滑動窗口來做預測。默認值爲5。
    # 在實際使用中,可以根據實際的需求來動態調整這個window的大小。對於一般的語料這個值推薦在[5, 10]之間。
    # min_count: 對字典做截斷.詞頻少於min_count次數的單詞會被丟棄掉, 默認值爲5。
    # max_vocab_size: 設置詞向量構建期間的RAM限制,設置成None則沒有限制。
    # sample: 高頻詞彙的隨機降採樣的配置閾值,默認爲1e - 3,範圍是(0, 1e-5)。
    # seed: 用於隨機數發生器。與初始化詞向量有關。
    # workers: 用於控制訓練的並行數。
    # min_alpha: 由於算法支持在迭代的過程中逐漸減小步長,min_alpha給出了最小的迭代步長值。
    # 隨機梯度下降中每輪的迭代步長可以由iter、alpha、min_alpha一起得出。對於大語料,需要對alpha、min_alpha、iter一起調參來選                        擇合適的三個值。
    # sg: 即我們的word2vec兩個模型的選擇了。如果是0則是CBOW模型,是1則是Skip-Gram模型,默認是0即CBOW模型。
    # hs: 即我們的word2vec兩個解法的選擇了,如果是0則是Negative Sampling,
    # 1的話並且負採樣個數negative大於0則是Hierarchical Softmax。默認是0即Negative Sampling。
    # negative: 如果大於零,則會採用negative sampling,用於設置多少個noise words(一般是5-20)。
    # cbow_mean: 僅用於CBOW在做投影的時候,爲0則採用上下文的詞向量之和,爲1則爲上下文的詞向量的平均值。默認值也是1不推薦修改默認值。
    # hashfxn: hash函數來初始化權重,默認使用python的hash函數。
    # iter: 隨機梯度下降法中迭代的最大次數,默認是5。對於大語料,可以增大這個值。
    # trim_rule: 用於設置詞彙表的整理規則,指定那些單詞要留下,哪些要被刪除。可以設置爲None(min_count會被使用)。
    # sorted_vocab: 如果爲1(默認)則在分配word index的時候會先對單詞基於頻率降序排序。
    # batch_words:每一批的傳遞給線程的單詞的數量,默認爲10000。
    word2vec = Word2Vec(Text8Corpus('word_corpus.txt'), size=200, window=5, min_count=2, workers=4, iter=10)
    word2vec.save('word2vec.model')
    # word2vec.save_word2vec_format('word2vec.model', binary=False)  不能追加訓練


# 訓練模型
def train_doc_model():
    corpus = prepare_doc_corpus()
    # vector_size: int, optional Dimensionality of the feature vectors.
    # window: int, optional The maximum distance between the current and predicted word within a sentence.
    # min_count: int, optional Ignores all words with total frequency lower than this.
    # max_vocab_size: int, optional Limits the RAM during vocabulary building; if there are more unique
    # words than this, then prune the infrequent ones. Every 10 million word types need about 1GB of RAM.
    # Set to `None` for no limit.
    # sample: float, optional The threshold for configuring which higher-frequency words are randomly downsampled,
    # useful range is (0, 1e-5).
    # negative: int, optional
    # If > 0, negative sampling will be used, the int for negative specifies how many "noise words"
    # should be drawn (usually between 5-20). If set to 0, no negative sampling is used.
    # workers: int, optional Use these many worker threads to train the model(=faster training with multicore machines).
    # epochs: int, optional Number of iterations (epochs) over the corpus.
    doc2vec = Doc2Vec(vector_size=300, min_count=2, window=10, workers=4, epochs=20)
    doc2vec.build_vocab(corpus)
    doc2vec.train(corpus, total_examples=doc2vec.corpus_count, epochs=doc2vec.epochs)
    doc2vec.save('doc2vec.model')


# 測試模型
def test_word_model_1(sentence_1, sentence_2):
    word2vec = Word2Vec.load('word2vec.model')
    print word2vec.wv.similarity(sentence_1, sentence_2)


# 測試模型
def test_word_model_2(sentence, topn=10):
    word2vec = Word2Vec.load('word2vec.model')
    similar_words = word2vec.wv.most_similar(sentence, topn=topn)
    for similar_word in similar_words:
        print '{} {}'.format(similar_word[0], similar_word[1])


# 測試模型
def test_word_model_3(sentence, topn=10):
    word2vec = Word2Vec.load('word2vec.model')
    similar_words = word2vec.wv.similar_by_word(sentence, topn=topn)
    for similar_word in similar_words:
        print '{} {}'.format(similar_word[0], similar_word[1])


# 測試模型
def test_word_model_4(words):
    word2vec = Word2Vec.load('word2vec.model')
    doesnt_match_words = word2vec.wv.doesnt_match(words)
    print doesnt_match_words


# 測試模型
def test_doc_model(sentence):
    doc2vec = Doc2Vec.load('doc2vec.model')
    result = doc2vec.infer_vector(sentence_segment(sentence))
    similar_docs = doc2vec.docvecs.most_similar([result], topn=10)
    for similar_doc in similar_docs:
        data = db['netease_ent_news_detail'].find_one({'_id': similar_doc[0]})
        print '{} {} {}'.format(similar_doc[1], str(data['title']).strip(), data['create_time'])

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章