Lucene暴走之巧用内存倒排索引高效识别垃圾数据

识别垃圾数据,在一些大数据项目中的ETL清洗时,非常常见,比如通过关键词 (1)过滤垃圾邮件 (2)识别yellow网站 (3)筛选海量简历招聘信息 (4)智能机器人问答测试 ........ 各个公司的业务规则都不一样,那么识别的算法和算法也不一样,这里提供一种思路,来高效快速的根据关键词规则识别垃圾数据。 下面看下需求: 业务定义一些主关键词若干少则几百个,多则几千个上万个,例如:

Java代码

  1. 公司
  2. 机车厂
  3. 化纤厂
  4. 建设局
  5. 实业集团
  6. 中心店
  7. 桑拿中心
  8. 托管中心

然后又定义一些辅助关键词若干:

Java代码

  1. 原告
  2. 被告
  3. 委托代理人
  4. 当事人
  5. 申请人
  6. 上诉人

ok,关键词有了,下面看下业务规则 , 规定如下: 任意辅助关键词组合主关键词都命中的情况下,并且词组间距不大于20者,即为合法数据。 嗯,没听懂?,那么来看个例子,一段文本如下:

Java代码

  1. 上诉人北京金建出租汽车有限公司因机动车x通事故责任纠纷一案

使用IK细粒度分词后可能是这样的:

Java代码

  1. 上诉人|上诉|人|北京|金|建出|出租汽车|出租|汽车|有限公司|有限|有|限|公司|因|机动车|机动|车|x通事故|x通|通事|事故责任|事故|责任|纠纷|一案|

根据规则,辅助词库与主词库都命中,而且中间的词组间距不超过20的,为合法数据, 本例子中: 辅助关键词:上诉人 主关键词: 公司 都出现,中间词组是12个,所以符合业务规则,即为合法数据, 假设,改变原来的文本的公司为集团,再次测试:

Java代码

  1. 上诉人北京金建出租汽车有限集团因机动车x通事故责任纠纷一案

使用IK细粒度分词后可能是这样的:

Java代码

  1. 上诉人|上诉|人|北京|金|建出|出租汽车|出租|汽车|有限集团|有限|有|限|集团|因|机动车|机动|车|x通事故|x通|通事|事故责任|事故|责任|纠纷|一案|

这次因为辅助关键词库命中了,但是主关键词库没有命中,所以会被当成垃圾数据。 上面是帮助理解业务的一个例子,下面再分析下,性能问题,假设主关键词有500个,辅助关键词有10个,那么任意 两两组合的可能就是500*10=5000个规则条件,也就是意味着需要最坏情况下,需要匹配5000次才能识别一篇垃圾数据,当然如果你参与识别垃圾的文本不是一个字段,而是二个字段,一个是标题,一个是内容,那么最后真正的匹配次数是5000*2=10000词匹配,如果再加上距离条件,那么查询的复杂度将会大幅度增加,这个时候,如果我们使用正则匹配 效率可想而知,使用正则每次全文扫描定位,耗时非常之慢,这时候我们假设有一种快捷的hash算法,来提升性能,毫无疑问,类似的倒排索引将会是解决这种问题的神器。 因为只需要构建一次临时索引,不落地磁盘,不与IO打交道,仅仅在内存和cpu之间参与计算匹配,而且规则方式非常灵活,可以有更多的规则制定进来,特别是关键词匹配这块,lucene索引非常完美的解决了这个问题。当然如此这种计算,非常耗CPU,对内存的占用不是非常高,因为一条数据,处理完之后,他占用的资源,会被释放。 在线情况下:平均几十毫秒左右就能识别一条数据,已经接近实时了 离线情况下:在集成到hadoop或者Spark这种分布式的集群里面,也是非常给力的,因为通常情况下spark和hadoop比较耗IO和磁盘而加入这种运算将会大大提升集群的资源使用效率。 本项目只是给出了一个根据关键词识别的例子,这个项目拿到你们本地也许并不能立刻使用,但是相似的业务,但是它提供了一种思路,大部分情况下,改动少许代码,即可适应大部分类似的业务。 核心代码如下:

