引言給定兩個(gè)文本文件(比如2018年政府工作報(bào)告.txt與2019年政府工作報(bào)告.txt),怎么計(jì)算兩者的相似度有多大?這是文本挖掘的一個(gè)任務(wù),本篇將使用的方法思想如下:
理論知識(shí)一、詞袋模型文檔內(nèi)容(以下均簡(jiǎn)稱(chēng)為文檔)中出現(xiàn)頻率越高的詞項(xiàng),越能描述該文檔(不考慮停用詞)。因此可以統(tǒng)計(jì)每個(gè)詞項(xiàng)在每篇文檔中出現(xiàn)的次數(shù),即詞項(xiàng)頻率,記為 ,其中t 為詞項(xiàng),d為文檔。獲得文檔中每個(gè)詞的 tf 權(quán)重,一篇文檔則轉(zhuǎn)換成了詞-權(quán)重的集合,通常稱(chēng)為詞袋模型(bag of words model)。我們用詞袋模型來(lái)描述一篇文檔 。詞袋的含義就是說(shuō),像是把一篇文檔拆分成一個(gè)一個(gè)的詞條,然后將它們?nèi)舆M(jìn)一個(gè)袋子里。在袋子里的詞與詞之間是沒(méi)有關(guān)系的。因此詞袋模型中,詞項(xiàng)在文檔中出現(xiàn)的次序被忽略,出現(xiàn)的次數(shù)被統(tǒng)計(jì)。例如,“a good book” 和“book good a” 具有同樣的意義。將詞項(xiàng)在每篇文檔中出現(xiàn)的次數(shù)保存在向量中,這就是這篇文檔的文檔向量。 二、余弦相似度計(jì)算前面提出了文檔向量的概念。其中每個(gè)分量代表詞項(xiàng)在文檔中的相對(duì)重要性。一系列文檔在同一向量空間的表示稱(chēng)為 VSM(Vector Space Model)。VSM 是詞袋模型。向量空間模型是信息檢索、文本分析中基本的模型。通過(guò)該模型,可以進(jìn)行有序文檔檢索、文檔聚類(lèi)、文檔分類(lèi)等。當(dāng)然,現(xiàn)在的研究有新發(fā)展。出現(xiàn)了很多模型代替VSM。每篇文檔在VSM中用向量表示,那么計(jì)算兩篇文檔的相似度自然的想到用兩個(gè)向量的差值。但是,可能存在的情況是。如果兩篇相似的文檔,由于文檔長(zhǎng)度不一樣。他們的向量的差值會(huì)很大。余弦相似度是使用的非常廣泛的計(jì)算兩個(gè)向量相似度的公式,它可以去除文檔長(zhǎng)度的影響。 公式的分母是兩個(gè)向量的歐幾里得長(zhǎng)度之積,分子是兩個(gè)向量的內(nèi)積。這樣計(jì)算得到的sim實(shí)際上就是兩個(gè)歐式歸一化的向量之間的夾角的余弦。如下圖: python實(shí)現(xiàn)及注釋1 import jieba 2 import math 3 import re 4 #讀入兩個(gè)txt文件存入s1,s2字符串中 5 s1 = open('rdbg2018.txt','r').read() 6 s2 = open('rdbg2019.txt','r').read() 7 8 #利用jieba分詞與停用詞表,將詞分好并保存到向量中 9 stopwords=[] 10 fstop=open('stop_words.txt','r',encoding='utf-8-sig') 11 for eachWord in fstop: 12 eachWord = re.sub("\n", "", eachWord) 13 stopwords.append(eachWord) 14 fstop.close() 15 s1_cut = [i for i in jieba.cut(s1, cut_all=True) if (i not in stopwords) and i!=''] 16 s2_cut = [i for i in jieba.cut(s2, cut_all=True) if (i not in stopwords) and i!=''] 17 word_set = set(s1_cut).union(set(s2_cut)) 18 19 #用字典保存兩篇文章中出現(xiàn)的所有詞并編上號(hào) 20 word_dict = dict() 21 i = 0 22 for word in word_set: 23 word_dict[word] = i 24 i += 1 25 26 27 #根據(jù)詞袋模型統(tǒng)計(jì)詞在每篇文檔中出現(xiàn)的次數(shù),形成向量 28 s1_cut_code = [0]*len(word_dict) 29 30 for word in s1_cut: 31 s1_cut_code[word_dict[word]]+=1 32 33 s2_cut_code = [0]*len(word_dict) 34 for word in s2_cut: 35 s2_cut_code[word_dict[word]]+=1 36 37 # 計(jì)算余弦相似度 38 sum = 0 39 sq1 = 0 40 sq2 = 0 41 for i in range(len(s1_cut_code)): 42 sum += s1_cut_code[i] * s2_cut_code[i] 43 sq1 += pow(s1_cut_code[i], 2) 44 sq2 += pow(s2_cut_code[i], 2) 45 46 try: 47 result = round(float(sum) / (math.sqrt(sq1) * math.sqrt(sq2)), 3) 48 except ZeroDivisionError: 49 result = 0.0 50 print("\n余弦相似度為:%f"%result)
|
|
來(lái)自: wenxuefeng360 > 《待分類(lèi)1》