solr创建索引_Solr:创建拼写检查器

solr创建索引

在上一篇文章中,我谈到了Solr Spellchecker的工作原理,然后向您展示了其性能的一些测试结果。 现在,我们将看到另一种拼写检查方法。
与其他方法一样,此方法使用两步过程。 相当快速的“候选单词”选择,然后对这些单词评分。 我们将从Solr使用的方法中选择不同的方法并测试其性能。 我们的主要目标是修正的有效性,第二个方面是提高结果的速度。 考虑到我们正在获得结果的正确性,我们可以忍受稍慢的性能。
我们的策略是使用特殊的Lucene索引,并使用模糊查询对其进行查询以获取候选列表。 然后,我们将使用Python脚本对候选人进行排名(如果获得更好的结果,可以轻松地在Solr拼写检查器子类中对其进行转换)。

候选人选择

历史上,模糊查询一直被认为是性能较慢的查询,但是由于在1.4版本中已对其进行了优化,因此对于我们算法的第一部分来说,它们是一个不错的选择。 因此,这个想法将非常简单:我们将构建一个Lucene索引,其中每个文档都是一个字典单词。 当我们必须纠正一个拼写错误的单词时,我们将对该单词进行简单的模糊查询并获得结果列表。 结果将是与我们提供的单词相似的单词(即,编辑距离较小)。 我发现,大约有70名候选人可以使我们获得出色的成绩。
对于模糊查询,我们涵盖了所有的错字,因为正如我在上一篇文章中所说,大多数错字相对于正确的单词的编辑距离均为1。 但是,尽管这是人们在键入时最常见的错误,但还有其他类型的错误。

我们可以找到三种拼写错误[Kukich] :

  1. 印刷错误
  2. 认知错误
  3. 语音错误
当人们知道正确的拼写但在打字时却使运动协调失误时,就会出现打字错误。 认知错误是由于人的知识不足引起的。 最后,语音错误是认知错误的一种特殊情况,认知错误是指听起来正确但拼写错误的单词。 我们已经用模糊查询解决了印刷错误,但是我们也可以为语音错误做些事情。 Solr的分析包中有一个语音过滤器,其中除其他外,还具有双重语音识别算法。 以相同的方式执行模糊查询以查找相似的单词,我们可以为该单词的等效语音索引并对其执行模糊查询。 我们必须手动获取该单词的等效词(因为Lucene查询解析器不会分析模糊查询),并使用该单词构造一个模糊查询。

简而言之,对于候选选择,我们使用以下solr模式构建索引:

<fieldType name="spellcheck_text" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true"><analyzer type="index"><tokenizer class="solr.KeywordTokenizerFactory"/><filter class="solr.LowerCaseFilterFactory"/><filter class="solr.PhoneticFilterFactory" encoder="DoubleMetaphone" maxCodeLength="20" inject="false"/></analyzer></fieldType><field name="original_word" type="string" indexed="true" stored="true" multiValued="false"/><field name="analyzed_word" type="spellcheck_text" indexed="true" stored="true" multiValued="false"/><field name="freq" type="tfloat" stored="true" multiValued="false"/>
如您所见,analyzered_word字段包含单词的“音似”。 频率字段将在算法的下一阶段中使用。 它只是该术语在语言中的出现频率。 我们如何估计语言中一个单词的出现频率? 计算大文本语料库中单词的出现频率。 在这种情况下,术语的来源是维基百科,我们使用Solr的TermComponents来计算每个术语在维基百科中出现的次数。
但是维基百科是由会出错的普通人编写的! 我们如何才能将其视为“正确的字典”? 我们利用撰写维基百科的人们的“集体知识”。 这个从维基百科提取的术语词典有很多术语! 超过1.800.00,其中大多数甚至都不是单词。 维基百科中可能正确拼写了高频单词。 从大量的单词集构建字典并考虑最正确的单词的这种方法并不新鲜。 在[Cucerzan]中,他们使用相同的概念,但使用查询日志来构建字典。 可以看出Google的“您的意思是”使用了类似的概念 。
我们可以在这里添加一些优化。 我发现我们可以删除一些单词并获得良好的结果。 例如,我删除了频率为1的单词和以数字开头的单词。 我们可以根据其他条件继续删除单词,但是我们将这样保留。
因此,建立索引的过程很简单,我们通过Solr的TermsComponent从Wikipedia索引中提取所有术语以及频率,然后使用SolrJ在Solr中创建索引。

候选人排名

