gensim相關功能函數及其案例

目錄

一、gensim介紹

二、訓練模型

相關轉換

詞頻-逆文檔頻(Term Frequency * Inverse Document Frequency, Tf-Idf)

潛在語義索引(Latent Semantic Indexing,LSI,or sometimes LSA)

隨機映射(Random Projections,RP)

隱含狄利克雷分配(Latent Dirichlet Allocation, LDA)

分層狄利克雷過程(Hierarchical Dirichlet Process,HDP)

三、gensim訓練好的word2vec使用

案例一:800萬微信語料訓練

案例二:字向量與詞向量的訓練

案例三:Python+gensim-文本相似度分析

案例四:Python+gensim【中文LDA】簡潔模型

LINK:


一、gensim介紹

Gensim是一款開源的第三方Python工具包,用於從原始的非結構化的文本中,無監督地學習到文本隱層的主題向量表達。 
它支持包括TF-IDF,LSA,LDA,和word2vec在內的多種主題模型算法, 支持流式訓練,並提供了諸如相似度計算,信息檢索等一些常用任務的API接口。

基本的語料處理工具

  • LSI
  • LDA
  • HDP
  • DTM
  • DIM
  • TF-IDF
  • word2vec、paragraph2vec

基本概念

  • 語料(Corpus):一組原始文本的集合,用於無監督地訓練文本主題的隱層結構。語料中不需要人工標註的附加信息。在Gensim中,Corpus通常是一個可迭代的對象(比如列表)。每一次迭代返回一個可用於表達文本對象的稀疏向量。
  • 向量(Vector):由一組文本特徵構成的列表。是一段文本在Gensim中的內部表達。
  • 稀疏向量(SparseVector):通常,我們可以略去向量中多餘的0元素。此時,向量中的每一個元素是一個(key, value)的元組
  • 模型(Model):是一個抽象的術語。定義了兩個向量空間的變換(即從文本的一種向量表達變換爲另一種向量表達)。
     

二、訓練模型

1、訓練

最簡單的訓練方式:

# 最簡單的開始
import gensim
sentences = [['first', 'sentence'], ['second', 'sentence','is']]

# 模型訓練
model = gensim.models.Word2Vec(sentences, min_count=1)
    # min_count,頻數閾值,大於等於1的保留
    # size,神經網絡 NN 層單元數,它也對應了訓練算法的自由程度
    # workers=4,default = 1 worker = no parallelization 只有在機器已安裝 Cython 情況下才會起到作用。如沒有 Cython,則只能單核運行。

第二種訓練方式:

# 第二種訓練方式
new_model = gensim.models.Word2Vec(min_count=1)  # 先啓動一個空模型 an empty model
new_model.build_vocab(sentences)                 # can be a non-repeatable, 1-pass generator     
new_model.train(sentences, total_examples=new_model.corpus_count, epochs=new_model.iter)                       
# can be a non-repeatable, 1-pass generator

案例:

#encoding=utf-8
from gensim.models import word2vec
sentences=word2vec.Text8Corpus(u'分詞後的爽膚水評論.txt')
model=word2vec.Word2Vec(sentences, size=50)

y2=model.similarity(u"好", u"還行")
print(y2)

for i in model.most_similar(u"滋潤"):
    print i[0],i[1]

txt文件是已經分好詞的5W條評論,訓練模型只需一句話:

model=word2vec.Word2Vec(sentences,min_count=5,size=50)

第一個參數是訓練語料,第二個參數是小於該數的單詞會被剔除,默認值爲5,
第三個參數是神經網絡的隱藏層單元數,默認爲100

2、模型使用

# 根據詞向量求相似
model.similarity('first','is')    # 兩個詞的相似性距離
model.most_similar(positive=['first', 'second'], negative=['sentence'], topn=1)  # 類比的防護四
model.doesnt_match("input is lunch he sentence cat".split())                   # 找出不匹配的詞語

如何查看模型內部詞向量內容:

# 詞向量查詢
model['first'] 

3、模型導出與導入

最簡單的導入與導出

