• 推荐自己的专栏:分享一些Python案例,将所学用出来

一:文本相似度比较概述

通过计算并比较文档的摘要,可实现文本的相似度比较。

  • 文档摘要的最简单形式可以使用文档中的k-grams(k个连续字符)的相对频率的向量来表示。
  • 假设字符的取值可能有128种不同的值(ASCII码) ,则向量的维度d为128k;对于Unicode编码,这更是天文数字。
  • 因此,一般使用哈希函数hash(s) % dk-grams字符串s映射到0d-1之间的整数,从而使得文档摘要向量的维度为d。.
  • 创建文档摘要向量之后,可通过比较两个文档摘要向量的距离的方法来判断两个文档的相似度。

下面先阐述向量类(Vector) 和文档摘要类(Sketch)的设计与实现,然后使用文档摘要类来比较文档的相似度。

二:向量(Vector) 类设计和实现

向量是一种数学抽象,n维向量可以使用一个n个实数的有序列表: (x0, x1,…,xn-1)。向量支持基本的四则算数运算,故可通过运算符重载来实现。

向量的基本运算
包括:两个向量的加法、一个向量乘以一个标量(一个实数)、计算两个向量的点积、计算向量大小和方向。

  1. 加法:x+y = (x0+y0, x1+y1, …, xn-1+yn-1)
  2. 减法:x-y = (x0-y0,x1-y1,…,xn-1-yn-1)
  3. 标量积:ax = (ax0,ax1, …,axn-1)
  4. 点积:xy = x0y0 + x1y1 +… + xn-1yn-1
  5. 大小:|x| = (x02 + x12 + … + xn-12)1/2
  6. 方向:x / |x| = ( x0 / |x|,x1 / |x|,…,xn-1 / |x| )

基本的向量(Vector) 类设计思路如下:

  • 定义带一个列表参数(向量的坐标,可以是任意维度)的构造函数,用于初始化对应向量的实例对象属性:_coords
def __init__(self, a):"""构造函数:切片拷贝列表参数a到对象实例变量_coords"""self._coords = a[:]self._n = len(a)
  • 重载方法__getitem__ ,返回第 i 个元素,即第 i 维坐标。
def __getitem__(self, i):"""返回第i个元素,即第i维坐标"""return self._coords[i]
  • 重载方法__len__, 返回向量的维度。
def __len__(self):"""返回向量的维度"""return self._n
  • 重载方法__str__ ,返回向量的字符串表示。.
def __str__(self):"""返回向量的字符串表示"""return str(self._coords)
  • 重载方法__add____sub__ ,实现向量的运算:加法、减法。

加法:x+y = (x0+y0, x1+y1, …, xn-1+yn-1)
减法:x-y = (x0-y0,x1-y1,…,xn-1-yn-1)

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)
  • 定义方法scale(),实现向量的运算:标量积。

标量积:ax = (ax0,ax1, …,axn-1)

def scale(self, n):"""返回向量与数值的乘积(标量积)"""result = []for i in range(self._n):result.append(self._coords[i] * n)return Vector(result)
  • 定义方法 dot(),实现向量的运算:点积。

点积:xy = x0y0 + x1y1 +… + xn-1yn-1

def dot(self, other):"""返回2向量的内积(点积)"""result = 0for i in range(self._n):result += self._coords[i] * other._coords[i]return result
  • 重载方法__abs__,实现向量的运算:大小(模)。

大小:|x| = (x02 + x12 + … + xn-12)1/2

def __abs__(self):"""返回向量的模"""return math.sqrt(self.dot(self))
  • 定义方法direction(),实现向量的运算:方向。

方向:x / |x| = ( x0 / |x|,x1 / |x|,…,xn-1 / |x| )

def direction(self):"""返回向量的单位向量"""return self.scale(1.0 / abs(self))

vector.py

