算法思想:将文章映射到一个n维向量v[],将向量的值二值化为0或1 。用向量a和向量b表示两篇文章,a和b同时为1的位数记为 S1(对为1的位求交集),a和b至少一个为1的位数记为S2(对为1的位求并集).相似度即为S1/S2. 重点在于如何将文章用一个向量表示。
主要计算流程如下:
为了便于存储,将448维的0-1向量用32个汉字表示。
Step1 构造汉明码的编码集
编码的字符集为2^14=16384个汉字,每个汉字代表0-16383中的1个数。
初始化编码集的算法如下:
Step2 将文章表示成向量
用ik将文章分词然后对每个词求hash值,在用hash值对448取模,即可将每个词映射到448位数组中的一个元素,将映射到的那一个元素置为1。
其中第170行是调用ik进行分词。
随机采样5000篇文章,1000个字平均会散列到448位中的200位左右。也就是说1000字左右的文章对应的448位向量会有大概200位非0。
Step3 将向量转化为汉明码以便存储
将448位0-1数组映射到32个汉字表示的汉明码的算法如下
其中 codes[number]表示上一步得到的汉字字符集中第number个汉字。
Spark streaming会实时计算汉明码,并将汉明码保存到数据库,供后面查询的时候计算相似和聚类使用。
Step4 将汉明码解码为向量
计算相似先要将汉明码解码为向量。
其中第106行表示根据汉字字符c 获取到这个汉字代表的数值。
Step5 计算相似度
有了解码后的向量,就可以计算相似度了:
首先求两个向量非0位的交集,记为intersection.
然后求两个向量非0位的并集,记为union.
最后求得相似度:
备注:本文写于2016年,发表在网易博客,因网易博客停止运营,将文章转移到云栖社区。