# 模型保存與載入
model.save('/tmp/mymodel')
new_model = gensim.models.Word2Vec.load('/tmp/mymodel')
odel = Word2Vec.load_word2vec_format('/tmp/vectors.txt', binary=False)  # 載入 .txt文件
# using gzipped/bz2 input works too, no need to unzip:
model = Word2Vec.load_word2vec_format('/tmp/vectors.bin.gz', binary=True)  # 載入 .bin文件

word2vec = gensim.models.word2vec.Word2Vec(sentences(), size=256, window=10, min_count=64, sg=1, hs=1, iter=10, workers=25)
word2vec.save('word2vec_wx')

word2vec.save即可導出文件,這邊沒有導出爲.bin

model = gensim.models.Word2Vec.load('xxx/word2vec_wx')
pd.Series(model.most_similar(u'微信',topn = 360000))

gensim.models.Word2Vec.load的辦法導入

其中的Numpy,可以用numpy.load:

import numpy
word_2x = numpy.load('xxx/word2vec_wx.wv.syn0.npy')

還有其他的導入方式:

import gensim
word_vectors = gensim.models.KeyedVectors.load_word2vec_format('/tmp/vectors.txt', binary=False)  # C text format
word_vectors = gensim.models.KeyedVectors.load_word2vec_format('/tmp/vectors.bin', binary=True)  # C binary format

導入txt格式+bin格式。

其他導出方式:

from gensim.models import KeyedVectors
# save
model.save(fname) # 只有這樣存才能繼續訓練! 
model.wv.save_word2vec_format(outfile + '.model.bin', binary=True)  # C binary format 磁盤空間比上一方法減半
model.wv.save_word2vec_format(outfile + '.model.txt', binary=False) # C text format 磁盤空間大,與方法一樣

# load
model = gensim.models.Word2Vec.load(fname)  
word_vectors = KeyedVectors.load_word2vec_format('/tmp/vectors.txt', binary=False)
word_vectors = KeyedVectors.load_word2vec_format('/tmp/vectors.bin', binary=True)

# 最省內存的加載方法
model = gensim.models.Word2Vec.load('model path')
word_vectors = model.wv
del model
word_vectors.init_sims(replace=True)

來源:簡書,其中:如果你不打算進一步訓練模型,調用init_sims將使得模型的存儲更加高效

4、增量訓練

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

不能對C生成的模型進行再訓練

# 增量訓練
model = gensim.models.Word2Vec.load(temp_path)
more_sentences = [['Advanced', 'users', 'can', 'load', 'a', 'model', 'and', 'continue', 'training', 'it', 'with', 'more', 'sentences']]
model.build_vocab(more_sentences, update=True)
model.train(more_sentences, total_examples=model.corpus_count, epochs=model.iter)

5、bow2vec + TFIDF模型

5.1 Bow2vec

主要內容爲:
拆分句子爲單詞顆粒,記號化;
生成詞典;
生成稀疏文檔矩陣。

documents = ["Human machine interface for lab abc computer applications",
             "A survey of user opinion of computer system response time",
             "The EPS user interface management system",
             "System and human system engineering testing of EPS",              
             "Relation of user perceived response time to error measurement",
             "The generation of random binary unordered trees",
             "The intersection graph of paths in trees",
             "Graph minors IV Widths of trees and well quasi ordering",
             "Graph minors A survey"]

# 分詞並根據詞頻剔除
# remove common words and tokenize
stoplist = set('for a of the and to in'.split())
texts = [[word for word in document.lower().split() if word not in stoplist]
         for document in documents]

# 生成詞語列表:
[['human', 'machine', 'interface', 'lab', 'abc', 'computer', 'applications'],
 ['survey', 'user', 'opinion', 'computer', 'system', 'response', 'time'],
 ['eps', 'user', 'interface', 'management', 'system'],
 ['system', 'human', 'system', 'engineering', 'testing', 'eps'],
 ['relation', 'user', 'perceived', 'response', 'time', 'error', 'measurement'],
 ['generation', 'random', 'binary', 'unordered', 'trees'],
 ['intersection', 'graph', 'paths', 'trees'],
 ['graph', 'minors', 'iv', 'widths', 'trees', 'well', 'quasi', 'ordering'],
 ['graph', 'minors', 'survey']]

