文本相似在问答系统中有很重要的应用,如基于知识的问答系统(Knowledge-based QA),基于文档的问答系统(Documen-based QA),以及基于FAQ的问答系统(Community-QA)等。像 对于问题的内容,需要进行相似度匹配,从而选择出与问题最接近,同时最合理的答案。本节介绍 基于simhash相似度。
算法描述:先计算两句子的simhash二进制编码,然后使用海明距离计算,最后使用两句的最大simhash值归一化得相似度。
from simhash import Simhash
def sim_simhash(s1, s2):
"""先计算两文档的simhash值,然后使用汉明距离求相似度"""
# 1. 计算文本simhash值
a_simhash = Simhash(s1, f=64)
b_simhash = Simhash(s2, f=64)
max_hashbit = max(len(bin(a_simhash.value)), len(bin(b_simhash.value)))
# 2. 计算汉明距离汉明距离
distance = a_simhash.distance(b_simhash)
# 3. 归一化到0~1
sim = 1 - distance / max_hashbit
return sim
word1 = '这是什么'
word2 = '这个什么价钱'
word_sim = sim_simhash( word1, word2 )
原理介绍:
可以将一个文档转换成64位的字节,然后我们可以通过判断两个字节的汉明距离就知道是否相似了。
汉明距离是以理查德·卫斯里·汉明的名字命名的。在信息论中,两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。换句话说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。例如:
1011101 与 1001001 之间的汉明距离是 2。
"toned" 与 "roses" 之间的汉明距离是 3。
首先我们来计算SimHash:
① 提取文档关键词得到[word,weight]这个一个数组。(举例 [美国,4])
② 用hash算法将word转为固定长度的二进制值的字符串[hash(word),weight]。(举例 [100101,4])
③ word的hash从左到右与权重相乘,如果为1则乘以1 ,如果是0则曾以-1。(举例4,-4,-4,4,-4,4)
④ 接着计算下个数,直到将所有分词得出的词计算完,然后将每个词第三步得出的数组中的每一个值相加。(举例美国和51区,[4,-4,-4,4,-4,4]和[5 -5 5 -5 5 5]得到[9 -9 1 -1 1 9])
⑤ 对第四步得到的数组中每一个值进行判断,如果>0记为1,如果<0记为0。(举例[101011])
第四步得出的就是这个文档的SimHash。
这样我们就能将两个不同长度的文档转换为同样长度的SimHash值,so,我们现在可以计算第一个文档的值和第二个文档的汉明距离(一般<3就是相似度高的)。
SimHash本质上是局部敏感性的hash(如果是两个相似的句子,那么只会有部分不同),和md5之类的不一样。 正因为它的局部敏感性,所以我们可以使用海明距离来衡量SimHash值的相似度。
如果想要小数形式的可以这么做:1 - 汉明距离 / 最长关键词数组长度。