Python實現(xiàn)文本相似度分析
1.文本相似度比較概述
通過計算并比較文檔的摘要可實現(xiàn)文本的相似度比較。
文檔摘要的最簡單形式可以使用文檔中的k-grams(k個連續(xù)字符)的相對頻率的向量來表示。假設字符的取值可能有128種不同的值(ASCII碼),則向量的維度d為128k,對于Unicode編碼,這更是天文數(shù)字。因此,一般使用哈希函數(shù)hash(s) % d把k-grams字符串s映射到0到d-1之間的整數(shù),從而使得文檔摘要向量的維度為d。
創(chuàng)建文檔摘要向量之后,可通過比較兩個文檔摘要向量的距離的方法來判斷兩個文檔的相似度。
下面先闡述向量類(Vector)和文檔摘要類(Sketch)的設計與實現(xiàn),然后使用文檔摘要類來比較文檔的相似度。
2.向量(Vector)類設計和實現(xiàn)
向量是一種數(shù)學抽象,n維向量可以使用一個n個實數(shù)的有序列表(x0, x1, …, xn-1)。向量支持基本的四則算數(shù)運算,故可通過運算符重載來實現(xiàn)。
向量的基本運算包括:兩個向量的加法、一個向量乘以一個標量(一個實數(shù))、計算兩個向量的點積、計算向量大小和方向。
(1)加法:x + y = ( x0 + y0, x1 + y1, . . ., xn-1 + yn-1 )
(2)減法:x - y = ( x0 - y0, x1 - y1, . . ., xn-1 - yn-1 )
(3)標量積:αx = (αx0, αx1, . . ., αxn-1)
(4)點積:x·y = x0y0 + x1y1 + . . . + xn-1yn-1
(5)大小:|x| = (x02 + x12 + . . . + xn-12)1/2
(6)方向:x / |x| = ( x0/|x|, x1/|x|, . . ., xn-1/|x|)
基本的向量(Vector)類設計思路如下。
(1)定義帶一個列表參數(shù)(向量的坐標,可以是任意維度)的構造函數(shù),用于初始化對應向量的實例對象屬性_coords。
(2)重載方法__getitem__(),返回第i個元素,即第i維坐標。
(3)重載方法__add__()、__sub__()、__abs__(),實現(xiàn)向量的運算,即加法、減法、大?。#?。
(4)定義方法scale()、dot()、direction(),實現(xiàn)向量的運算,即標量積、點積、方向。
(5)重載方法__len__(),返回向量的維度。
(6)重載方法__str__(),返回向量的字符串表示。
基于上述設計思想,向量(Vector)的實現(xiàn)和測試代碼如下所示。
【例1】向量類(Vector)的實現(xiàn)和測試(vector.py)。
import math class Vector: """笛卡爾坐標系向量""" def __init__(self, a): """構造函數(shù):切片拷貝列表參數(shù)a到對象實例變量_coords""" self._coords = a[:] # 坐標列表 self._n = len(a) # 維度 def __getitem__(self, i): """返回第i個元素,即第i維坐標""" return self._coords[i] def __add__(self, other): """返回2個向量之和""" result = [] for i in range(self._n): result.append(self._coords[i] + other._coords[i]) return Vector(result) def __sub__(self, other): """返回2個向量之差""" result = [] for i in range(self._n): result.append(self._coords[i] - other._coords[i]) return Vector(result) def scale(self, n): """返回向量與數(shù)值的乘積差""" result = [] for i in range(self._n): result.append(self._coords[i] * n) return Vector(result) def dot(self, other): """返回2向量的內積""" result = 0 for i in range(self._n): result += self._coords[i] * other._coords[i] return result def __abs__(self): """返回向量的模""" return math.sqrt(self.dot(self)) def direction(self): """返回向量的單位向量""" return self.scale(1.0 / abs(self)) def __str__(self): """返回向量的字符串表示""" return str(self._coords) def __len__(self): """返回向量的維度""" return self._n #測試代碼 def main(): xCoords = [2.0, 2.0, 2.0] yCoords = [5.0, 5.0, 0.0] x = Vector(xCoords) y = Vector(yCoords) print('x = {}, y = {}'.format(x, y)) print('x + y = {}'.format(x + y)) print('10x = {}'.format(x.scale(10.0))) print('|x| = {}'.format(abs(x))) print(' = {}'.format(x.dot(y))) print('|x-y| = {}'.format(abs(x-y))) if __name__ == '__main__': main()
程序運行結果如下。
x = [2.0, 2.0, 2.0], y = [5.0, 5.0, 0.0]
x + y = [7.0, 7.0, 2.0]
10x = [20.0, 20.0, 20.0]
|x| = 3.4641016151377544
= 20.0
|x-y| = 4.69041575982343
3.文檔摘要類(Sketch)的設計和實現(xiàn)
文檔摘要類(Sketch)用于封裝文檔的摘要信息。設計思路如下。
(1)定義帶3個列表參數(shù)(text(文本)、k(k-grams)、d(文檔摘要向量的維度))的構造函數(shù)。使用列表解析創(chuàng)建一個包含d個元素的列表freq(初始值為0),用于存儲k-grams的頻率。循環(huán)抽取文本的所有k-grams,并使用hash函數(shù)映射到0-d之間的整數(shù),從而更新對應的列表freq的元素值(遞增)。然后使用freq創(chuàng)建Vector對象vector,并調用向量對象的direction()方法進行歸一化。最后把文檔摘要向量vector并保存到實例對象屬性_sketch。
(2)定義方法similarTo(),計算兩個文檔摘要向量的余弦相似度。
比較兩個向量的常用方法包括歐幾里得距離和余弦相似性度。給定向量x和y,其歐幾里得距離定義為:
余弦相似性度定義為:
基于Vector對象,給定向量x和y,其歐幾里得距離為abs(x – y),余弦相似性度的計算方法為x.dot(y)。
(3)重載方法__str__(),返回向量的字符串表示。
基于上述設計思想,向量(Sketch)的實現(xiàn)和測試代碼如下所示。
【例2】文檔摘要類(Sketch)的實現(xiàn)和測試(sketch.py)。
import sys from vector import Vector class Sketch: """計算文本text的k-grams的文檔摘要向量(d維)""" def __init__(self, text, k, d): """初始化函數(shù):計算文本text的文檔摘要向量""" freq = [0 for i in range(d)] #創(chuàng)建長度為d的列表,初始值0 for i in range(len(text) - k): #循環(huán)抽取k-grams,計算頻率 kgram = text[i:i+k] freq[hash(kgram) % d] += 1 vector = Vector(freq) #創(chuàng)建文檔摘要向量 self._sketch = vector.direction() #歸一化并賦值給對象實例變量 def similarTo(self, other): """比較兩個文檔摘要對象Sketch的余弦相似度""" return self._sketch.dot(other._sketch) def __str__(self): return str(self._sketch) #測試代碼 def main(): with open("tomsawyer.txt","r") as f: text = f.read() sketch = Sketch(text, 5, 100) print(sketch) if __name__ == '__main__': main()
程序的運行結果如下。
[0.09151094195152963, …, 0.08903767325013694]
說明
哈希函數(shù)基于一個數(shù)值“種子”計算,在Python 3中,哈希種子會改變(缺省情況下),即給定對象的哈希值可能每次運行結果都不一樣。因而,程序輸出結果可能不同。
4.通過比較文檔摘要確定文檔的相似度
使用前文設計和實現(xiàn)的類Sketch,可以比較文檔的相似度。
【例3】使用Sketch類比較文檔的相似度(document_compare.py)。
import sys from vector import Vector from sketch import Sketch #測試文檔列表 filenames = [ 'gene.txt', 'pride.txt', 'tomsawyer.txt'] k = 5 #k-grams d = 100000 #文檔摘要向量維度 sketches = [0 for i in filenames] for i in range(len(filenames)): with open(filenames[i], 'r') as f: text = f.read() sketches[i] = Sketch(text, k, d) #輸出結果標題 print(' '*15, end='') for filename in filenames: print('{:>22}'.format(filename), end='') print() #輸出結果比較明細 for i in range(len(filenames)): print('{:15}'.format(filenames[i]), end='') for j in range(len(filenames)): print('{:22}'.format(sketches[i].similarTo(sketches[j])), end='') print()
程序運行結果如下:
結果表明,相同文檔的相似度為1,相同類型的文檔(pride.txt和tomsawyer.txt)相似度比較大,而不同類型的文檔(gene.txt和pride.txt)的相似度則比較低。
到此這篇關于Python實現(xiàn)文本相似度分析的文章就介紹到這了,更多相關Python文本相似度內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Pandas時間序列重采樣(resample)方法中closed、label的作用詳解
這篇文章主要介紹了Pandas時間序列重采樣(resample)方法中closed、label的作用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12Python技法之如何用re模塊實現(xiàn)簡易tokenizer
當我們在Python中開始新的東西時,我通常首先看一些模塊或庫來使用,下面這篇文章主要給大家介紹了關于Python技法之如何用re模塊實現(xiàn)簡易tokenizer的相關資料,需要的朋友可以參考下2022-05-05python 基于opencv 實現(xiàn)一個鼠標繪圖小程序
這篇文章主要介紹了python 基于opencv 實現(xiàn)一個鼠標繪圖小程序,幫助大家更好的理解和使用python的opencv庫,感興趣的朋友可以了解下2020-12-12Python簡單實現(xiàn)查找一個字符串中最長不重復子串的方法
這篇文章主要介紹了Python簡單實現(xiàn)查找一個字符串中最長不重復子串的方法,涉及Python針對字符串的簡單遍歷、運算等相關操作技巧,需要的朋友可以參考下2018-03-03