# 詞典生成
dictionary = corpora.Dictionary(texts)
dictionary.save(os.path.join(TEMP_FOLDER, 'deerwester.dict'))  # store the dictionary, for future reference
print(dictionary)
print(dictionary.token2id)  # 查看詞典中所有詞

# 稀疏文檔矩陣的生成:
# 單句bow 生成
new_doc = "Human computer interaction Human"
new_vec = dictionary.doc2bow(new_doc.lower().split())
print(new_vec)  
    # the word "interaction" does not appear in the dictionary and is ignored
    # [(0, 1), (1, 1)] ,詞典(dictionary)中第0個詞,出現的頻數爲1(當前句子),
    # 第1個詞,出現的頻數爲1
    
# 多句bow 生成
[dictionary.doc2bow(text) for text in texts]  # 當前句子的詞ID + 詞頻

5.2 tfidf

from gensim import corpora, models, similarities
corpus = [[(0, 1.0), (1, 1.0), (2, 1.0)],
          [(2, 1.0), (3, 1.0), (4, 1.0), (5, 1.0), (6, 1.0), (8, 1.0)],
          [(1, 1.0), (3, 1.0), (4, 1.0), (7, 1.0)],
          [(0, 1.0), (4, 2.0), (7, 1.0)],
          [(3, 1.0), (5, 1.0), (6, 1.0)],
          [(9, 1.0)],
          [(9, 1.0), (10, 1.0)],
          [(9, 1.0), (10, 1.0), (11, 1.0)],
          [(8, 1.0), (10, 1.0), (11, 1.0)]]
tfidf = models.TfidfModel(corpus)

# 詞袋模型,實踐
vec = [(0, 1), (4, 1),(9, 1)]
print(tfidf[vec])
>>>  [(0, 0.695546419520037), (4, 0.5080429008916749), (9, 0.5080429008916749)]

查找vec中,0,4,9號三個詞的TFIDF值。同時進行轉化,把之前的文檔矩陣中的詞頻變成了TFIDF值。

利用tfidf求相似:

# 求相似
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=12)
vec = [(0, 1), (4, 1),(9, 1)]
sims = index[tfidf[vec]]
print(list(enumerate(sims)))
>>>[(0, 0.40157393), (1, 0.16485332), (2, 0.21189235), (3, 0.70710677), (4, 0.0), (5, 0.5080429), (6, 0.35924056), (7, 0.25810757), (8, 0.0)]

對corpus的9個文檔建立文檔級別的索引,vec是一個新文檔的詞語的詞袋內容,sim就是該vec向量對corpus中的九個文檔的相似性。

索引的導出與載入:

index.save('/tmp/deerwester.index')
index = similarities.MatrixSimilarity.load('/tmp/deerwester.index')

5.3 繼續轉換

潛在語義索引(LSI) 將Tf-Idf語料轉化爲一個潛在2-D空間

lsi = models.LsiModel(tfidf[corpus], id2word=dictionary, num_topics=2) # 初始化一個LSI轉換
corpus_lsi = lsi[tfidf[corpus]] # 在原始語料庫上加上雙重包裝: bow->tfidf->fold-in-lsi

設置了num_topics=2,
利用models.LsiModel.print_topics()來檢查一下這個過程到底產生了什麼變化吧:

lsi.print_topics(2)

根據LSI來看,“tree”、“graph”、“minors”都是相關的詞語(而且在第一主題的方向上貢獻最多),而第二主題實際上與所有的詞語都有關係。如我們所料,前五個文檔與第二個主題的關聯更強,而其他四個文檔與第一個主題關聯最強:

>>> for doc in corpus_lsi: # both bow->tfidf and tfidf->lsi transformations are actually executed here, on the fly
...     print(doc)
[(0, -0.066), (1, 0.520)] # "Human machine interface for lab abc computer applications"
[(0, -0.197), (1, 0.761)] # "A survey of user opinion of computer system response time"
[(0, -0.090), (1, 0.724)] # "The EPS user interface management system"
[(0, -0.076), (1, 0.632)] # "System and human system engineering testing of EPS"
[(0, -0.102), (1, 0.574)] # "Relation of user perceived response time to error measurement"
[(0, -0.703), (1, -0.161)] # "The generation of random binary unordered trees"
[(0, -0.877), (1, -0.168)] # "The intersection graph of paths in trees"
[(0, -0.910), (1, -0.141)] # "Graph minors IV Widths of trees and well quasi ordering"
[(0, -0.617), (1, 0.054)] # "Graph minors A survey"

