計算文檔與文檔的相似度

最近幫很多本科畢業生做文本數據分析,經常遇到的一個需求是計算文檔相似度。

思路:

  1. 抽取語料(所有文檔)中的詞語,構建詞典(詞語與數字對應起來)。

  2. 根據構建的詞典對每個文檔進行重新編碼(將文檔轉化爲向量)。

  3. 使用餘弦計算相似度

下面的corpus是我在知乎live隨便找到的幾個評論,拿來當做測試的例子。好像數據不怎麼好玩,大家跟着一起湊合湊合吧。


corpus = ['老師講的很好很全面乾貨很多',
        '講述的很好乾貨滿滿',
        '滿滿的乾貨很實用',
        '感謝老師無私的分享啦',
        '真水呵呵噠']

構建詞典-學習語料特徵
其實在機器學習裏,學習語料的所有詞語並將其轉化爲數字,這一步驟叫做特徵化。強烈推薦對數據科學感興趣的童鞋學學scikit-learn庫,人工智能咱們小白可能還玩不轉,但是調用封裝好的機器學習算法,淺顯的玩玩機器學習還是沒啥難度的。

在scikit-learn中,涉及到文本數據特徵化的類有sklearn.feature_extraction.text.CountVectorizer 和sklearn.feature_extraction.text.TfidfVectorizer 。我們先以常見的詞頻統計作爲特徵抽取的方式開始探索,由於scikit默認使用英文空格作爲分詞符號,所以處理中文數據前我們要分詞並以空格間隔開來。


from sklearn.feature_extraction.text import CountVectorizer
import jieba
corpus = [' '.join(jieba.lcut(doc))
          for doc in corpus]corpus
['老師 講 的 很 好 很 全面 乾貨 很多',
 '講述 的 很 好 乾貨 滿滿',
 '滿滿的 乾貨 很 實用',
 '感謝 老師 無私 的 分享 啦',
 '真水 呵呵 噠']
wordcounter = CountVectorizer()

#學習特徵(構建詞典)fit  並轉化爲特徵矩陣。
matrix=wordcounter.fit_transform(corpus)
print(matrix.toarray())

#查看下特徵與詞語對應關係
print(wordcounter.get_feature_names())
[[1 0 0 0 1 1 0 0 0 0 0 1 0]
 [0 0 0 0 1 0 0 0 1 0 0 0 1]
 [0 0 0 1 1 0 0 0 0 1 0 0 0]
 [0 1 0 0 0 0 1 1 0 0 0 1 0]
 [0 0 1 0 0 0 0 0 0 0 1 0 0]]
['全面', '分享', '呵呵', '實用', '乾貨', 
'很多', '感謝', '無私', '滿滿', '滿滿的', 
'真水', '老師', '講述']

計算相似度
這裏使用scikit提供的cosine-similarity函數。


from sklearn.metrics.pairwise import cosine_similarity

cosine_similarity(matrix)
array([[1.        , 0.28867513, 0.28867513, 0.25      , 0.        ],
       [0.28867513, 1.        , 0.33333333, 0.        , 0.        ],
       [0.28867513, 0.33333333, 1.        , 0.        , 0.        ],
       [0.25      , 0.        , 0.        , 1.        , 0.        ],
       [0.        , 0.        , 0.        , 0.        , 1.        ]])
我們看到這個矩陣是沿着對角線對稱的,所以我們只需要看第一行。

第一個評論與第一個評論之間的相似度爲1
第一個評論與第二個評論的相似度爲0.28867513
第一個評論與第三個評論的相似度爲0.28867513
第一個評論與第四個評論的相似度爲0.25
第一個評論與第四個評論的相似度爲0

高中數學知識cos相似性計算公式
本以爲自己對這裏很熟悉,結果自己寫cos計算公式時居然出錯了。粘貼到這裏,幫助大家回憶高中知識。(a和b是向量)

計算文檔與文檔的相似度

#cos相似性計算


def cosVector(x,y):
    result1=0.0
    result2=0.0
    result3=0.0
    for i in range(len(x)):
        result1 +=x[i]*y[i]   #sum(a*b)
        result2 +=x[i]**2     #sum(a*a)
        result3 +=y[i]**2     #sum(b*b)

    return str(result1/((result2*result3)**0.5))
vect1 = [1,0,1]
vect2 = [0,1,0]
vect3 = [1,1,1]

print("vect1與vect2相似度爲:", cosVector(vect1, vect2))
print("vect1與vect3相似度爲:", cosVector(vect1, vect3))
print("vect2與vect3相似度爲:", cosVector(vect2, vect3))
vect1與vect2相似度爲: 0.0
vect1與vect3相似度爲: 0.8164965809277261
vect2與vect3相似度爲: 0.5773502691896258
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章