Java代码

  1. package com.anytrust.algo;
  2. import com.anytrust.model.MonitorType;
  3. import com.anytrust.tools.DictTools;
  4. import org.apache.lucene.index.memory.MemoryIndex;
  5. import org.apache.lucene.queryparser.classic.QueryParser;
  6. import org.apache.lucene.search.BooleanQuery;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import org.wltea.analyzer.lucene.IKAnalyzer;
  10. /**
  11. * Created by qindongliang on 2016/1/7.
  12. * 根据规则识别是否为垃圾数据
  13. */
  14. public class CheckOneAlgo {
  15. //IK中文分词器
  16. IKAnalyzer analyzer=new IKAnalyzer(false);
  17. //内存索引处理
  18. MemoryIndex index = new MemoryIndex();
  19. static {
  20. //设置Lucene的boolean query条件数最大支持个数
  21. BooleanQuery.setMaxClauseCount(10000);
  22. }
  23. static Logger logger= LoggerFactory.getLogger(CheckOneAlgo.class);
  24. /**构建查询query
  25. * @param type 根据类型构建
  26. * */
  27. private String buildQuery(MonitorType type){
  28. StringBuffer sb =new StringBuffer("(");
  29. for(String kw: DictTools.main_kws){//遍历主词库
  30. switch (type) {
  31. case LITIGATION://代表文书 0105
  32. for (String hkw : DictTools.assist_kws) { //遍历辅助词库
  33. sb.append("tc:\"").append(hkw + kw).append("\"~20 ");
  34. }
  35. break;
  36. case ANNOUNCEMENT://公告 0104
  37. sb.append("tc:\"").append(kw).append("\" ");
  38. break;
  39. default:
  40. logger.error("未知类型:{}",type);
  41. break;
  42. }
  43. }
  44. sb.append(" ) ");
  45. return sb.toString();
  46. }
  47. /***
  48. * 对一段文本执行垃圾数据识别功能
  49. * 返回true说明是有效数据
  50. * 返回false说明是垃圾数据
  51. * @param text 监测的文本
  52. * @return
  53. */
  54. public boolean checkDoc(String text,MonitorType type){
  55. String query=buildQuery(type);
  56. QueryParser parser = new QueryParser("", analyzer);
  57. index.addField("tc", text, analyzer);
  58. try {
  59. float score = index.search(parser.parse(query));
  60. if(score > 0.0f){
  61. return true;//正确数据
  62. }else{
  63. return false;//垃圾数据
  64. }
  65. }catch (Exception e){
  66. logger.error("识别垃圾数据异常!",e);
  67. }finally {
  68. index.reset();//重置index引擎,服复用类对象
  69. }
  70. return false;
  71. }
  72. }

有些关键词在Iteye博客会屏蔽,建议直接到github看: Github地址:https://github.com/qindongliang/lucene-garbage-check

原文发布于微信公众号 - 我是攻城师(woshigcs)

原文发表时间:2016-02-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏牛客网

滴滴面试

4035
来自专栏恰童鞋骚年

自己动手写游戏:Flappy Bird

START:最近闲来无事,看了看一下《C#开发Flappy Bird游戏》的教程,自己也试着做了一下,实现了一个超级简单版(十分简陋)的Flappy Bird...

1362
来自专栏数据科学与人工智能

【Python环境】Python数据挖掘兵器谱

Python正渐渐成为很多人工作中的第一辅助脚本语言,在文本处理,科学计算,机器学习和数据挖掘领域,有很多很多优秀的Python工具包可供使用,所以作为Pyth...

2316
来自专栏PHP在线

编程命名看编程质量问题

很多人以为提高编码质量,需要很多激动人心的创新,需要明显的飞跃,这也许对,但我个人感觉项目中提高编码质量是个水磨功夫,要一步步积累,方法论大多时候帮助不大。 这...

3434
来自专栏灯塔大数据

每周学点大数据 | No.44 MapReduce 图算法概述

No.43期 MapReduce 图算法概述 Mr. 王:MapReduce 作为一种经典的并行编程框架,可以用于解决很多问题,包括一些图论问题。在客观世界...

3765
来自专栏Python中文社区

Python数据分析之基情的择天记

專 欄 ❈ 罗罗攀,Python中文社区专栏作者 专栏地址: http://www.jianshu.com/u/9104ebf5e177 ❈ 人一生都可能无...

2246
来自专栏诸葛青云的专栏

为什么C++比C要麻烦?程序员这样回答,终于知道他为什么单身了

同样衍生出来的还有一个小故事:情人节,有人看到C一个人喝酒,便问:你的好哥们C++、Java、Python他们呢?

910
来自专栏Crossin的编程教室

【每周一坑】三国演义中谁的存在感最强 +【解答】暴力计算圆周率

自然语言处理(NLP)是人工智能的一个重要领域。在对中文做自然语言处理的时候,一个很基础的操作就是分词:因为中文不像英语有现成的单词划分,需要将汉字序列切分成一...

842
来自专栏数据科学与人工智能

【数据挖掘】图数据挖掘

互联网发展至今,数据规模越来越大,数据结构越来越复杂,而且对系统的需求越来越高。如果学习过数据结构,那么都知道图是放在最后一个结构,当你学习了图,那么应该感知到...

3268
来自专栏牛客网

网申 网易游戏 测试开发 一面凉经

2400

扫码关注云+社区

领取腾讯云代金券