相關轉換

參考:《 Gensim官方教程翻譯(三)——主題與轉換(Topics and Transformations)》

詞頻-逆文檔頻(Term Frequency * Inverse Document Frequency, Tf-Idf)

一個詞袋形式(整數值)的訓練語料庫來實現初始化。

model = tfidfmodel.TfidfModel(bow_corpus, normalize=True)

潛在語義索引(Latent Semantic Indexing,LSI,or sometimes LSA)

將文檔從詞袋或TfIdf權重空間(更好)轉化爲一個低維的潛在空間。在真正的語料庫上,推薦200-500的目標維度爲“金標準”。

model = lsimodel.LsiModel(tfidf_corpus, id2word=dictionary, num_topics=300)

LSI訓練的獨特之處是我們能在任何繼續“訓練”,僅需提供更多的訓練文本。這是通過對底層模型進行增量更新,這個過程被稱爲“在線訓練”。正因爲它的這個特性,輸入文檔流可以是無限大——我們能在以只讀的方式使用計算好的模型的同時,還能在新文檔到達時一直“餵食”給LSI“消化”!

model.add_documents(another_tfidf_corpus) # 現在LSI已經使用tfidf_corpus + another_tfidf_corpus進行過訓練了
lsi_vec = model[tfidf_vec] # 將新文檔轉化到LSI空間不會影響該模型
...
model.add_documents(more_documents) # tfidf_corpus + another_tfidf_corpus + more_documents
lsi_vec = model[tfidf_vec]

隨機映射(Random Projections,RP)

目的在於減小空維度。這是一個非常高效(對CPU和內存都很友好)方法,通過拋出一點點隨機性,來近似得到兩個文檔之間的Tfidf距離。推薦目標維度也是成百上千,具體數值要視你的數據集大小而定。

model = rpmodel.RpModel(tfidf_corpus, num_topics=500)

隱含狄利克雷分配(Latent Dirichlet Allocation, LDA)

也是將詞袋計數轉化爲一個低維主題空間的轉換。LDA是LSA(也叫多項式PCA)的概率擴展,因此LDA的主題可以被解釋爲詞語的概率分佈。這些分佈式從訓練語料庫中自動推斷的,就像LSA一樣。相應地,文檔可以被解釋爲這些主題的一個(軟)混合(又是就像LSA一樣)。

model = ldamodel.LdaModel(bow_corpus, id2word=dictionary, num_topics=100)

gensim使用一個基於[2]的快速的在線LDA參數估計實現,修改並使其可以在計算機集羣上以分佈式模式運行。

分層狄利克雷過程(Hierarchical Dirichlet Process,HDP)

是一個無參數貝葉斯方法(注意:這裏沒有num_topics參數):

model = hdpmodel.HdpModel(bow_corpus, id2word=dictionary)

gensim使用一種基於[3]的快速在線來實現。該算法是新加入gensim的,並且還是一種粗糙的學術邊緣產品——小心使用。
增加新的VSM轉化(例如新的權重方案)相當平常;參見API參考或者直接參考我們的源代碼以獲取信息與幫助。

三、gensim訓練好的word2vec使用

1、相似性

持數種單詞相似度任務:
相似詞+相似係數(model.most_similar)、model.doesnt_match、model.similarity(兩兩相似)

model.most_similar(positive=['woman', 'king'], negative=['man'], topn=1)
[('queen', 0.50882536)]

model.most_similar(positive=‘woman’, topn=topn, restrict_vocab=restrict_vocab)  # 直接給入詞
model.most_similar(positive=[vector], topn=topn, restrict_vocab=restrict_vocab)  # 直接給入向量

model.doesnt_match("breakfast cereal dinner lunch".split())
'cereal'

model.similarity('woman', 'man')
.73723527

2、詞向量

通過以下方式來得到單詞的向量:

model['computer']  # raw NumPy vector of a word
array([-0.00449447, -0.00310097,  0.02421786, ...], dtype=float32)

