15分鐘入門NLP神器—Gensim
作者:李雪冬
編輯:李雪冬
前 言
作為自然語言處理愛好者,大家都應該聽說過或使用過大名鼎鼎的Gensim吧,這是一款具備多種功能的神器。
Gensim是一款開源的第三方Python工具包,用於從原始的非結構化的文字中,無監督地學習到文字隱層的主題向量表達。
它支援包括TF-IDF,LSA,LDA,和word2vec在內的多種主題模型演算法,
支援流式訓練,並提供了諸如相似度計算,資訊檢索等一些常用任務的API介面
基本概念
語料(Corpus):一組原始文字的集合,用於無監督地訓練文字主題的隱層結構。語料中不需要人工標註的附加資訊。在Gensim中,Corpus通常是一個可迭代的物件(比如列表)。每一次迭代返回一個可用於表達文字物件的稀疏向量。
向量(Vector):由一組文字特徵構成的列表。是一段文字在Gensim中的內部表達。
稀疏向量(SparseVector):通常,我們可以略去向量中多餘的0元素。此時,向量中的每一個元素是一個(key, value)的元組
模型(Model):是一個抽象的術語。定義了兩個向量空間的變換(即從文字的一種向量表達變換為另一種向量表達)。
步驟一:訓練語料的預處理
由於Gensim使用python語言開發的,為了減少安裝中的繁瑣,直接使用anaconda工具進行集中安裝,
輸入:pip install gensim,這裡不再贅述。
訓練語料的預處理指的是將文件中原始的字元文字轉換成Gensim模型所能理解的稀疏向量的過程。
通常,我們要處理的原生語料是一堆文件的集合,每一篇文件又是一些原生字元的集合。在交給Gensim的模型訓練之前,我們需要將這些原生字元解析成Gensim能處理的稀疏向量的格式。由於語言和應用的多樣性,我們需要先對原始的文字進行分詞、去除停用詞等操作,得到每一篇文件的特徵列表。例如,在詞袋模型中,文件的特徵就是其包含的word:
texts = [['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']]
其中,corpus的每一個元素對應一篇文件。
接下來,我們可以呼叫Gensim提供的API建立語料特徵(此處即是word)的索引字典,並將文字特徵的原始表達轉化成詞袋模型對應的稀疏向量的表達。依然以詞袋模型為例:
from gensim import corpora
dictionary = corpora.Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts]
print corpus[0] # [(0, 1), (1, 1), (2, 1)]
到這裡,訓練語料的預處理工作就完成了。我們得到了語料中每一篇文件對應的稀疏向量(這裡是bow向量);向量的每一個元素代表了一個word在這篇文件中出現的次數。值得注意的是,雖然詞袋模型是很多主題模型的基本假設,這裡介紹的doc2bow函式並不是將文字轉化成稀疏向量的唯一途徑。在下一小節裡我們將介紹更多的向量變換函式。
最後,出於記憶體優化的考慮,Gensim支援文件的流式處理。我們需要做的,只是將上面的列表封裝成一個Python迭代器;每一次迭代都返回一個稀疏向量即可。
class MyCorpus(object):
def __iter__(self):
for line in open('mycorpus.txt'):
# assume there's one document per line, tokens separated by whitespace
yield dictionary.doc2bow(line.lower().split())
3步驟二:主題向量的變換
對文字向量的變換是Gensim的核心。通過挖掘語料中隱藏的語義結構特徵,我們最終可以變換出一個簡潔高效的文字向量。
在Gensim中,每一個向量變換的操作都對應著一個主題模型,例如上一小節提到的對應著詞袋模型的doc2bow變換。每一個模型又都是一個標準的Python物件。下面以TF-IDF模型為例,介紹Gensim模型的一般使用方法。
首先是模型物件的初始化。通常,Gensim模型都接受一段訓練語料(注意在Gensim中,語料對應著一個稀疏向量的迭代器)作為初始化的引數。顯然,越複雜的模型需要配置的引數越多。
from gensim import models
tfidf = models.TfidfModel(corpus)
其中,corpus是一個返回bow向量的迭代器。這兩行程式碼將完成對corpus中出現的每一個特徵的IDF值的統計工作。
接下來,我們可以呼叫這個模型將任意一段語料(依然是bow向量的迭代器)轉化成TFIDF向量(的迭代器)。需要注意的是,這裡的bow向量必須與訓練語料的bow向量共享同一個特徵字典(即共享同一個向量空間)。
doc_bow = [(0, 1), (1, 1)]
print tfidf[doc_bow] # [(0, 0.70710678), (1, 0.70710678)]
注意,同樣是出於記憶體的考慮,model[corpus]方法返回的是一個迭代器。如果要多次訪問model[corpus]的返回結果,可以先將結果向量序列化到磁碟上。
我們也可以將訓練好的模型持久化到磁碟上,以便下一次使用:
tfidf.save("./model.tfidf")
tfidf = models.TfidfModel.load("./model.tfidf")
Gensim內建了多種主題模型的向量變換,包括LDA,LSI,RP,HDP等。這些模型通常以bow向量或tfidf向量的語料為輸入,生成相應的主題向量。所有的模型都支援流式計算。關於Gensim模型更多的介紹,可以參考這裡:API Reference(https://radimrehurek.com/gensim/apiref.html)
4步驟三:文件相似度的計算
在得到每一篇文件對應的主題向量後,我們就可以計算文件之間的相似度,進而完成如文字聚類、資訊檢索之類的任務。在Gensim中,也提供了這一類任務的API介面。
以資訊檢索為例。對於一篇待檢索的query,我們的目標是從文字集合中檢索出主題相似度最高的文件。
首先,我們需要將待檢索的query和文字放在同一個向量空間裡進行表達(以LSI向量空間為例):
# 構造LSI模型並將待檢索的query和文字轉化為LSI主題向量
# 轉換之前的corpus和query均是BOW向量
lsi_model = models.LsiModel(corpus, id2word=dictionary, num_topics=2)
documents = lsi_model[corpus]
query_vec = lsi_model[query]
接下來,我們用待檢索的文件向量初始化一個相似度計算的物件:
index = similarities.MatrixSimilarity(documents)
我們也可以通過save()和load()方法持久化這個相似度矩陣:
index.save('/tmp/test.index')
index = similarities.MatrixSimilarity.load('/tmp/test.index')
注意,如果待檢索的目標文件過多,使用similarities.MatrixSimilarity類往往會帶來記憶體不夠用的問題。此時,可以改用similarities.Similarity類。二者的介面基本保持一致。
最後,我們藉助index物件計算任意一段query和所有文件的(餘弦)相似度:
sims = index[query_vec]
#返回一個元組型別的迭代器:(idx, sim)
5
補充
TF-IDF
TF-IDF(注意:這裡不是減號)是一種統計方法,用以評估一字詞對於一個檔案集或一個語料庫中的其中一份檔案的重要程度。
字詞的重要性隨著它在檔案中出現的次數成正比增加,但同時會隨著它在語料庫中出現的頻率成反比下降。TF-IDF加權的各種形式常被搜尋引擎應用,作為檔案與使用者查詢之間相關程度的度量或評級。
1. 一個詞預測主題能力越強,權重就越大,反之,權重就越小。我們在網頁中看到“原子能”這個詞,或多或少地能瞭解網頁的主題。我們看到“應用”一次,對主題基本上還是一無所知。因此,“原子能“的權重就應該比應用大。
2. 應刪除詞的權重應該是零。
LDA文件主題生成模型
LDA是一種文件主題生成模型,包含詞、主題和文件三層結構。
所謂生成模型,就是說,我們認為一篇文章的每個詞都是通過“以一定概率選擇了某個主題,並從這個主題中以一定概率選擇某個詞語”這樣一個過程得到。文件到主題服從多項式分佈,主題到詞服從多項式分佈。
LDA是一種非監督機器學習技術,可以用來識別大規模文件集或語料庫中潛藏的主題資訊。它採用了詞袋的方法,這種方法將每一篇文件視為一個詞頻向量,從而將文字資訊轉化為了易於建模的數字資訊。
但是詞袋方法沒有考慮詞與詞之間的順序,這簡化了問題的複雜性,同時也為模型的改進提供了契機。每一篇文件代表了一些主題所構成的一個概率分佈,而每一個主題又代表了很多單詞所構成的一個概率分佈。
小結gensim作為一款強大且開源的工具包非常值得我們花時間學習,如果對搜尋引擎和自然語言處理感興趣,更需要深入學習。在學習過程中建議大家多關注一些牛人部落格,並進行歸納。這裡只是拋磚引玉,想了解更多機器學習相關知識,請關注我們公眾號:機器學習演算法全棧工程師
參考資料公子天:https://www.cnblogs.com/iloveai/p/gensim_tutorial.html
官網:https://radimrehurek.com/gensim/
end
機器學習演算法全棧工程師
一個用心的公眾號
進群,學習,得幫助
你的關注,我們的熱度,
我們一定給你學習最大的幫助