如何更正用户输入(类似于谷歌“你的意思是啥?”)
Posted
技术标签:
【中文标题】如何更正用户输入(类似于谷歌“你的意思是啥?”)【英文标题】:How to correct the user input (Kind of google "did you mean?")如何更正用户输入(类似于谷歌“你的意思是什么?”) 【发布时间】:2010-11-20 01:33:16 【问题描述】:我有以下要求:-
我有很多(比如 100 万个)值(名称)。 用户将键入一个搜索字符串。
我不希望用户正确拼写名称。
所以,我想做一种谷歌“你的意思是”。这将列出我的数据存储中的所有可能值。有一个类似但不相同的问题here。这没有回答我的问题。
我的问题:- 1) 我认为不建议将这些数据存储在 RDBMS 中。因为那样我就不会对 SQL 查询进行过滤。而且我必须进行全表扫描。那么,在这种情况下应该如何存储数据?
2) 第二个问题同this。但是,只是为了我的问题的完整性:我如何搜索大型数据集? 假设数据集中有一个名字 Franky。 如果用户键入为 Phranky,我如何匹配 Franky?我必须遍历所有名称吗?
我遇到了Levenshtein Distance,这将是一种查找可能字符串的好方法。但同样,我的问题是我是否必须对数据存储中的所有 100 万个值进行操作?
3) 我知道,Google 通过观察用户行为来做到这一点。但我想在不观察用户行为的情况下做到这一点,即使用我还不知道的距离算法。因为前一种方法需要大量搜索才能开始!
4) 正如Kirk Broadhurst 在回答below 中指出的那样,有两种可能的情况:-
用户输入错误的单词(编辑 距离算法) 用户不认识单词并猜测 (语音匹配算法)我对这两个都感兴趣。它们实际上是两个不同的东西。例如Sean 和 Shawn 听起来一样,但编辑距离为 3 - 太高而不会被视为错字。
【问题讨论】:
Google 确实“您的意思是?” (粗略地说)通过观察用户自己如何纠正,然后将最受欢迎的纠正提供给其他用户。 我同意。但我的问题是如何实现类似的功能。我相信也有可能实现类似的计算功能。 这里几乎所有的答案都是有用的。所以,我认为我们应该评估解决方案并形成一个组合完整的分析。我会在几个周末尝试做。 【参考方案1】:Soundex 算法可以帮助您解决这个问题。
http://en.wikipedia.org/wiki/Soundex
您可以为每个名称预先生成 soundex 值并将其存储在数据库中,然后对其编制索引以避免扫描表。
【讨论】:
不确定这是算法的最佳选择。【参考方案2】:这是一个老问题,DWIM(按我的意思做),由 Warren Teitelman 在 Xerox Alto 上著名地实现。如果您的问题是基于发音,这里有一份调查报告可能会有所帮助:
J。 Zobel 和 P. Dart,“语音字符串匹配:信息检索的教训”,Proc。第 19 届国际米兰。 ACM SIGIR 会议信息检索研究与开发 (SIGIR'96),1996 年 8 月,第 166-172 页。
从事信息检索工作的朋友告诉我,Knuth 描述的 Soundex 现在被认为已经过时了。
【讨论】:
【参考方案3】:我会考虑为此使用预先存在的解决方案。
Aspell 带有custom dictionary 的名称可能非常适合此操作。生成字典文件将预先计算快速给出建议所需的所有信息。
【讨论】:
【参考方案4】:Bitap Algorithm 旨在在正文中查找近似匹配。也许你可以用它来计算可能的匹配。 (它基于Levenshtein Distance)
(更新:阅读Ben Sanswer(使用现有的解决方案,可能是aspell
)是要走的路)
正如其他人所说,Google 会通过观察用户自己更正来进行自动更正。如果我搜索“someting
”(原文如此),然后立即搜索“something
”,很可能第一个查询不正确。检测这一点的可能启发式方法是:
那么第二个查询可能是对第一个查询的改进,您可以将其存储并呈现给其他用户。
请注意,您可能需要很多个查询来收集足够的数据,以使这些建议有用。
【讨论】:
【参考方案5】:只需使用Solr 或类似的搜索服务器,您就不必成为该主题的专家。使用拼写建议列表,对每个建议的结果进行搜索,如果结果多于当前搜索查询,则将其添加为“您的意思是”结果。 (这可以防止虚假拼写建议实际上不会返回更多相关命中。)这样,您不需要收集大量数据来进行初始“您的意思是”产品,尽管 Solr 有一些机制可以让您可以手动调整某些查询的结果。
一般来说,您不会将 RDBMS 用于此类搜索,而是使用用于此目的的只读、稍微陈旧的数据库。 (Solr 为底层 Lucene 引擎和数据库添加了友好的编程接口和配置。)在我工作的公司的网站上,夜间服务从 RDBMS 中选择更改的记录,并将它们作为文档推送到 Solr。不费吹灰之力,我们就有了一个系统,搜索框可以非常有效地搜索产品、客户评论、网站页面和博客条目,并在搜索结果中提供拼写建议,以及像您在 NewEgg 看到的分面浏览, Netflix 或 Home Depot,对服务器(尤其是 RDBMS)几乎没有额外的压力。 (我相信 Zappo 的 [新网站] 和 Netflix 都在内部使用 Solr,但请不要引用我的话。)
在您的场景中,您将使用名称列表填充 Solr 索引,并在配置文件中选择适当的匹配算法。
【讨论】:
我发现 Lucene/SOLR 运行起来简直是噩梦。根据我的经验,Sphinx 要简单得多。【参考方案6】:就像您引用的问题的答案之一一样,Peter Norvig 的great solution 可以解决这个问题,并附上 Python 代码。谷歌可能会通过多种方式查询建议,但他们需要的是大量数据。当然,他们可以使用庞大的查询日志对用户行为进行建模,但他们也可以仅使用文本数据通过查看哪个更正更常见来找到最可能正确的单词拼写。 someting
这个词没有出现在字典中,即使它是一个常见的拼写错误,正确的拼写也更为常见。当您找到相似的单词时,您需要最接近拼写错误且在给定上下文中最有可能出现的单词。
Norvig 的解决方案是从 Project Gutenberg 中提取几本书的语料库并计算出现的单词。他根据这些词创建了一个字典,您还可以在其中估计一个词的概率 (COUNT(word) / COUNT(all words)
)。如果你将这一切存储为直接哈希,访问速度很快,但存储可能会成为问题,所以你也可以使用suffix tries之类的东西。访问时间仍然相同(如果您基于哈希实现),但存储需求可以少得多。
接下来,他为拼写错误的单词生成简单的编辑(通过删除、添加或替换一个字母),然后使用语料库中的字典限制可能性列表。这是基于编辑距离(例如 Levenshtein 距离)的概念,具有简单的启发式方法,即大多数拼写错误发生在编辑距离为 2 或更小的情况下。您可以根据自己的需要和计算能力来扩大范围。
一旦他有了可能的单词,他就会从语料库中找到最可能的单词,这就是你的建议。您可以添加许多东西来改进模型。例如,您还可以通过考虑拼写错误中字母的键盘距离来调整概率。当然,这假设用户使用的是英文 QWERTY 键盘。例如,转置e
和q
比转置e
和l
更有可能。
【讨论】:
此外,Norvig 在新书 Beautiful Data 的一章中对此进行了扩展,提出了一种更快但更复杂的算法,并以同样的方式展示了其他一些简洁的东西。 (在这里,我有点自吹自擂,因为他采纳了我的一些建议。)【参考方案7】:对于推荐 Soundex 的人来说,它已经过时了。 Metaphone(更简单)或 Double Metaphone(复杂)要好得多。如果它真的是名称数据,它应该可以正常工作,如果名称是欧洲式的,或者至少是语音的。
至于搜索,如果你想自己动手,而不是使用 Aspell 或其他一些智能数据结构......在幼稚的情况下,预先计算可能的匹配是 O(n^2),但我们知道为了完全匹配,它们必须有一个“音素”重叠,甚至两个。这个预索引步骤(误报率低)可以大大降低复杂性(在实际情况下,类似于 O(30^2 * k^2),其中 k
【讨论】:
【参考方案8】:您有两个可能的问题需要解决(如果您愿意,也可以不解决)
-
用户输入错误的单词(编辑距离算法)
不认识单词和猜测的用户(语音匹配算法)
您是对这两个感兴趣,还是只对其中一个感兴趣?它们实际上是两个不同的东西。例如Sean 和 Shawn 听起来一样,但编辑距离为 3 - 太高而不会被视为拼写错误。
您应该预先索引字数,以确保您只建议相关答案(类似于 ealdent 的建议)。例如,如果我输入sith
,我可能会被问到我的意思是不是smith
,但是如果我输入smith
,那么建议sith
是没有意义的。确定一个算法来衡量一个单词的相对可能性,并且只建议更有可能的单词。
我在松散匹配方面的经验强化了一项简单但重要的学习——根据需要执行尽可能多的索引/筛选层,不要害怕包含超过 2 或 3 个。剔除任何不以正确开头的内容例如,字母,然后剔除不以正确字母结尾的所有内容,依此类推。您真的只想对尽可能小的数据集执行编辑距离计算,因为这是一项非常密集的操作。
因此,如果您有一个 O(n)、一个 O(nlogn) 和一个 O(n^2) 算法 - 请按顺序执行所有这三个算法,以确保您只将“好的前景”通过你的繁重算法。
【讨论】:
以上是关于如何更正用户输入(类似于谷歌“你的意思是啥?”)的主要内容,如果未能解决你的问题,请参考以下文章