现在的候选人排名。 对于算法的第二阶段,我们将利用信息论,尤其是噪声信道模型 。 应用于这种情况的嘈杂通道假定人类知道一个单词的正确拼写,但是通道中的一些噪声引入了错误,结果我们得到了另一个拼写错误的单词。 我们直观地知道,在尝试键入“ house”时我们不太可能获得“ sarasa”,因此嘈杂的渠道模型引入了某种形式来确定错误的可能性。
例如,我们拼错了“ houze”,我们想知道哪一个是我们最想输入的单词。 为实现这一点,我们拥有大量可能的单词词典,但并非所有单词都具有相同的可能性。 我们希望获得打算输入的可能性最高的单词。 在数学中称为条件概率; 假设我们键入“ houze”,那么每个正确单词成为我们想要的单词的可能性有多高。 条件概率的表示法是:P('house'|'houze')表示给定“ houze”时“ house”的概率
这个问题可以从两个角度看待:我们可能认为最常见的词更有可能,例如,“ house”比“ hose”更有可能,因为前者是一个更常见的词。 另一方面,我们也凭直觉认为“房屋”比“光合作用”更有可能,因为两个词的差异很大。 这两个方面均由贝叶斯定理正式推论:
我们必须最大化这种可能性,并且只有一个参数:正确的候选单词(在所示情况下为“ house”)。
因此,拼写错误的单词的概率将是恒定的,我们对此不感兴趣。 公式简化为
为了给它增加更多的结构,科学家给这两个因素起了名字。 P('houze'|'house')因子是错误模型(或通道模型),并且与通道在尝试写入第二个单词时引入此特定拼写错误的可能性有关。 第二个术语P('house')称为语言模型,它使我们了解单词在语言中的普遍程度。
到目前为止,我仅介绍了该模型的数学方面。 现在我们必须提出这两个概率的具体模型。 对于语言模型,我们可以在文本语料库中使用术语的频率。 从经验上我发现,使用频率的对数比单独使用频率要好得多。 也许是因为我们要减少频繁项的权重,而不是减少频繁项的权重,而对数正是这样做的。
不仅存在一种构造渠道模型的方法。 已经提出了许多不同的想法。 我们将使用一个基于Damerau-Levenshtein距离的简单距离。 但是我也发现,第一阶段的模糊查询在找到候选者方面做得很好。 在某些数据集的一半以上的测试用例中,它首先给出了正确的单词。 因此,通道模型将是Damerau-Levenshtein距离和Lucene为模糊查询条件创建的得分的组合。

排名公式为:

我编写了一个小脚本(python),该脚本执行了之前所说的所有操作:

from urllib import urlopen
import doubleMethaphone
import levenshtain
import jsonserver = "http://benchmarks:8983/solr/testSpellMeta/"def spellWord(word, candidateNum = 70):#fuzzy + soundlikemetaphone = doubleMethaphone.dm(word)query = "original_word:%s~ OR analyzed_word:%s~" % (word, metaphone[0])if metaphone[1] != None:query = query + " OR analyzed_word:%s~" % metaphone[1]doc = urlopen(server + "select?rows=%d&wt=json&fl=*,score&omitHeader=true&q=%s" % (candidateNum, query)).read( )response = json.loads(doc)suggestions = response['response']['docs']if len(suggestions) > 0:#scorescores = [(sug['original_word'], scoreWord(sug, word)) for sug in suggestions]scores.sort(key=lambda candidate: candidate[1])return scoreselse:return []def scoreWord(suggestion, misspelled):distance = float(levenshtain.dameraulevenshtein(suggestion['original_word'], misspelled))if distance == 0:distance = 1000fuzzy = suggestion['score']logFreq = suggestion['freq']return distance/(fuzzy*logFreq)
在前面的清单中,我必须做一些说明。 在第2行和第3行中,我们使用Levenshtein距离和变音位算法的第三方库。 在第8行中,我们正在收集70个候选人的列表。 该特定数字是凭经验找到的。 候选数越高,算法就越慢,而算法越少,则效果越差。 我们还将第30行的候选单词中的拼写错误的单词排除在外。由于我们使用Wikipedia作为来源,因此通常会在字典中找到拼写错误的单词。 因此,如果Leveshtain距离为0(相同的单词),我们将其距离加1000。

测验

我使用此算法进行了一些测试。 第一个将使用Peter Norvig在他的文章中使用的数据集。 我在大约80%的情况下都在第一个位置找到了该单词的正确建议!!! 那是一个非常好的结果。 具有相同数据集(但算法和训练集不同)的Norvig获得了67%

现在,让我们重复上一篇文章的一些测试,以查看改进。 在下表中,我向您显示结果。

测试集 %Solr %新 Solr时间[秒] 新时间[秒] 改善 时间损失
FAWTHROP1DAT.643 45,61% 81,91% 31,50 74,19 79,58% 135,55%
batch0.tab 28,70% 56,34% 21,95 47,05 96,30% 114,34%
SHEFFIELDDAT.643 60,42% 86,24% 19,29 35,12 42,75% 82,06%

