得搞个目录
方法一
方法二
方法三
方法四
方法五
方法六
方法七
方法八
方法九
方法十
方法十一
每个方法写了一段代码
输入:
s0=20个字的句子
s1=10个字的句子
s2=20个字的句子
s3=30个字的句子
输出:
s0与s1的相似度
s0与s2的相似度
s0与 s3的相似度
方法一:莱文斯坦距离(编辑距离)
莱文斯坦距离,又称Levenshtein距离,是编辑距离的一种。指两个字串之间,由一个转成另一个所需的最少编辑操作次数。允许的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
https://baike.baidu.com/item/莱文斯坦距离/14448097
参考1:《NLP句子相似性方法总结及实现》https://blog.csdn.net/huangzhilin2015/article/details/113415951
参考2 :参考python实现:其实跟百度百科一样,但是搜到了就很简单https://blog.csdn.net/sinat_26811377/article/details/102652547
easyDemo:
# -*- coding: utf-8 -*-
# 中文编辑距离的代码实现(传统方法)
# author:菠萝侠
# date:2022-12-07
import argparse
import numpy as np
def laiwensitan(first,second):
if len(first) > len(second):
first, second = second, first
str1,str2 = first,second
matrix = [[i + j for j in range(len(str2) + 1)] for i in range(len(str1) + 1)]
for i in range(1, len(str1) + 1):
for j in range(1, len(str2) + 1):
# 如果相同则不用动
if (str1[i - 1] == str2[j - 1]):
d = 0
else:
d = 1
matrix[i][j] = min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + d)
return matrix[len(str1)][len(str2)]
def fun(s0,s1,f0,f1):
ans = []
for i in range(len(s0)):
x = laiwensitan(s0[i],s1[i])
# 距离越大实际上越小,故x取负值
ans.append(x*(-1))
# 1:01标准化
max_ans = max(ans)
min_ans = min(ans)
ans1 = []
for i in range(len(s0)):
x = (ans[i] - min_ans) / (max_ans - min_ans) * f0
x = float(int(x*2)/2)
ans1.append(6.0- x)
print(ans1)
# 2:标准归一化
junzhi = np.average(ans)
fangcha = np.average(ans)
ans2 = []
for i in range(len(s0)):
x = (ans[i]-junzhi)*f0 /fangcha + f1
x = float(int(x * 2) / 2)
ans2.append(x)
print(ans2)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
# 为了方便测试,找来百度百科的一段话进行改编
''' 自然语言处理是计算机科学领域与人工智能领域中的一个重要方向。它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。自然语言处理是一门融语言学、计算机科学、数学于一体的科学。因此,这一领域的研究将涉及自然语言,即人们日常使用的语言,所以它与语言学的研究有着密切的联系,但又有重要的区别。自然语言处理并不是一般地研究自然语言,而在于研制能有效地实现自然语言通信的计算机系统,特别是其中的软件系统。因而它是计算机科学的一部分 。'''
S0 = '自然语言处理是研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。'
S1 = '这里是一段狗屁不通的护眼乱语,NLP是人机之间用自然语言进行有效通信的各种理论和方法。'
S2 = '研究用自然语言相关的各种理论和方法。'
S3 = '自然语言处理是计算机科学的一部分,是实现自然语言通信的计算机系统,及用自然语言进行有效通信的各种理论和方法。'
parser.add_argument('--cankao',type=list,default=[S0,S0,S0],help='基准')
parser.add_argument('--xueshen',type=list,default=[S1,S2,S3],help='对比')
parser.add_argument('--fenshu',type=float,default=6.0,help='分值')
parser.add_argument('--junfen',type=float,default=4.0,help='均分')
opt = parser.parse_args()
fun(opt.cankao,opt.xueshen,opt.fenshu,opt.junfen)
# 思考:
结果:
01标准化的:
[0.0, 6.0, 4.0]
标准归一化:
[3.5, 4.0, 4.0]
增加一些自己的想法:
easyDemo2:
'''
基于三个:
1. 汉字构成复杂,但偏旁有一定的意义;
2. 同义词、近义词是可以替换的,且替换的距离应该很近、反义词应该很远;
3. 一个字/词可能有多个含义;
我们再次进行改进
描述方法:
字典1:偏旁字典
字典2:同义词词典
字典3:逻辑词典(并列关系、转折关系等)
流程:
s0 = 我吃饭后回家
s1 = 我回家后直接干饭
step1:选出相同 用in就行 if s1[i] in s0: ...
得到 我 饭 后 回 家
step2:s0分词
我 吃饭 后 回家
s1分词
我 回家 后 直接 干饭
可能同义词:饭
是否需要修改:是
是否需要添加:否
是否需要删除:是
step3:修改过程:
s1 多余词 直接 删除 距离 2 -> 乘以适当的系数 -> x1
s1 = 我 回家 后 干饭
s1 近义词 干饭 - 吃饭 距离 10 -> 乘以适当的系数 -> x2
s1 = 我 回家 后 吃饭
s1 位置修改1(最短,最左开始) 回家>> 1位
if 回家 or 吃饭 or 后 in 并列关系的词
距离 += 0
elif 转折(但是、然而、然)
距离 += 2 * 大系数
elif 递进关系(先后关系、前后关系)
距离 += 2 * 大系数
else
距离 += 2
距离 = x3
s1 =我 后 回家 吃饭
s1 位置修改2
if 后 回家 吃饭 in 词典
同理
距离 = x4
s1 = 我 回家 后 吃饭 = s0
step4:计算距离
'''
参考3:《相似度算法–莱文斯坦距离加入同义词逻辑》https://blog.csdn.net/huangzhilin2015/article/details/113415951
参考4:《【NLP】45个小众而实用的NLP开源字典和工具》https://blog.csdn.net/qq_27590277/article/details/106263884
# -*- coding: utf-8 -*-
# 中文编辑距离的代码实现(增加“距离字典”方法)
# author:菠萝侠
# date:2022-12-08
方法二:BM25
TFIDF计算
TextRank算法中的句⼦相似性
基于Word2Vec的余弦相似度
DSSM(Deep Structured Semantic Models)
下面是苏神科学空间的相关的文章和推荐阅读
- 《从局部到全局:语义相似度的测地线距离》 链接
- 《Unsupervised Opinion Summarization Using Approximate Geodesics》《使用近似测地线的无监督意见总结》链接
- 《CoSENT(一):比Sentence-BERT更有效的句向量方案》链接
- 《CoSENT(二):特征式匹配与交互式匹配有多大差距?》链接
- 《CoSENT(三):作为交互式相似度的损失函数》链接
- 评论区大神给出了代码:https://github.com/shawroad/CoSENT_Pytorch
- https://github.com/ymcui/Chinese-BERT-wwm
- 相关竞赛搜狐文本匹配:基于条件LayerNorm的多任务baseline 链接
- NLP语义相似度计算的两大类方法 链接