gensim計算文檔相似度
gensim是一個基於Python語言的開源工具集,用於處理向量空間模型(vector space modeling)和話題模型(topic modeling)的相關問題。本文分享如何使用gensim工具來計算兩篇中文文檔的相似度。
首先我們要生成一些中文文檔。下面的代碼生成一個名為documents
的文檔列表,由於是演示,這裡的每個文檔中只有幾個詞語。關於如何對原始的字元串做分詞操作,可以參考jieba
from gensim import corporafrom pprint import pprintdocuments = ["你好 好的 不錯 笨蛋", "笨蛋 傻瓜 傻子 哈哈", "好的 不錯 你好 哈哈", "有趣 可以 好的 不錯 還行", "傻瓜 傻子 二貨 還行", "可以 好的 不錯 哈哈", "有趣 有趣 哈哈 哈哈"]texts = [[word for word in document.split()] for document in documents]pprint(texts)[[你好, 好的, 不錯, 笨蛋], [笨蛋, 傻瓜, 傻子, 哈哈], [好的, 不錯, 你好, 哈哈], [有趣, 可以, 好的, 不錯, 還行], [傻瓜, 傻子, 二貨, 還行], [可以, 好的, 不錯, 哈哈], [有趣, 有趣, 哈哈, 哈哈]]
然後我們要對原始的文檔做一些預處理。這裡我們統計了每個詞語出現的次數,移除了只出現一次的詞語,因為這些詞語通常不會對計算文檔相似度產生任何貢獻。其他的預處理操作還包括移除數字、字母以及標點符號等,這裡我們沒有展示,如果實際中遇到可以進行相應的處理。
from collections import defaultdictfrequency = defaultdict(int)for text in texts: for token in text: frequency[token] += 1texts = [[token for token in text if frequency[token] > 1] for text in texts]pprint(texts)[[你好, 好的, 不錯, 笨蛋], [笨蛋, 傻瓜, 傻子, 哈哈], [好的, 不錯, 你好, 哈哈], [有趣, 可以, 好的, 不錯, 還行], [傻瓜, 傻子, 還行], [可以, 好的, 不錯, 哈哈], [有趣, 有趣, 哈哈, 哈哈]]
接著我們生成了包含所有詞語的詞典,為後面的計算做準備。在實際情況中,詞典通常會很大,為了避免重複計算,可以將詞典保存下來。
dictionary = corpora.Dictionary(texts)dictionary.save(sample.dict)print(dictionary)Dictionary(10 unique tokens: [不錯, 你好, 好的, 笨蛋, 傻子]...)
有了前一步生成的詞典,我們就可以將每個詞語轉化成一個索引,表示該詞語在所有文檔中出現的次序,然後每個文檔就可以轉化成一個索引的列表,比如這裡的第一個文檔表示為[(0, 1), (1, 1), (2, 1), (3, 1)]
,它的含義是在第一篇文檔中,第0個詞語(也就是「你好」)出現了一次,第一個詞語(也就是「好的」)出現了一次,依次類推。
corpus = [dictionary.doc2bow(text) for text in texts]corpora.MmCorpus.serialize(sample.mm, corpus)pprint(corpus)[[(0, 1), (1, 1), (2, 1), (3, 1)], [(3, 1), (4, 1), (5, 1), (6, 1)], [(0, 1), (1, 1), (2, 1), (6, 1)], [(0, 1), (2, 1), (7, 1), (8, 1), (9, 1)], [(4, 1), (5, 1), (9, 1)], [(0, 1), (2, 1), (6, 1), (7, 1)], [(6, 2), (8, 2)]]
然後我們可以調用gensim中的tf-idf
模塊來進一步對每個單詞計算權重。關於tf-idf
的計算方法,可以參考維基百科
from gensim import models, similaritiestf_idf = models.TfidfModel(corpus)vec = [(0, 1), (5, 1), (7, 1)]print(tf_idf[vec])[(0, 0.3011997233053068), (5, 0.6742695034927825), (7, 0.6742695034927825)]
現在,我們可以開始計算兩個文檔的相似度了。這裡我們採用了餘弦相似度作為衡量指標,當然還有其他的方式,可以參考文本相似度計算方法研究綜述
index = similarities.SparseMatrixSimilarity(tf_idf[corpus], num_features=10)sims = index[tf_idf[vec]]print(sims)[0.08686648 0.37695488 0.10641449 0.43870124 0.38928968 0.63969857 0. ]
我們還可以將整個相似度矩陣列印出來,就可以看到前面我們所準備的七篇文檔兩兩之間的相似度。
print(index[tf_idf[corpus]])[[1. 0.3609379 0.71441036 0.13975498 0. 0.20378576 0. ] [0.3609379 1.0000001 0.08823138 0. 0.64554304 0.08823138 0.10185669] [0.71441036 0.08823138 1.0000001 0.17120475 0. 0.37446705 0.1440983 ] [0.13975498 0. 0.17120475 1. 0.31315398 0.60019135 0.4952337 ] [0. 0.64554304 0. 0.31315398 0.99999994 0. 0. ] [0.20378576 0.08823138 0.37446705 0.60019135 0. 1. 0.1440983 ] [0. 0.10185669 0.1440983 0.4952337 0. 0.1440983 0.99999994]]
本文中的代碼使用Jupyter Notebook編寫,需要的朋友可以直接到github上查看。
推薦閱讀:
※[本人原創]思維(意識)整體論圖Graph假設(記憶-抽象實體化,聯結記憶(工作記憶)-邊關係化)
※Distant Supervision for Relation Extraction with Sentence-Level Attention and Entity Descriptions
※tf.nn.nce_loss 來自一篇古老的文章
※SQLnet 代碼閱讀筆記
※《Dialogue Act Sequence Labeling using Hierarchical encoder with CRF》閱讀筆記
TAG:JupyterNotebookIPythonNotebook | 自然語言處理 |