python實(shí)現(xiàn)余弦相似度文本比較的示例
向量空間模型VSM:
VSM的介紹:
一個(gè)文檔可以由文檔中的一系列關(guān)鍵詞組成,而VSM則是用這些關(guān)鍵詞的向量組成一篇文檔,其中的每個(gè)分量代表詞項(xiàng)在文檔中的相對(duì)重要性。
VSM的例子:
比如說(shuō),一個(gè)文檔有分詞和去停用詞之后,有N個(gè)關(guān)鍵詞(或許去重后就有M個(gè)關(guān)鍵詞),文檔關(guān)鍵詞相應(yīng)的表示為(d1,d2,d3,...,dn),而每個(gè)關(guān)鍵詞都有一個(gè)對(duì)應(yīng)的權(quán)重(w1,w1,...,wn)。對(duì)于一篇文檔來(lái)說(shuō),或許所含的關(guān)鍵詞項(xiàng)比較少,文檔向量化后的向量維度可能不是很大。而對(duì)于多個(gè)文檔(2篇文檔或兩篇文檔以上),則需要合并所有文檔的關(guān)鍵詞(關(guān)鍵詞不能重復(fù)),形成一個(gè)不重復(fù)的關(guān)鍵詞集合,這個(gè)關(guān)鍵詞集合的個(gè)數(shù)就是每個(gè)文檔向量化后的向量的維度。打個(gè)比方說(shuō),總共有2篇文檔A和B,其中A有5個(gè)不重復(fù)的關(guān)鍵詞(a1,a2,a3,a4,a5),B有6個(gè)關(guān)鍵詞(b1,b2,b3,b4,b5,b6),而且假設(shè)b1和a3重復(fù),則可以形成一個(gè)簡(jiǎn)單的關(guān)鍵詞集(a1,a2,a3,a4,a5,,b2,b3,b4,b5,b6),則A文檔的向量可以表示為(ta1,ta2,ta3,ta4,ta5,0,0,0,0,0),B文檔可以表示為(0,0,tb1,0,0,tb2,tb3,tb4,tb5,tb6),其中的tb表示的對(duì)應(yīng)的詞匯的權(quán)重。
最后,關(guān)鍵詞的權(quán)重一般都是有TF-IDF來(lái)表示,這樣的表示更加科學(xué),更能反映出關(guān)鍵詞在文檔中的重要性,而如果僅僅是為數(shù)不大的文檔進(jìn)行比較并且關(guān)鍵詞集也不是特別大,則可以采用詞項(xiàng)的詞頻來(lái)表示其權(quán)重(這種表示方法其實(shí)不怎么科學(xué))。
TF-IDF權(quán)重計(jì)算:
TF的由來(lái):
以前在文檔搜索的時(shí)候,我們只考慮詞項(xiàng)在不在文檔中,在就是1,不在就是0。其實(shí)這并不科學(xué),因?yàn)槟切┏霈F(xiàn)了很多次的詞項(xiàng)和只出現(xiàn)了一次的詞項(xiàng)會(huì)處于等同的地位,就是大家都是1.按照常理來(lái)說(shuō),文檔中詞項(xiàng)出現(xiàn)的頻率越高,那么就意味著這個(gè)詞項(xiàng)在文檔中的地位就越高,相應(yīng)的權(quán)重就越大。而這個(gè)權(quán)重就是詞項(xiàng)出現(xiàn)的次數(shù),這樣的權(quán)重計(jì)算結(jié)果被稱為詞頻(term frequency),用TF來(lái)表示。
IDF的出現(xiàn):
在用TF來(lái)表示權(quán)重的時(shí)候,會(huì)出現(xiàn)一個(gè)嚴(yán)重的問(wèn)題:就是所有 的詞項(xiàng)都被認(rèn)為是一樣重要的。但在實(shí)際中,某些詞項(xiàng)對(duì)文本相關(guān)性的計(jì)算來(lái)說(shuō)毫無(wú)意義,舉個(gè)例子,所有的文檔都含有汽車這個(gè)詞匯,那么這個(gè)詞匯就沒(méi)有區(qū)分能力。解決這個(gè)問(wèn)題的直接辦法就是讓那些在文檔集合中出現(xiàn)頻率較高的詞項(xiàng)獲得一個(gè)比較低的權(quán)重,而那些文檔出現(xiàn)頻率較低的詞項(xiàng)應(yīng)該獲得一個(gè)較高的權(quán)重。
為了獲得出現(xiàn)詞項(xiàng)T的所有的文檔的數(shù)目,我們需要引進(jìn)一個(gè)文檔頻率df。由于df一般都比較大,為了便于計(jì)算,需要把它映射成一個(gè)較小的范圍。我們假設(shè)一個(gè)文檔集里的所有的文檔的數(shù)目是N,而詞項(xiàng)的逆文檔頻率(IDF)。計(jì)算的表達(dá)式如下所示:

通過(guò)這個(gè)idf,我們就可以實(shí)現(xiàn)罕見(jiàn)詞的idf比較高,高頻詞的idf比較低。
TF-IDF的計(jì)算:
TF-IDF = TF * IDF
有了這個(gè)公式,我們就可以對(duì)文檔向量化后的每個(gè)詞給予一個(gè)權(quán)重,若不含這個(gè)詞,則權(quán)重為0。
余弦相似度的計(jì)算:
有了上面的基礎(chǔ)知識(shí),我們可以將每個(gè)分好詞和去停用詞的文檔進(jìn)行文檔向量化,并計(jì)算出每一個(gè)詞項(xiàng)的權(quán)重,而且每個(gè)文檔的向量的維度都是一樣的,我們比較兩篇文檔的相似性就可以通過(guò)計(jì)算這兩個(gè)向量之間的cos夾角來(lái)得出。下面給出cos的計(jì)算公式:

分母是每篇文檔向量的模的乘積,分子是兩個(gè)向量的乘積,cos值越趨向于1,則說(shuō)明兩篇文檔越相似,反之越不相似。
文本比較實(shí)例:
對(duì)文本進(jìn)行去停用詞和分詞:
文本未分詞前,如下圖所示:

文本分詞和去停用詞后,如下圖所示:

詞頻統(tǒng)計(jì)和文檔向量化
對(duì)經(jīng)過(guò)上一步處理過(guò)的文檔,我們可以統(tǒng)計(jì)每個(gè)文檔中的詞項(xiàng)的詞頻,并且將其向量化,下面我直接給出文檔向量化之后的結(jié)果。注意:在這里由于只是比較兩篇文檔的相似性,所以我只用了tf來(lái)作為詞項(xiàng)的權(quán)重,并未使用tf-idf:

向量化后的結(jié)果是:
[1,1,1,1,1,1,1,1,1,1,1,1,1,1]
- 兩篇文檔進(jìn)行相似度的計(jì)算,我會(huì)給出兩篇文檔的原文和最終計(jì)算的相似度:
文檔原文如下所示:

文檔A的內(nèi)容

文檔B的內(nèi)容

