写在前面的话
偶尔出来放个比较大的招啦。这是我自己目前研究领域的一分部,基于k-gram hash 查重检测文档的相似性这个技术已经是相当成熟的。这个是我这几个月的工作方向中最小的一个模块之一,现在和大家稍微稍微稍微的分享一下我自己的感悟和心得。
我比较菜,也比较水,可能很多东西没有前辈们掌握的更加透彻,参悟的更加明白,欢迎各位大神给我提提意见。
前天改完作业,我突然发现了好几份相似的代码,逻辑思维和代码风格都全部一样。熊孩子们又没有好好做作业,我就想这两天写个自动化检测的剽窃的脚本,把抄作业的熊孩子找出来。哈哈哈,大家不用担心,你只要不要让我觉得抄的很过分,我会考虑放过你的。只不过看着这么好一堆的ground truth 在我面前,这好可以检测我写的代码的正确性,有什么地方可以改进的。还有一点,请各位同学不!要!抄!作!业!因为我是过目不忘的,请不要往枪口上撞。
我的标题是不是起的很奇怪,我自己也觉得很奇怪。我想了半天才想出来这么个名字,首先它是基于k-gram 的,有个时候我们看某些文献的时候,你可能会发现人家叫n-gram,这两个东西其实就是相同的。我们基于 k-gram hash 算法主要的目的就是来提取我们文档或者是代码的特征值,我们根据这些特征值来找到和该文档相似的其他文档,所以我们可以用这种技术来判断软件的相似性(similarity)以及用来查重(clone),剽窃(plagiarism)检测。
总的来说,这个算法的效果还是很不错的。
1.背景知识
首先我们这篇文章的主要讲的是一个03年就提出的技术。我们主要参考的是这篇文章:Winnowing: Local Algorithms for Document Fingerprinting 你可以在这个地方下载到这篇文章。
1.1winnowing
winnowing 这个词用英语翻译过来是“扬场”的意思,就是用风过滤筛选种子的意思。在一大堆的东西中我们只留下对我们有价值的东西(如饱满的种子),然后让风吹去没有价值的东西比如我们的麦秆之类的。
用我们中国话比较文绉绉一点的就是:取其精华去其糟粕! 保留对我们有用的,丢弃那些干扰项。
就行很有农情意味的 : 用簸箕挑选种子去沙的道理是一样的。
我是不是话太多了。
绝对良心博客!
1.2 k-gram model
这个模型在做NLP自然语言处理的时候经常能够用得到,做这个方向的同学应该对这个概念是比较清楚的。
K-gram/ n-gram 英文翻译过来就叫做n元语法模型
参见维基百科:
n-gram English version
n-gram 中文版
我们其实在密码学中接触过这个概念,Playfair Cipher加密算法就是使用了这样一种分类的概念。
k-gram 就是将一个连续的文本进行切割,每一个部分的长度都是k。当长度为1,2, 3时 分别对应的名称叫做 一元语法(1-gram unigram), 二元语法(bigram),三元语法(trigram).
为了形象的说明这个问题,我们来举一个简单的例子。有一个简单的文档 叫做A,由字母yabbadabbadoo组成:
我们给它们都编一个号:
0 1 2 3 4 5 6 7 8 9 10 11 12
A : y a b b a d a b b a d o o
这个时候我们在A这个文档上取一个大小为3的滑动窗口,就得到了一个3-gram 的集合:
A : yab abb bba dad ada dab abb bba bad ado doo
我们把这个集合中的元素都称为shingle.
下面我们再来看另一个文档C,文档C由下面的这些字符组成的:doobeedoobeedoo
0 1 2 3 4 5 6 7 8 9 10 11 12