3、 詞向量表

model.wv.vocab.keys()

案例一:800萬微信語料訓練

來源於:【不可思議的Word2Vec】 2.訓練好的模型

訓練過程:

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

import pymongo
import hashlib

db = pymongo.MongoClient('172.16.0.101').weixin.text_articles_words
md5 = lambda s: hashlib.md5(s).hexdigest()
class sentences:
    def __iter__(self):
        texts_set = set()
        for a in db.find(no_cursor_timeout=True):
            if md5(a['text'].encode('utf-8')) in texts_set:
                continue
            else:
                texts_set.add(md5(a['text'].encode('utf-8')))
                yield a['words']
        print u'最終計算了%s篇文章'%len(texts_set)

word2vec = gensim.models.word2vec.Word2Vec(sentences(), size=256, window=10, min_count=64, sg=1, hs=1, iter=10, workers=25)
word2vec.save('word2vec_wx')

這裏引入hashlib.md5是爲了對文章進行去重(本來1000萬篇文章,去重後得到800萬),而這個步驟不是必要的。

案例二:字向量與詞向量的訓練

來源github:https://github.com/nlpjoe/daguan-classify-2018/blob/master/src/preprocess/EDA.ipynb

# 訓練詞向量
def train_w2v_model(type='article', min_freq=5, size=100):
    sentences = []

    if type == 'char':
        corpus = pd.concat((train_df['article'], test_df['article']))
    elif type == 'word':
        corpus = pd.concat((train_df['word_seg'], test_df['word_seg']))
    for e in tqdm(corpus):
        sentences.append([i for i in e.strip().split() if i])
    print('訓練集語料:', len(corpus))
    print('總長度: ', len(sentences))
    model = Word2Vec(sentences, size=size, window=5, min_count=min_freq)
    model.itos = {}
    model.stoi = {}
    model.embedding = {}
    
    print('保存模型...')
    for k in tqdm(model.wv.vocab.keys()):
        model.itos[model.wv.vocab[k].index] = k
        model.stoi[k] = model.wv.vocab[k].index
        model.embedding[model.wv.vocab[k].index] = model.wv[k]

    model.save('../../data/word2vec-models/word2vec.{}.{}d.mfreq{}.model'.format(type, size, min_freq))
    return model
model = train_w2v_model(type='char', size=100)
model = train_w2v_model(type='word', size=100)
# model.wv.save_word2vec_format('../../data/laozhu-word-300d', binary=False)
# train_df[:3]
print('OK')

案例三:Python+gensim-文本相似度分析

來源於:Python+gensim-文本相似度分析

1、gensim使用流程

2、代碼實現

from gensim import corpora, models, similarities
import jieba
# 文本集和搜索詞
texts = ['吃雞這裏所謂的吃雞並不是真的吃雞,也不是我們常用的諧音詞刺激的意思',
         '而是出自策略射擊遊戲《絕地求生:大逃殺》裏的臺詞',
         '我吃雞翅,你吃雞腿']
keyword = '玩過吃雞?今晚一起吃雞'
# 1、將【文本集】生成【分詞列表】
texts = [jieba.lcut(text) for text in texts]
# 2、基於文本集建立【詞典】,並提取詞典特徵數
dictionary = corpora.Dictionary(texts)
feature_cnt = len(dictionary.token2id)
# 3、基於詞典,將【分詞列表集】轉換成【稀疏向量集】,稱作【語料庫】
corpus = [dictionary.doc2bow(text) for text in texts]
# 4、使用【TF-IDF模型】處理語料庫
tfidf = models.TfidfModel(corpus)
# 5、同理,用【詞典】把【搜索詞】也轉換爲【稀疏向量】
kw_vector = dictionary.doc2bow(jieba.lcut(keyword))
# 6、對【稀疏向量集】建立【索引】
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=feature_cnt)
# 7、相似度計算
sim = index[tfidf[kw_vector]]
for i in range(len(sim)):
    print('keyword 與 text%d 相似度爲:%.2f' % (i + 1, sim[i]))

打印結果:

keyword 與 text1 相似度爲:0.62
keyword 與 text2 相似度爲:0.00
keyword 與 text3 相似度爲:0.12