余弦相似度代碼實(shí)現(xiàn):
import math # 兩篇待比較的文檔的路徑 sourcefile = '1.txt' s2 = '2.txt' # 關(guān)鍵詞統(tǒng)計(jì)和詞頻統(tǒng)計(jì),以列表形式返回 def Count(resfile): t = {} infile = open(resfile, 'r', encoding='utf-8') f = infile.readlines() count = len(f) # print(count) infile.close() s = open(resfile, 'r', encoding='utf-8') i = 0 while i < count: line = s.readline() # 去換行符 line = line.rstrip('\n') # print(line) words = line.split(" ") # print(words) for word in words: if word != "" and t.__contains__(word): num = t[word] t[word] = num + 1 elif word != "": t[word] = 1 i = i + 1 # 字典按鍵值降序 dic = sorted(t.items(), key=lambda t: t[1], reverse=True) # print(dic) # print() s.close() return (dic) def MergeWord(T1,T2): MergeWord = [] duplicateWord = 0 for ch in range(len(T1)): MergeWord.append(T1[ch][0]) for ch in range(len(T2)): if T2[ch][0] in MergeWord: duplicateWord = duplicateWord + 1 else: MergeWord.append(T2[ch][0]) # print('重復(fù)次數(shù) = ' + str(duplicateWord)) # 打印合并關(guān)鍵詞 # print(MergeWord) return MergeWord # 得出文檔向量 def CalVector(T1,MergeWord): TF1 = [0] * len(MergeWord) for ch in range(len(T1)): TermFrequence = T1[ch][1] word = T1[ch][0] i = 0 while i < len(MergeWord): if word == MergeWord[i]: TF1[i] = TermFrequence break else: i = i + 1 # print(TF1) return TF1 def CalConDis(v1,v2,lengthVector): # 計(jì)算出兩個(gè)向量的乘積 B = 0 i = 0 while i < lengthVector: B = v1[i] * v2[i] + B i = i + 1 # print('乘積 = ' + str(B)) # 計(jì)算兩個(gè)向量的模的乘積 A = 0 A1 = 0 A2 = 0 i = 0 while i < lengthVector: A1 = A1 + v1[i] * v1[i] i = i + 1 # print('A1 = ' + str(A1)) i = 0 while i < lengthVector: A2 = A2 + v2[i] * v2[i] i = i + 1 # print('A2 = ' + str(A2)) A = math.sqrt(A1) * math.sqrt(A2) print('兩篇文章的相似度 = ' + format(float(B) / A,".3f")) T1 = Count(sourcefile) print("文檔1的詞頻統(tǒng)計(jì)如下:") print(T1) print() T2 = Count(s2) print("文檔2的詞頻統(tǒng)計(jì)如下:") print(T2) print() # 合并兩篇文檔的關(guān)鍵詞 mergeword = MergeWord(T1,T2) # print(mergeword) # print(len(mergeword)) # 得出文檔向量 v1 = CalVector(T1,mergeword) print("文檔1向量化得到的向量如下:") print(v1) print() v2 = CalVector(T2,mergeword) print("文檔2向量化得到的向量如下:") print(v2) print() # 計(jì)算余弦距離 CalConDis(v1,v2,len(v1))
到此這篇關(guān)于python實(shí)現(xiàn)余弦相似度文本比較的文章就介紹到這了,更多相關(guān)python余弦相似度內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于python實(shí)現(xiàn)MUI區(qū)域滾動(dòng)
這篇文章主要介紹的是python實(shí)現(xiàn)MUI區(qū)域滾動(dòng),MUI提供了區(qū)域滾動(dòng)的組件,使用時(shí)遵循DOM結(jié)構(gòu)就可以,下面來(lái)看看文章具體的實(shí)現(xiàn)內(nèi)容,需要的朋友可以參考一下2021-11-11
基于Python實(shí)現(xiàn)西西成語(yǔ)接龍小助手
成語(yǔ)接龍是中華民族傳統(tǒng)的文字游戲。本文將用Python制作一個(gè)簡(jiǎn)單的成語(yǔ)接龍小程序,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-08-08
keras分類之二分類實(shí)例(Cat and dog)
這篇文章主要介紹了keras分類之二分類實(shí)例(Cat and dog),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
講解Python的Scrapy爬蟲(chóng)框架使用代理進(jìn)行采集的方法
這篇文章主要介紹了講解Python的Scrapy爬蟲(chóng)框架使用代理進(jìn)行采集的方法,并介紹了隨機(jī)使用預(yù)先設(shè)好的user-agent來(lái)進(jìn)行爬取的用法,需要的朋友可以參考下2016-02-02
python基礎(chǔ)之Numpy庫(kù)中array用法總結(jié)
NumPy(Numerical Python的縮寫(xiě))是一個(gè)開(kāi)源的Python科學(xué)計(jì)算庫(kù),使用NumPy就可以很自然地使用數(shù)組和矩陣,這篇文章主要給大家介紹了關(guān)于python基礎(chǔ)之Numpy庫(kù)中array用法的相關(guān)資料,需要的朋友可以參考下2021-08-08
使用python下載大型文件顯示進(jìn)度條和下載時(shí)間的操作代碼
大家都知道下載大型文件時(shí)存在一個(gè)問(wèn)題,那就是內(nèi)存使用量迅速上升,可能會(huì)造成電腦卡死,所以我們需要換一個(gè)方式進(jìn)行下載,這篇文章主要介紹了使用python下載大型文件的方法顯示進(jìn)度條和下載時(shí)間,需要的朋友可以參考下2022-11-11
Python數(shù)據(jù)結(jié)構(gòu)與算法中的棧詳解(1)
這篇文章主要為大家詳細(xì)介紹了Python中的棧,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03