import mathclass Vector:"""笛卡尔坐标系向量"""def __init__(self, a):"""构造函数:切片拷贝列表参数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):"""返回向量与数值的乘积(标量积)"""result = []for i in range(self._n):result.append(self._coords[i] * n)return Vector(result)def dot(self, other):"""返回2向量的内积(点积)"""result = 0for i in range(self._n):result += self._coords[i] * other._coords[i]return resultdef __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()print('x + y = {}'.format(x + y))print()print('10x = {}'.format(x.scale(10.0)))print()print('|x| = {}'.format(abs(x)))print()print('<x, y> = {}'.format(x.dot(y)))print()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<x, y> = 20.0|x - y| = 4.69041575982343

三:文档摘要类(Sketch) 的设计和实现

文档摘要类(Sketch) 用于封装文档的摘要信息。

设计思路如下:

  • 初始化

定义带3个列表参数(text (文本)、k (k-grams) 、d (文档摘要向量的维度) )的构造函数。

def __init__(self, text, k, d):

使用列表解析创建一个包含d个元素的列表freq (初始值为0),用于存储k-grams的频率。

freq = [0 for i in range(d)]

循环抽取文本的所有k-grams,并使用hash函数映射到0-d之间的整数,从而更新对应的列表freq的元素(递增)。

for i in range(len(text) - k):kgram = text[i:i+k]freq[hash(kgram) % d] += 1

然后使用freq创建Vector对象vector,并调用向量对象的Direction方法进行归一化。

vector = Vector(freq)

最后把文档摘要向量vector并保存到实例对象属性:_sketch

self._sketch = vector.direction()
  • 定义方法similarTo(),计算两个文档摘要向量的余弦相似度。
    比较两个向量的常用方法包括欧几里得距离和余弦相似性度。
    给定向量x和y,其欧几里得距离定义为:|x-y| = ((x0 - y0)2 + (x1 - y1)2 +… + (xn-1 - yn-1)2)1/2
    余弦相似性度定义为:xy = x0y0 + x1y1 + … + xn-1yn-1
    基于Vector对象,给定向量x和y,其欧几里得距离为:abs(x - y), 余弦相似性度的计算方法为: x.dot(y)
def similarTo(self, other):"""比较两个文档摘要对象Sketch的余弦相似度"""return self._sketch.dot(other._sketch)
  1. 重载方法__str__,返回向量的字符串表示。
def __str__(self):return str(self._sketch)

sketch.py

import sys
from vector import Vectorclass Sketch:"""计算文本text的k-grams的文档摘要向量(d维) """def __init__(self, text, k, d):"""初始化函数:计算文本text的文档摘要向量"""freq = [0 for i in range(d)] #创建长度为d的列表,初始值0for i in range(len(text) - k): #循环抽取k- grams,计算频率kgram = text[i:i+k]freq[hash(kgram) % d] += 1vector = Vector(freq) #创建文档摘要向量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("华夏.txt", "r", encoding='UTF-8') as f:text = f.read()sketch = Sketch(text, 5, 100)print(sketch)if __name__ == '__main__':main()

因为我打开的文本“华夏.txt”的编码方式是UTF-8,所以需要指定第三个参数:open("华夏.txt", "r", encoding='UTF-8')

而且,上述代码的输出是列表,列表中的每个值是文本循环输出的的k-grams(k个连续字符)的向量方向(即余弦值),就不将运行结果放出来了。

补充说明:哈希函数基于一个数值“种子”计算,在Python 3中,哈希种子会改变(缺省情况下),即给定对象的哈希值可能每次运行结果都不一样。因而,程序输出结果可能不同。

四:通过比较文档摘要确定文档的相似度

document_compare.py

import sys
from vector import Vector
from sketch import Sketch# 测试文档列表
filenames = ['华夏.txt', '中国.txt', '炎黄子孙.txt']
k = 5 #k-grams
d = 10000 #文档摘要维度
sketches = [0 for i in filenames]
for i in range(len(filenames)):with open(filenames[i], 'r', encoding='UTF-8') as f:text = f.read()sketches[i] = Sketch(text, k, d)# 输出结果标题
print(' ' * 20, end = ' ')
for filename in filenames:print('{:>25}'.format(filename), end = ' ')
print()# 输出结果比较明细
for i in range(len(filenames)):print('{:10}'.format(filenames[i]), end = ' ')for j in range(len(filenames)):print('{: <22}'.format(sketches[i].similarTo(sketches[j])), end = ' ')print()

运行结果:

                       华夏.txt               中国.txt             炎黄子孙.txt
华夏.txt     0.9999999999999785     0.5011577874531165     0.42527486798147096
中国.txt     0.5011577874531165     1.0000000000000089     0.536571712819202
炎黄子孙.txt   0.42527486798147096    0.536571712819202      1.0000000000000757

结果表明,相同文档的相似度为1,相同类型的文档(华夏.txt和中国.txt)相似度尚可,而不同类型的文档(华夏.txt和炎黄子孙.txt)的相似度则稍微低些。

Python实现文本相似度比较分析相关推荐

  1. python jieba 文本相似度_文本相似度分析(基于jieba和gensim)

    ##基础概念 本文在进行文本相似度分析过程分为以下几个部分进行, 文本分词 语料库制作 算法训练 结果预测 分析过程主要用两个包来实现jieba,gensim jieba:主要实现分词过程 gensi ...

  2. python实现文本相似度算法的对比及

    文本相似度算法的对比及python实现 前言 通常我们有这样的需求:对两篇文章或者产品内容进行重复率查询. 为了解决类似的问题,罗列了一些常见的相似度算法,用python代码实现. 五种常见的相似度算 ...

  3. python数据分析-文本相似度分析

    由于本文设计较多知识点,在编写代码之前需要搞清楚这些知识点的含义. 1.知识点解释 Gensim是一款开源的第三方Python工具包,用于从原始的非结构化的文本中,无监督地学习到文本隐层的主题向量表达 ...

  4. python实现文本查重系统_NLP之gensim库python实现文本相似度/匹配/查重

    目的 给定一个或多个搜索词,如"高血压 患者",从已有的若干篇文本中找出最相关的(n篇)文本. 理论知识 文本检索(text retrieve)的常用策略是:用一个ranking ...

  5. Python比较文本相似度的7种方法(详细)

    1词袋模型 from gensim import corpora from gensim import models from gensim import similarities #from cor ...

  6. 文本相似度php,分析php计算文本字符串相似度函数similar_text()的原理

    PHP有个计算两个文本字符串相似度的函数similar_text(),可以得出一个百分比来表示两个字符串的相似程度.效果如下: similar_text('aaaa', 'aaaa', $percen ...

  7. python实现词语相似度计算分析_相似度计算的方法及Python实现

    现实生活中,我们经常提到距离这个词,本文谈的相似度就是基于距离定义的,当两个向量之间的距离特别小时,就说这俩个向量相似度高,反之相似度不高.所以,衡量相似度的指标就是距离度量. 经常使用的相似度计算公 ...

  8. python对比文本相似度

    方法:使用difflib中的SequenceMatcher s=difflib.SequenceMatcher(isjunk=None,a,b, autojunk=True) :构造函数,主要创建任何 ...

  9. python 文本相似度现状_python文本相似度分析

    如何用python计算文本的相似度 同学欢迎来到CSS布局HTML~文本的相似度计算是NLP(自然语言处理)方向的范畴,感兴趣可以找相关的书籍详细学习研究.同学问的这个问题,可以搜索:python文本 ...

最新文章

  1. 算法(1)斐波那契数列
  2. 2020-12-3(ESP定律脱壳理解)
  3. springboot返回modelandview 找不到视图_SpringBoot错误处理机制及原理
  4. 算法学习之路|打印排名
  5. 02.德国博士练习_01_cluster_install
  6. linux nfs spec,创建 NFS Ubuntu Linux 服务器卷 - Azure Kubernetes Service | Microsoft Docs
  7. 安装docker-machine
  8. Unity3d读取.csv文件
  9. 忆当年!董明珠处罚困难员工后自掏腰包补偿:制度必须坚决执行
  10. ODP.NET连接池性能计数器
  11. 【Python】int binary str 互转
  12. Android权限设置引导
  13. 【堆栈溢出】堆栈溢出_liangchaoxi的IT博客_新浪博客
  14. HikariCP 的使用
  15. 单招面试问为什么选择计算机这个专业,单招面试常见问题及答案 面试要注意什么...
  16. 2022年京东年货节红包雨攻略,年货节红包最高领8888元红包
  17. 基于anchor-free的目标检测算法CenterNet研究
  18. Kivy教程之 08 倒计时App实现timer调用(教程含源码)
  19. ASP.NET Core 高级(一)【.NET 的开放 Web 接口 (OWIN)】
  20. 区块链的希望与原罪:从金融场景谈起

热门文章

  1. 且初土豆泥、everbab棉花糖粉扑、好望水气泡饮、王小卤虎皮凤爪、PWU留香珠…月销千万的黑马爆品如何玩转新消费营销?
  2. HTML 实现打电话
  3. 百度搜索结果页面的参数 搜索历史记录(rsv_sug)
  4. 【初级算法】10.有效的数独
  5. RabbitMQ在Docker中安装以及Management API returned status code 500错误
  6. 淘宝自动回复机器人配置手册——目前2018年淘宝主流自动回复软件一览
  7. Android使用XML做动画UI
  8. 阿里云国际版购买了服务器后如何下载发票?
  9. 大促在即,拥有亿级流量的电商平台开发了一个订单系统,我们应该如何来预估其并发量?如何根据并发量来合理配置JVM参数呢?
  10. fx3u4ad一adp说明书_FX3U-4AD-ADP使用案例三菱FX3U-4AD-ADP硬件手册 - 广州正凌