3、過程拆解

3.1、生成分詞列表

對文本集中的文本進行中文分詞,返回分詞列表,格式如下:

[‘word1’, ‘word2’, ‘word3’, …]

import jieba
text = '七月七日長生殿,夜半無人私語時。'
words = jieba.lcut(text)

print(words)

[‘七月’, ‘七日’, ‘長生殿’, ‘,’, ‘夜半’, ‘無人’, ‘私語’, ‘時’, ‘。’]

3.2、基於文本集建立詞典,獲取特徵數

  • corpora.Dictionary:建立詞典
  • len(dictionary.token2id):詞典中詞的個數
from gensim import corpora
import jieba
# 文本集
text1 = '堅果果實'
text2 = '堅果實在好吃'
texts = [text1, text2]
# 將文本集生成分詞列表
texts = [jieba.lcut(text) for text in texts]
print('文本集:', texts)
# 基於文本集建立詞典
dictionary = corpora.Dictionary(texts)
print('詞典:', dictionary)
# 提取詞典特徵數
feature_cnt = len(dictionary.token2id)
print('詞典特徵數:%d' % feature_cnt)

打印結果:

文本集: [[‘堅果’, ‘果實’], [‘堅果’, ‘實在’, ‘好吃’]]
詞典: Dictionary(4 unique tokens: [‘堅果’, ‘果實’, ‘好吃’, ‘實在’])
詞典特徵數:4

3.3、基於詞典建立語料庫

語料庫存放稀疏向量列表

from gensim import corpora
import jieba
text1 = '來東京吃東京菜'
text2 = '東京啊東京啊東京'
texts = [text1, text2]
texts = [jieba.lcut(text) for text in texts]
dictionary = corpora.Dictionary(texts)
print('詞典(字典):', dictionary.token2id)
# 基於詞典建立新的【語料庫】
corpus = [dictionary.doc2bow(text) for text in texts]
print('語料庫:', corpus)

打印結果

詞典(字典): {‘東京’: 0, ‘吃’: 1, ‘來’: 2, ‘菜’: 3, ‘啊’: 4}
語料庫: [[(0, 2), (1, 1), (2, 1), (3, 1)], [(0, 3), (4, 2)]]

  • doc2bow函數生成稀疏向量

1、將所有單詞取【集合】,並對每個單詞分配一個ID號
以['東京', '啊', '東京', '啊', '東京']爲例
對單詞分配ID:東京→0;啊→4
變成:[0, 4, 0, 4, 0]
2、轉換成稀疏向量
0有3個,即表示爲(0, 3)
4有2個,即表示爲(4, 2)
最終結果:[(0, 3), (4, 2)]

3.4、使用TF-IDF模型處理語料庫,並建立索引

  • TF-IDF是一種統計方法,用以評估一字詞對於一個文件集或一個語料庫中的其中一份文件的重要程度
from gensim import corpora, models, similarities
import jieba
text1 = '南方醫院無痛人流'
text2 = '北方人流浪到南方'
texts = [text1, text2]
texts = [jieba.lcut(text) for text in texts]
dictionary = corpora.Dictionary(texts)
feature_cnt = len(dictionary.token2id.keys())
corpus = [dictionary.doc2bow(text) for text in texts]
# 用TF-IDF處理語料庫
tfidf = models.TfidfModel(corpus)
# 對語料庫建立【索引】
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=feature_cnt)

print(tfidf)

TfidfModel(num_docs=2, num_nnz=9)

3.5、用詞典把搜索詞轉成稀疏向量

from gensim import corpora
import jieba
text1 = '南方醫院無痛人流'
text2 = '北方人流落南方'
texts = [text1, text2]
texts = [jieba.lcut(text) for text in texts]
dictionary = corpora.Dictionary(texts)
# 用【詞典】把【搜索詞】也轉換爲【稀疏向量】
keyword = '無痛人流'
kw_vector = dictionary.doc2bow(jieba.lcut(keyword))

print(kw_vector)

[(0, 1), (3, 1)]

3.6、相似度計算

