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,一经查实,立即删除!

相关文章

带有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…

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

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

如何以访客模式访问_重新访问了访客模式

如何以访客模式访问访客模式是面向对象设计中最被高估但又被低估的模式之一。 高估了它&#xff0c;因为它通常选择得太快了&#xff08; 可能是由建筑宇航员选择的 &#xff09;&#xff0c;然后以错误的方式添加后&#xff0c;使原本非常简单的设计肿了。 如果您不遵循教科书…

【数据挖掘导论】——数据质量

数据质量数据挖掘使用的数据一般是为其它用途收集或者收集的时候还没有明白目的。因此数据经常不能在数据的源头控制质量。为了避免数据质量的问题&#xff0c;所以数据挖掘着眼于两个方面&#xff1a;数据质量问题的检測和纠正&#xff08;数据清理&#xff09;&#xff1b;使…

Spark学习笔记(7)---Spark SQL学习笔记

Spark SQL学习笔记 Spark SQL学习笔记设计到很多代码操作&#xff0c;所以就放在github, https://github.com/yangtong123/RoadOfStudySpark/blob/master/src/com/spark/sql/Readme.md其中包括了对Spark2.0的新特性的介绍&#xff0c;包括SparkSession, DataSet等转载于:https:…

性能实战(一) --- clock_gettime造成系统整体cpu过高定位过程

问题背景 有一台linux服务器测试环境cpu经常到达80%,造成系统卡顿,部分功能不可用. 分析步骤 1.使用perf制作cpu火焰图 通过制作cpu火焰图,发现很多进程都存在大量的clock_gettime系统调用. 2. 使用bcc工具funclatency`进一步查看clock_gettime的调用次数 # /usr/share/bc…

玩透个人所得税

每次拿着工资条的时候&#xff0c;总有个代扣个税这么一项&#xff0c;不知道你们有没有想过这到底是怎样计算得出来的。下面我就给你们普及一下这个知识。 个人所得税 个人所得税是对个人&#xff08;自然人&#xff09;取得的各项所得征收的一种所得税。个人所得税…

哔哩哔哩swot分析_哔哩哔哩2020校园招聘游戏运营笔试真题

在前不久《英雄联盟》S9世界大赛总决赛上&#xff0c;中国FPX战队以3&#xff1a;0横扫欧洲G2最终夺得S9世界冠军&#xff0c;国内玩家万分激动。总决赛刚结束不久&#xff0c;B站以8亿元价格拍得《英雄联盟》全球总决赛中国地区三年独家直播版权。作为主打年轻人群体起家的产品…

P2280 [HNOI2003]激光炸弹

P2280 [HNOI2003]激光炸弹 题目描述 输入输出格式 输入格式&#xff1a;输入文件名为input.txt 输入文件的第一行为正整数n和正整数R&#xff0c;接下来的n行每行有3个正整数&#xff0c;分别表示 xi&#xff0c;yi &#xff0c;vi 。 输出格式&#xff1a;输出文件名为output.…

在Spring Boot中使用配置元数据来配置您的配置

Spring Boot 1.3.0中发布了许多更新&#xff0c;但是其中一个对我很突出&#xff0c;因为我以前并不了解此更新&#xff0c;它的状态使其成为一项真正有用的功能&#xff08;不幸的是&#xff0c;撰写本文时仅在Spring Boot中可用&#xff09;这个&#xff09;。 我正在谈论配置…

jsp实现数据禁用和只读

jsp实现数据禁用和只读

java事务不生效场景_讲一下,我最近帮忙面试的几个“高级”JAVA,真的心累

最近看了很多简历&#xff0c;很多候选人年限不小&#xff0c;但是想着也不能通过简历就直接否定一个人&#xff0c;何况现在大环境越来 越难&#xff0c;大家找工作也不容易&#xff0c;于是就打算见一见。在沟通中发现&#xff0c;由于年限不小&#xff0c;他们的定位基本都是…

antlr 教程_ANTLR教程– Hello Word

antlr 教程Antlr代表另一种语言识别工具。 该工具能够为任何计算机语言生成编译器或解释器。 除了明显的用途&#xff08;例如需要解析一种真正的“大型”编程语言&#xff0c;例如Java&#xff0c;PHP或SQL&#xff09;外&#xff0c;它还可以帮助执行更小&#xff0c;更常见的…

Java中使用ArrayList的10个示例–教程

Java中的ArrayList是HashMap之后最常用的集合类。 Java ArrayList表示一个可自动调整大小的数组&#xff0c;并用于代替数组。 由于创建数组后我们无法修改数组的大小&#xff0c;因此我们更喜欢在Java中使用ArrayList&#xff0c;一旦数组满了&#xff0c;它就会自动调整大小。…

[SoapUI] How to create a random UUID in each Request's Headers

${java.util.UUID.randomUUID()} is OK 转载于:https://www.cnblogs.com/MasterMonkInTemple/p/7159589.html

设置Tomcat管理员用户名和密码

http://dove19900520.iteye.com/blog/1774980 今天tomcat出点问题&#xff0c;然后我就想进入tomcat manager看看&#xff0c;结果怎么输入密码都不行&#xff0c;后来网上查了查才找到配置管理员用户名和密码的正确方式&#xff0c;在此记录一下&#xff1a; 要想配置管理员用…

怎么把两个div一左一右放

怎么把两个div一左一右放1.代码 <% page contentType"text/html;charsetUTF-8" language"java" %> <html> <head><title>Title</title> </head> <body> <div style"width:150px;height:50px;margin:0;…

为Java + STANDARD值引入Cucumber

作为软件开发人员&#xff0c;我们都有最喜欢的工具来使我们成功。 许多人在上手时就很适合这份工作&#xff0c;但很快就不见了。 其他人则需要太多的设置和培训才能“将脚趾浸入水中”&#xff0c;只是为了找出自己是否是正确的工具即可。 Cucumber JVM是一个测试框架&#…