我们可以看到,我们在改正效果方面得到了很好的改进,但是大约需要两倍的时间。

未来的工作

我们如何改进此拼写检查器。 好了,研究候选人名单后,可以发现其中通常包含正确单词(95%的次数)。 因此,我们所有的努力都应旨在改进评分算法。
我们有许多改进渠道模型的方法; 几篇论文表明,根据语言统计数据计算更复杂的距离,对不同的字母转换加权,可以为我们提供更好的度量。 例如,我们知道写“ houpe”比写“ houze”的可能性要小。
对于语言模型,可以通过向单词添加更多上下文来获得重大改进。 例如,如果我们拼错了“ nouse”,很难说出正确的单词是“ house”或“ mouse”。 但是,如果我们添加更多的单词“画我的鼻子”,则很明显,我们所寻找的单词是“房子”(除非您有与啮齿动物有关的奇怪习惯)。 这些也称为ngram(在这种情况下是单词,而不是字母)。 Google提供了大量ngram,可以下载它们的频率。
最后但并非最不重要的一点是,可以通过用Java编写脚本来提高性能。 该算法的一部分在python中。
再见!
作为对所有感兴趣的人的更新,Robert Muir在“ Solr用户”列表中告诉我 ,有一个新的拼写检查器DirectSpellChecker,它当时在后备箱中,现在应该是Solr 3.1的一部分。 它使用与本条目中介绍的技术类似的技术,而不会降低性能。
参考资料
[Kukich] Karen Kukich –自动校正文本中的单词的技术– ACM计算调查–第24卷,第4期,1992年12月
[Cucerzan] S. Cucerzan和E. Brill拼写校正是一个利用Web用户集体知识的迭代过程。 2004年7月
Peter Norvig –如何编写拼写校正器

参考: emmaespina博客上的JCG合作伙伴 Emmanuel Espina 用Solr创建了拼写检查 工具 。


翻译自: https://www.javacodegeeks.com/2012/06/solr-creating-spellchecker.html

solr创建索引

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/355250.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5000元性价比高的笔记本_2018性价比笔记本电脑品牌推荐 5000左右笔记本性价比推荐...

对于年年都出新款的电子产品&#xff0c;购买者们每年都经历一回挑花眼的时刻&#xff0c;那2018有什么笔记本比较好呢?宏碁暗影骑士3参考价&#xff1a;5099元内存容量&#xff1a;8G  显存容量&#xff1a;2G  硬盘容量&#xff1a;128G1T显卡型号&#xff1a;GTX1050(高…

Hibernate模糊查询