from gensim import corpora, models, similarities
import jieba
text1 = '無痛人流並非無痛'
text2 = '北方人流浪到南方'
texts = [text1, text2]
keyword = '無痛人流'
texts = [jieba.lcut(text) for text in texts]
dictionary = corpora.Dictionary(texts)
feature_cnt = len(dictionary.token2id)
corpus = [dictionary.doc2bow(text) for text in texts]
tfidf = models.TfidfModel(corpus)
new_vec = dictionary.doc2bow(jieba.lcut(keyword))
# 相似度計算
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=feature_cnt)
print('\nTF-IDF模型的稀疏向量集:')
for i in tfidf[corpus]:
    print(i)
print('\nTF-IDF模型的keyword稀疏向量:')
print(tfidf[new_vec])
print('\n相似度計算:')
sim = index[tfidf[new_vec]]
for i in range(len(sim)):
    print('第', i+1, '句話的相似度爲:', sim[i])

4、附錄

En Cn
corpus n. 文集;[計]語料庫(複數:corpora)
sparse adj. 稀疏的
vector n. 矢量
Sparse Matrix Similarity 稀疏矩陣相似性
word2vec word to vector
doc2bow document to bag of words(詞袋

案例四:Python+gensim【中文LDA】簡潔模型

來源於:Python+gensim【中文LDA】簡潔模型

0、原理

  • LDA文檔主題生成模型,也稱三層貝葉斯概率模型,包含詞、主題和文檔三層結構。
    利用文檔中單詞的共現關係來對單詞按主題聚類,得到“文檔-主題”和“主題-單詞”2個概率分佈。

  • gensim流程

1、代碼實現

from gensim import corpora, models
import jieba.posseg as jp, jieba
# 文本集
texts = [
    '美國教練坦言,沒輸給中國女排,是輸給了郎平',
    '美國無緣四強,聽聽主教練的評價',
    '中國女排晉級世錦賽四強,全面解析主教練郎平的執教藝術',
    '爲什麼越來越多的人買MPV,而放棄SUV?跑一趟長途就知道了',
    '跑了長途才知道,SUV和轎車之間的差距',
    '家用的轎車買什麼好']
# 分詞過濾條件
jieba.add_word('四強', 9, 'n')
flags = ('n', 'nr', 'ns', 'nt', 'eng', 'v', 'd')  # 詞性
stopwords = ('沒', '就', '知道', '是', '才', '聽聽', '坦言', '全面', '越來越', '評價', '放棄', '人')  # 停詞
# 分詞
words_ls = []
for text in texts:
    words = [word.word for word in jp.cut(text) if word.flag in flags and word.word not in stopwords]
    words_ls.append(words)
# 構造詞典
dictionary = corpora.Dictionary(words_ls)
# 基於詞典,使【詞】→【稀疏向量】,並將向量放入列表,形成【稀疏向量集】
corpus = [dictionary.doc2bow(words) for words in words_ls]
# lda模型,num_topics設置主題的個數
lda = models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=2)
# 打印所有主題,每個主題顯示4個詞
for topic in lda.print_topics(num_words=4):
    print(topic)
# 主題推斷
print(lda.inference(corpus))

結果

主題0(體育):‘0.081*“郎平” + 0.080*“中國女排” + 0.077*“輸給” + 0.074*“主教練”’
主題1(汽車):‘0.099*“長途” + 0.092*“SUV” + 0.084*“” + 0.074*“轎車”’

2、過程詳解

2.1、打印中間件

print(words_ls)
[[‘美國’, ‘輸給’, ‘中國女排’, ‘輸給’, ‘郎平’],
[‘美國’, ‘無緣’, ‘四強’, ‘主教練’],
[‘中國女排’, ‘晉級’, ‘世錦賽’, ‘四強’, ‘主教練’, ‘郎平’, ‘執教’, ‘藝術’],
[‘買’, ‘MPV’, ‘SUV’, ‘跑’, ‘長途’],
[‘跑’, ‘長途’, ‘SUV’, ‘轎車’, ‘差距’],
[‘家用’, ‘轎車’, ‘買’]]

