前期项目需求需要做一个千万级的文章,新闻类的匹配,周期近20天左右,前半月用simhash 做的算法,从网上和一些博客看到一些资料,经过自己的整理和规划,准备自己出一半simhash 的算法项目
服务器:就这个!
cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 63
model name : Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz
stepping : 2
microcode : 0x1
cpu MHz : 2494.224
cache size : 30720 KB
model name : Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz
stepping : 2
microcode : 0x1
cpu MHz : 2494.224
cache size : 30720 KB
算法:先不谈它的优缺点,先上算法的个人理解
首先需要解释google 的simhash ,不是仅仅的simhash库。网上说的长短文本敏感度其实是有问题的。有的人写simhash 是由二进制实现的,也有一些算法实现,但是通过python的算法包simhash它的value 值是16进制实现。google 的二进制切分四个片段,因为hash 是散列,有不确定性。比如:
41 1101110110101110011000100011001011110011001110000110001111001011 1844
42 1101110110101110011000100011001011110011001110000110001111001011 2018
不同文章,长度不同,simhash自我实现后的二进制居然是相同的。
hash实现原理:将64-bit按照16位划分为4个区间,每个区间剩余的48-bit再按照每个12-bit划分为4个区间,因此总共16个table并行查找,即使三个不同的k-bit落在A、B、C、D中三个不同的区块,此划分方法也不会导致遗漏。这样造成了分区的不确定性。
我跑了517152条simhash 。如果一一做匹配要匹配2000多万次。
但是发现很多相似simhash值
原因就是随机性
海明距离:
A和B的海明距离是否小于等于n,这个n值根据经验一般取值为3,
simhash本质上是局部敏感性的hash,和md5之类的不一样。 正因为它的局部敏感性,所以我们可以使用海明距离来衡量simhash值的相似度。
在一个码组集合中,任意两个码字之间对应位上码元取值不同的位的数目定义为这两个码字之间的汉明距离。即
d(x,y)=∑x[i]⊕y[i]
这里i=0,1,..n-1,x,y都是n位的编码,⊕表示异或
line为字符串类型:
Simhash(line1).distance(Simhash(line2))
原理demo:
def distance(self, another): assert self.f == another.f x = (self.value ^ another.value) & ((1 << self.f) - 1) ans = 0 while x: ans += 1 x &= x - 1 return ans
网上写的距离有问题。
我开发后觉得是准确的,但是要换一种思路去做。
第一:要缩短文章长度。即关键词提取:部分开发代码:
keyword = np.array(word_weight['word']) word_split = [keyword[x] for x in range(0, topK)] # print(word_split) word_split = " ".join(word_split) # keys.append(word_split.encode("utf-8")) keys.append(word_split) # print(word_split) result = pd.DataFrame({"id": ids, "title": titles, "key": keys}, columns=['id', 'title', 'key']) return result
首先缩短文本长度。尽量减少hash 的权重分配。不然我确信你会失败。通过短文本匹配你可以适当调节汉明距离。不一定为3.
然后通过进行关键词匹配去算16进制的simhash 值。准确度在85%y以上
完整项目关注并点赞后可以跟我留言获取。