Hibernate模糊查询1.不使用hql DetachedCriteria criteria DetachedCriteria.forClass(User.class);if (StringUtils.isNotEmpty(yh)) {criteria.add(Restrictions.or(Restrictions.eq("yhid", yh),Restrictions.like("yhxm", yh, MatchMode.ANYWHERE)))…

带有Javaslang的Java 8中的功能数据结构

Java 8的lambda&#xff08;λ&#xff09;使我们能够创建出色的API。 它们令人难以置信地提高了语言的表达能力。 Javaslang利用lambda来基于功能模式创建各种新功能。 其中之一是功能性集合库&#xff0c;旨在替代Java的标准集合。 &#xff08;这只是鸟瞰图&#xff0c;您…

丰田pcs可以关闭吗_丰田车必备的配置有哪些是在亚洲龙上体现了?

亚洲龙基于丰田TNGA架构下的GA-K平台打造而来&#xff0c;与雷克萨斯ES一致&#xff0c;先期推出搭载2.5L自然吸气发动机以及2.5L混合系统的车型。作为一汽丰田的全新旗舰轿车&#xff0c;亚洲龙主销车型配备丰田TSS规避碰撞辅助套装&#xff0c;英文全拼为 “Toyota Safety Se…

[NOIP2014]飞扬的小鸟

思路{ 对于每一列&#xff0c;小鸟或下落&#xff0c;或上升。那我们很容易想到对应的背包问题&#xff01; 按照完全背包的思想更新上升部分&#xff0c;01背包的方法更新下降部分。 撞到柱子了(aluba。。。。。。aluba.。。。。。)不慌&#xff0c;只需把它设为不可打即可&am…

2020 dns排名_2020年新版全球/全国各地ISP的DNS服务器地址表

【第一】国内外知名的公共DNS服务器(排列不分先后)&#xff1a;腾讯公共DNS(119.29.29.29、182.254.116.116)阿里公共DNS(223.5.5.5、223.6.6.6)百度公共DNS(180.76.76.76)360安全DNS(123.125.81.6)Google(8.8.8.8、8.8.4.4)114DNS(114.114.114.114、114.114.115.115)OpenDNS(2…

Spring MVC 登录拦截器

Spring MVC 登录拦截器1.编写拦截器 package interceptor;import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRespons…

bzoj1556 (DP)

bzoj 1556 点这里打开题目 题目是求 a^2 求和&#xff1b; 原问题可以转化为&#xff1a;两个人在玩这个东西&#xff0c;问这两个人弄出来的序列相同的有多少种情况&#xff0c;操作方式不同即为一种不同的情况。 就这个问题&#xff0c;参考大佬的DP思想。 DP[t][i][j] 分别…

帆软参数设置_数据分析软件之FineReport教程:[5]参数界面JS(全)

在用报表工具设计报表时&#xff0c;使用参数控件时&#xff0c;有时我们希望部分参数控件在没满足条件时不显示&#xff0c;满足条件后再显示&#xff0c;接下来我就来教教大家怎么做&#xff01;表格软件如何根据条件控制参数控件是否显示一&#xff1a;问题描述在使用参数控…

wurfl_比较OpenDDR与WURFL

wurfl量身定制的Web内容通常受益于定制&#xff0c;以考虑多种因素&#xff0c;例如屏幕大小&#xff0c;标记语言支持和图像格式支持。 此类信息存储在“设备描述存储库”&#xff08;DDR&#xff09;中。 WURFL和OpenDDR项目都提供了访问DDR的API&#xff0c;以简化并促进适应…

ssm 静态资源处理器

ssm 静态资源处理器<!-- 静态资源处理--><mvc:default-servlet-handler/>

极简单的方式序列化sqlalchemy结果集为JSON

继承 json.JSONEncoder 实现一个针对sqlalchemy返回类型的处理方式。 sqlalchemy的返回类型有大都有两种&#xff0c;一种是Model对象&#xff0c;一种是Query集合&#xff08;只查询部分字段&#xff09;。 针对这两种返回结果&#xff0c;都是来自同一中类型 sqlalchemy.orm…

easymock 图片_数据模拟神器 easy-mock 正式开源

开源公告由大搜车无线团队出品的 easy-mock 在线数据模拟服务上线至今已经有几个月时间了&#xff0c;近期网站刚更新了焕然一新的 2.0 版本&#xff0c;与此同时&#xff0c;我们还带来一个更重磅的消息&#xff1a;今天正式将整个服务的代码在 github 开源(github.com/easy-m…

在自定义Java 9映像上运行Eclipse Neon

我已经开始修改自定义Java二进制运行时映像文件。 映像文件是打包为运行时平台的模块的配置。 基本上&#xff0c;默认映像包含组成Java运行时的所有内容。 自定义图像可以包含该图像的一些子集。 例如&#xff0c;我创建了一个仅包含“ compact 3”概要文件的映像&#xff0c…

ssm异常捕获和处理

ssm异常捕获和处理package exception;import lombok.extern.slf4j.Slf4j; import org.hibernate.HibernateException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ResponseBody; import entity.vo.Res…

载波聚合或双连接的方式进行_处理载波聚合及双连接的装置及方法与流程

本发明涉及一种用于无线通信系统的通信装置及方法&#xff0c;尤其涉及一种处理载波聚合及双连接的装置及方法。背景技术&#xff1a;通过第三代合作伙伴计划(third generation partnership project&#xff0c;3GPP)发起的新无线(new radio&#xff0c;NR)系统包含有新无线接口…

拼接xml

拼接xml/*** description 拼接xml* param list 用户信息* return java.lang.String 拼接完成的xml* author zhaohuaqing* date 2021/6/21 15:39* version 1.0*/public static String getUserXMl(List<User> list,int totalNumber,int start){StringBuilder sb new Stri…

unity游戏开发毕设_一个程序小白的unity 2D游戏开发的反思与经验

学游戏设计的码农&#xff0c;中传大三在校生&#xff0c;代码水平目前还在进阶中。这个学期和美术一起进行了一次不成熟的磕磕绊绊的游戏开发。踩了很多坑&#xff0c;就当是毕设前的预热吧&#xff0c;做个总结&#xff0c;希望毕设不会再犯这些错误。因为整个本科阶段做的或…

Asp.Net MVC项目通过Git同步到新开发设备上后无法作为网站启动

右键项目名->属性->启动项目->单启动项目&#xff0c;在下拉框中选择你的网站主项目就可以了。&#xff08;由于用的英文版&#xff0c;所以翻译的内容可能略有差异&#xff09;转载于:https://www.cnblogs.com/chenyangsocool/p/7127469.html

前端参数编码

前端参数编码//对参数编码 function paramsCode(){var params ;$(.param).each(function () {var name $(this).attr("name");if ($(this).attr("type") "radio"){params (&name encodeStr($("input[name"name"]:checke…