print(dictionary.token2id)
{‘中國女排’: 0, ‘美國’: 1, ‘輸給’: 2, ‘郎平’: 3, ‘主教練’: 4, ‘四強’: 5, ‘無緣’: 6, ‘世錦賽’: 7, ‘執教’: 8, ‘晉級’: 9, ‘藝術’: 10, ‘MPV’: 11, ‘SUV’: 12, ‘買’: 13, ‘跑’: 14, ‘長途’: 15, ‘差距’: 16, ‘轎車’: 17, ‘家用’: 18}

print(corpus)
[[(0, 1), (1, 1), (2, 2), (3, 1)],
[(1, 1), (4, 1), (5, 1), (6, 1)],
[(0, 1), (3, 1), (4, 1), (5, 1), (7, 1), (8, 1), (9, 1), (10, 1)],
[(11, 1), (12, 1), (13, 1), (14, 1), (15, 1)],
[(12, 1), (14, 1), (15, 1), (16, 1), (17, 1)],
[(13, 1), (17, 1), (18, 1)]]

print(lda)
LdaModel(num_terms=19, num_topics=2, decay=0.5, chunksize=2000)

2.2、doc2bow函數

[‘美國’, ‘輸給’, ‘中國女排’, ‘輸給’, ‘郎平’]
↓↓↓【詞→ID】
↓↓↓(美國→0、輸給→2、中國女排→1、郎平→3)
[0, 2, 1, 2, 3]
↓↓↓【生成稀疏向量】
↓↓↓(2有兩個,其它只有一個)
[(0, 1), (1, 1), (2, 2), (3, 1)]

2.3、主題推斷

for e, values in enumerate(lda.inference(corpus)[0]):
    print(texts[e])
    for ee, value in enumerate(values):
        print('\t主題%d推斷值%.2f' % (ee, value))

美國教練坦言,沒輸給中國女排,是輸給了郎平
    主題0推斷值5.29(體育)
    主題1推斷值0.71
  美國無緣四強,聽聽主教練的評價
    主題0推斷值4.44(體育)
    主題1推斷值0.56
  中國女排晉級世錦賽四強,全面解析主教練郎平的執教藝術
    主題0推斷值8.44(體育)
    主題1推斷值0.56
  爲什麼越來越多的人買MPV,而放棄SUV?跑一趟長途就知道了
    主題0推斷值0.54
    主題1推斷值5.46(汽車)
  跑了長途才知道,SUV和轎車之間的差距
    主題0推斷值0.56
    主題1推斷值5.44(汽車)
  家用的轎車買什麼好
    主題0推斷值0.68
    主題1推斷值3.32(汽車)

text5 = '中國女排將在郎平的率領下向世界女排三大賽的三連冠發起衝擊'
bow = dictionary.doc2bow([word.word for word in jp.cut(text5) if word.flag in flags and word.word not in stopwords])
ndarray = lda.inference([bow])[0]
print(text5)
for e, value in enumerate(ndarray[0]):
    print('\t主題%d推斷值%.2f' % (e, value))

 中國女排將在郎平的率領下向世界女排三大賽的三連冠發起衝擊
    主題0推斷值2.40(體育)
    主題1推斷值0.60

2.4、詞和主題的關係

  • 單個詞與主題的關係
word_id = dictionary.doc2idx(['長途'])[0]
for i in lda.get_term_topics(word_id):
    print('【長途】與【主題%d】的關係值:%.2f%%' % (i[0], i[1]*100))

【長途】與【主題0】的關係值:1.61%
【長途】與【主題1】的關係值:7.41%(汽車)

  • 全部詞與主題的關係(minimum_probability設置概率閾值)
for word, word_id in dictionary.token2id.items():
    print(word, lda.get_term_topics(word_id, minimum_probability=1e-8))

3、附錄

En Cn
LDA Latent Dirichlet Allocation
latent 潛在的
allocation n. 分配;定位(allocation)
inference n. 推理
term 術語;學期;
doc2bow document to bag of words(詞袋)
doc2idx document to index

 

LINK:

python︱gensim訓練word2vec及相關函數與功能理解

15分鐘入門NLP神器—Gensim

Python+gensim-文本相似度分析

Python+gensim【中文LDA】簡潔模型

基於python的gensim word2vec訓練詞向量

Gensim Word2vec 使用教程

官方教程:http://radimrehurek.com/gensim/models/word2vec.html

 

 

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