【NLP學習筆記】(二)gensim使用之Topics and Transformations

本文主要翻譯自:https://radimrehurek.com/gensim/tut2.html

這個教程會向大家展示如何將代表文檔的向量轉換成另一種向量,做這件事的目的主要有兩個:

  1. 發現語料中的隱藏結構,比如詞與詞之間的聯繫,然後用一種全新的方式、一種更能表現語義的方式(semantic way)來描述文檔。
  2. 使文檔的表示更加緊湊,這樣可以提高效率和功效,因爲新的表達方式消耗更少的資源,並且去除了噪音。

一、回顧

在之前的gensim基礎使用中,我們介紹瞭如何將語料提取特徵後轉換爲向量(基於詞袋模型),上一章中的結果:

# 清洗後的語料庫,只有九句話,代表九個文檔
[['human', 'interface', 'computer'],
 ['survey', 'user', 'computer', 'system', 'response', 'time'],
 ['eps', 'user', 'interface', 'system'],
 ['system', 'human', 'system', 'eps'],
 ['user', 'response', 'time'],
 ['trees'],
 ['graph', 'trees'],
 ['graph', 'minors', 'trees'],
 ['graph', 'minors', 'survey']]
# 根據上面語料訓練的詞典,每個詞都有一個id
{'computer': 0,
 'eps': 8,
 'graph': 10,
 'human': 1,
 'interface': 2,
 'minors': 11,
 'response': 3,
 'survey': 4,
 'system': 5,
 'time': 6,
 'trees': 9,
 'user': 7}
# 根據詞典基於詞袋模型,訓練上面語料的結果,(0,1.0)的意思是id爲0的單詞,即“computer”在第一篇文章中出現了1次。其它類似。
[[(0, 1.0), (1, 1.0), (2, 1.0)],
 [(0, 1.0), (3, 1.0), (4, 1.0), (5, 1.0), (6, 1.0), (7, 1.0)],
 [(2, 1.0), (5, 1.0), (7, 1.0), (8, 1.0)],
 [(1, 1.0), (5, 2.0), (8, 1.0)],
 [(3, 1.0), (6, 1.0), (7, 1.0)],
 [(9, 1.0)],
 [(9, 1.0), (10, 1.0)],
 [(9, 1.0), (10, 1.0), (11, 1.0)],
 [(4, 1.0), (10, 1.0), (11, 1.0)]]

二、加載上一章中結果(保存的字典和語料向量)

from gensim import corpora, models, similarities
import os
if(os.path.exists('./gensim_out/deerwester.dict')):
    dictionary = corpora.Dictionary.load('./gensim_out/deerwester.dict')
    corpus = corpora.MmCorpus('./gensim_out/deerwester.mm')
    print("使用之前已經存儲的字典和語料向量")
else:
    print("請先通過上一章生成deerwester.dict和deerwester.mm")

#pprint(dictionary.tokenz`2id)
#pprint(corpus)

三、初始化一個轉換模型(Creating a transformation)

轉換模型是標準的python對象,通常需要傳入一個語料庫進行初始化。
我們使用教程1中的舊語料庫來初始化(訓練)轉換模型。也就是上面加載的corpus, 不同的轉換模型一般需要不同的初始化參數; 在TfIdf的情況下,“訓練”僅包括通過提供的語料庫一次並計算其所有詞頻和逆文檔頻率。 訓練其他模型,例如潛在語義分析或潛在狄利克雷分析,涉及更多,因此也會消耗更多時間。

tfidf = models.TfidfModel(corpus) #初始化一個模型

doc_bow = [(0, 1), (1, 1)]

print(tfidf[doc_bow])#輸出:[(0, 0.70710678), (1, 0.70710678)]```

上面已經創建了tfidf模型,我們應該將其作爲一個只讀對象來看待,用它可以將舊的向量表示(上一節中的詞袋模型)轉換爲新的向量表示(比如tf-idf權重)
假設新文本爲:“***Human computer interaction***”
doc_bow是新文本經過上一章的清洗、分詞、基於詞袋模型轉換後的結果,(0, 1)表示id爲0,即“computer”。1表示“computer”在新文本中出現了1次;(1, 1)表示id爲1,即“human”也出現了1次。
tfidf模型將新文本從詞袋向量模型([(0, 1), (1, 1)])轉換爲了詞頻-逆文檔頻率權重向量([(0, 0.70710678), (1, 0.70710678)]),即“computer”的權重爲0 0.70710678,“human”的權重爲0.70710678

### 四、序列化轉換後的結果
調用model_name[corpus]僅在舊的語料庫文檔流周圍創建一個包裝器 ,實際轉換在文檔迭代期間即時完成。 我們無法在調用corpus_transformed = model [corpus]時轉換整個語料庫,因爲這意味着將結果存儲在內存中,這與gensim的內存獨立的目標相矛盾。 如果您將多次迭代轉換的corpus_transformed,並且轉換成本很高,請先將生成的語料庫序列化到磁盤然後再使用它。

用tfidf轉換語料庫corpus

corpus_tfidf = tfidf[corpus]

# initialize an LSI transformation(初始化LSI模型)lsi = models.LsiModel(corpus_tfidf, id2word=dictionary, num_topics=2)

create a double wrapper over the original corpus: bow->tfidf->fold-in-lsicorpus_lsi = lsi[corpus_tfidf]

lsi.print_topics(2)

輸出:topic #0(1.594): -0.703"trees" + -0.538"graph" + -0.402"minors" + -0.187"survey" + -0.061"system" + -0.060"response" + -0.060"time" + -0.058"user" + -0.049"computer" + -0.035"interface"

topic #1(1.476): -0.460"system" + -0.373"user" + -0.332"eps" + -0.328"interface" + -0.320"response" + -0.320"time" + -0.293"computer" + -0.280"human" + -0.171"survey" + 0.161"trees"


根據上面結果可以看出“trees”, “graph” and “minors都是相關聯的詞彙,並且對第一個主題的貢獻度最高,第二個主題,更多的是關注其他的詞彙

for doc in corpus_lsi:

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"


#### 保存模型與加載模型

保存

lsi.save('./gensim_out/model.lsi') # same for tfidf, lda, ...

加載

lsi = models.LsiModel.load('/tmp/model.lsi')


### gensim中可用的轉換模型

* Term Frequency * Inverse Document Frequency, Tf-Idf

model = models.TfidfModel(corpus, normalize=True)

* Latent Semantic Indexing, LSI (or sometimes LSA)

model = models.LsiModel(tfidf_corpus, id2word=dictionary, num_topics=300)
model.add_documents(another_tfidf_corpus) # now LSI has been trained on tfidf_corpus + another_tfidf_corpus
lsi_vec = model[tfidf_vec] # convert some new document into the LSI space, without affecting the model
...
model.add_documents(more_documents) # tfidf_corpus + another_tfidf_corpus + more_documents
lsi_vec = model[tfidf_vec]
...

* Random Projections, RP 

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

* Latent Dirichlet Allocation, LDA 

model = models.LdaModel(corpus, id2word=dictionary, num_topics=100)

* Hierarchical Dirichlet Process, HDP

model = models.HdpModel(corpus, id2word=dictionary)

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