做舆情系统,爬虫采集了很多文章,这些文章都保存在了ES上,当用户看到一篇文章的时候,需要将这篇文章的相似文章都找出来。ES的底层是一个搜索引擎,查找相似文章没问题,不过文章都比较长,直接基于整个文章去计算相似性,恐怕不太妙。
于是我们想到了搜索引擎常用的相似性算法simhash,这是Google在07年提出的算法,算法思想这个文章讲得比较透彻了:https://zhuanlan.zhihu.com/p/81026564
来自知乎
有了simhash算法,我们就能讲一篇常常的文章变成一个64位的二进制字符串,ES好像是在7.2版本之后,可以直接支持向量计算,如果放到现在就简单了。不过我们用的那个时候,版本还在6,没有向量计算功能。
将向量转化为搜索特征
es那个时候虽然还不支持向量,但是支持关键词搜索,我们只要使用空格将特征分开,然后就能搜索。而simhash是要计算相同位上相同值的个数,相同的值越多,相似度越高。我们的算法大概如下:
假设,有个文章对应的simhash为“1011”(一个二进制位表示两个状态,64位共有128个状态):
- 将二进制的simhash从右到左进行位置编码0,1,2,3,4...,如1011中,位置0的值为1,位置1的值为1,位置2的值为0,位置3的值为1;
- 将位置和值做运算:2×位置序号 值,例如位置1运算后的值为2*1 1=3,位置2的新值为2*2 0=4,故二进制1011对应的新值为:1,3,4,7。注意位置序号是从右到左的;
- 将运算后的值组成字符串:“1 3 4 7”,这就是搜索特征,该特征保存在es中,使用空格进行分词。
例如一个文章的simhash值为:
1011100101010111000100111010011110110010100111101000100001110111
转换成搜索特征为:
1 2 5 7 9 10 12 15 16 19 20 23 24 27 29 31 32 34 36 39 40 42 45 47
49 50 53 54 56 59 61 63 65 66 69 71 72 74 77 78 81 82 84 87 89 91
93 94 97 98 100 102 105 106 108 110 112 115 117 119 120 123 125 127
需要计算某个文章的相似文章数量的时候,需要做的是:先按上面的算法生成自己的搜索特征,然后根据搜索特征去ES搜索,返回匹配的若干条个文章(例如该值设置为500,那大于该值的则可以显示为500 ,搜索时可以设置匹配度),然后再对结果做一次相似度计算(最简单的,对两个搜索特征做交集运算即可)
这就是在ES尚未支持向量计算的年代讨巧的实现方式。不过虽然实现有点讨巧,不过这整个思路还是很值得学习的。