成功的匹配两篇文章的相似度,准确率接近100%
2017-06-17 00:00
246 查看
开始
最近写了很多MySQL全文索引的知识,是因为工作中使用到了它。由于效率以及准确率的问题,我维护的语篇查重系统一直受到编辑小伙伴的吐槽,在近一个月的苦思冥想中,终于想到了不错的解决办法,初步测试效果理想。问题叙述
查重系统顾名思义就是将编辑们输入的文章与已经录入的文章进行匹配,如果有重复的再决定文章是否进行使用。碰到的问题是,线上数据量80万左右,每条数据都是由一套试卷组成,里面包含各种符号,中文英文等大量的数据。我们就要在这样的数据源里面寻找是否有已经使用过的文章。系统在我接手之前使用的MySQL全文索引,而MySQL全文索引的机制也就决定了这个系统的准确率一定会饱受诟病,这就是我要解决的问题。具体机制可查看其他翻译篇。
思路变化
首先想到的是去查看除了MySQL全文索引之外的解决方案,例如Sphinx、SimHash等。但是这些都被否定了。Sphinx搜索引擎性能可能会比较高,但是准确率不高。因为MySQL的全文索引与Sphinx是类似的,适合使用关键字搜索,而不适合整片文章进行比对。SimHash算法是我们领导告诉我的,我看了一下,感觉该算法入门有点难(数学比较渣),而且基于文章生成的hash值,再通过海明距离判断相似度并不太适合我们的系统,因为hash值是整篇文章的,但是编辑可能输入其中的某一个段落,这样海明距离比较大,不会被视为相似。(对Sphinx和SimHash的理解较浅,有错误请指正)。正在我纠结的时候,结识了公司的实习生,聊天聊到论文查重,我突然意识到公司需要的可能正是像论文查重这样基于段落或者句子的对比方式。 于是开始动手实现基于短句的查重方式。
还是利用MySQL全文索引的相似度计算系统,我想要的只是让其分词技术不是按单词分,而是按句子进行分离。
首先想到的是添加专用的字符集和校对规则,将空格视为单词的一部分,这样可以利用MySQL全文索引天然的按句分词了。但是这个方法有一个问题就是需要重启MySQL,经过与运维小伙伴的沟通,得知重启数据库还是比较棘手的,所以pass掉了这个方案。
第二个方案就是通过php应用将单词组合成句,下划线在MySQL内置的全文引擎中会被视为单词的一部分。
删除原数据表的全文索引,创建一个索引表,包含一个主键id和一个全文索引列。全文索引列存储的是一个文章,文章为按下划线组成的句子组成,例如:’i_love_you,mysql_database',那么辅助索引表就会存储形如‘i_love_you'和’mysql_database'的列。通过实验发现效果不行,因为试卷的文章结构特别乱,导致分词长度比较杂乱,中文和标点处理的也不是特别理想,有的索引特长,即使方案可行效率也不会特别高。
最终想出了现在使用的方案。思路与3类似,但是优化了对特殊字符的替换,核心的变化是将拆分过滤好的句子生成hash码,拼接在一起存储在新表的全文索引列,例如现在的全文索引列的内容是‘1982398349,2398203483’,MySQL的辅助索引表里面的内容就是‘1982398349’和‘2398203483’,每个hash码代表一句话,长度基本固定,对查询速率有很大提高。
结果
通过测试收到的成效不错,本地20万数据量,查询秒级,基本没有出现所查篇章在排名第二的情况。这个解决思路主要是建立在对全文索引的理解之上。
相关代码
// 普通hash函数,函数形式并不是特别关键,碰撞几率越小越好 function myHash($str) { $md5 = substr(md5($str), 0, 8); $seed = 31; $hash = 0; for($i = 0; $i < 8; $i++){ $hash = $hash * $seed + ord($md5{$i}); } return $hash & 0x7FFFFFFF; }
还有影响比较大的是html标签,字母大小写,html实体,转义字符,空格的个数等,比如html实体' ',这里面的分号会影响分词,而数据库存入的数据可能会转实体之后的数据,如果不进行过滤同一句话的hash值也不同。可以用php的stripslashes,html_entity_decode,strip_tags,str_replace等函数进行处理,目的是尽量让字符串简单,保证同一句话的hash值相同。
相关文章推荐
- 两篇关于python中的模式匹配和python匹配中文的文章
- 两篇文章的相似度比较
- 如何比较两篇文章的相似度
- 两篇文章相似度:TF-IDF与余弦相似性的应用
- 两篇文章相似度:TF-IDF与余弦相似性的应用
- [将小白进行到底] 如何比较两篇文章的相似度
- 计算两篇文章相似度代码
- 最终敲定两篇文章,开始用心研读和翻译。希望一路顺利。
- 家乐福,该不该抵制??兼谈韩寒和Acosta的两篇文章
- MyEclipse快捷键两篇文章
- 搭建git for windows服务器(100%可以成功)
- 搭建git for windows服务器(100%可以成功)【转】
- 两篇破解无线路由的文章
- 发现两篇不错的文章在这里把地址收藏一下
- 有感于.net社区挺唐骏的作假的文章,诚实是美德,你们可以做假发财成功,但请不要批评,嘲笑他人诚实贫穷
- Neural Relation Extraction(神经关系抽取)的两篇文章
- 两篇关于论文格式等问题的文章
- android 线程池两篇文章 。后期添加自己见解
- CNN两篇好文章
- Redis做消息队列文章两篇 的地址