主要关注查询的拼写校订。例如,用户输入carot时,实际上可能想返回包含词项carrot的文档。Google的报告指出,当用户输入britian spears、britney's spears、brandy spears或者prittany spears时,实际上搜索引擎都会当成是britney spears的错误拼写来处理。咱们将会考虑解决该问题的两个步骤:第一步基于编程距离(edit distance),第二步基于k-gram重合度(k-gram overlap)。在介绍详细算法以前,咱们首先简单介绍一下搜索引擎是如何实现拼写纠正并使其成为用户体验的一部分的。算法
对于大多数拼写纠正(spelling correction)算法而言,存在如下两个基本的原则。编程
拼写校订算法基于这些邻近度计算,其功能主要经过如下几种方式返回给用户。grunt
这里咱们主要关注两种拼写校订的方法:一种是词项独立(isolated-term)的校订,另外一种是上下文敏感(content-sensitive)的校订。在词项独立的校订方法中,无论查询中包含多少个查询词项,其每次只对单个查询项进行校订,也就是说在象征时词项是相互独立的。上面给出的carot例子就属于这一类作法。利用这种词项独立校订的方法,就很难检测到查询flew form Heathrow 中实际上包含一个错误的词项form(正确的形式应该是from),这是由于在校订时每一个词项之间就是相互独立的。搜索引擎
首先咱们介绍两种词项独立的校订方法:编辑距离方法及k-gram重合度方法。而后,咱们基于上下文敏感校订方法。编码
拼写校订问题不知须要计算出编辑距离:给定字符串集合V
(对应词项词汇表)和查询字符串q
,咱们要从V
中寻找和q
具备最小编辑距离的字符串。咱们能够把这个问题当作是解码问题,其中编码词(对应V
中的字符串)已经预先定义好。最直接的方法是,计算q
到V
中的每一个字符串的编辑距离,而后选择其中编辑距离最小的字符串。很显然,这种穷举的搜索方法开销很大。所以实际中使用了多种启发式方法来提升查找的效率。
最简单的启发式方法是将搜索限制在与查询词具备相同的首字母的字符串上,也就是说咱们指望查询的拼写错误不会出如今第一个字符上。上述启发式方法的一个更复杂的作法是利用轮排索引的某种版本,忽略了刺猬的$
符号。考虑查询字符串q
的全部旋转结果集合,对集合中每一个旋转r,经过遍历B树来访问轮排索引(即轮排索引的词汇表查找能够经过B树来实现),返回旋转结果中以r开头的词项。例如,若是q为mase,那么咱们考虑其旋转r=sema,这是咱们会返回诸如semantic和semaphore的词,而这些词和mase之间的编辑距离并不小。遗憾的是,采用这种作法咱们会错过包括mare和mane在内的一些更可能相关的词。为解决这个问题,咱们改变旋转的使用机制:对每一个旋转结果,在遍历B树以前咱们忽略其长度的e
的后缀,这样作能够保证返回词项集合R中的每一个词项和q之间都包含一段较长的公共子串。e
的值取决于q的长度。固然咱们也能够设置为常数。日志
为了进一步限制计算编辑距离后获得的词汇表大小,如下介绍如何经过使用k-gram索引来辅助返回与查询q具备较小编辑距离的词项。一旦返回这些词项以后,利用k-gram索引,就能从中找出与q具备最小编辑距离的词。
实际上,咱们利用k-gram索引来查找与查询具备不少公共k-gram的词项。只要对“具备不少公共k-gram”进行合理定义,咱们认为上述查找其实是对查询字符串q中k-gram的倒排记录表进行单遍扫面的过程。
查询bord的2-gram索引的一个片断,其中包含3个2-gram组成的倒排记录表。假定咱们想返回包含上面3个2-gram中的至少2个词项,对倒排记录表的单遍扫描(和第一章相似)会返回知足该条件的全部词项,本例当中词项包括aboard、boardroom及border。 code
这种经过线性扫描并当即合并倒排记录表的作法十分简单,只须要待匹配词项包含查询q中某个固定数目的k-gram便可。可是这种作法有一个缺点,好比boardroom这种不多是bord的正确拼写形式的词也会被返回。因此,咱们须要计算词汇表中词项与查询q之间更精细的重叠计算方法。好比采用jaccard系数(jaccard coefficient)就能够对先前的线性扫描合并方法进行修正。这里,Jaccard系数的计算公式为|A∩B|/|A∪B|,其中A、B分别是查询q、词汇表词项中的k-gram集合、扫描过程当中,一旦扫描到与当前的词项t,就快速计算出q和t的Jaccard系数,而后继续扫描下一个词项。若是Jaccard系数超过预约的阈值,则将t输出。不然,咱们每每继续扫描。上述过程代表,在计算Jaccard系数时,咱们须要知道q和t的k-gram集合。
因为是对q中的全部k-gram扫描倒排记录表,所以q中的k-gram集合是已知的,因而问题就变成如何求解t中的全部k-gram。理论上咱们能够穷举出t中全部k-gram。可是这种作法不只慢并且在实际中也难以实现。在不少状况下,倒排记录自己极可能并不包含完整的t字符串而每每是t的某种编码形式。也就是说,每每并不知道t的k-gram集合。然而,一个重要的发现使得这种状况下q和tJaccard系数的计算成为可能。这个发现就是,在计算Jaccard系数的时候,咱们只须要知道t的长度便可。对于查询q=bord扫描倒排记录表直到t=boardroom。这时咱们知道有2个2-gram已经匹配上了。若是倒排记录表中已经预先记录了boardroom所包含的2-gram的数目(这里是8),那么全部计算Jaccard的系数的信息都已知,计算公式2/(8+3-2)。其中,分子为倒排记录的命中数(值为2,分别来自bo和rd),分母为bord及boardroom中的2-gram之和减去倒排记录表的命中数。
须要指出的是,也能够把Jaccard系数替换成其余可以进行快速计算的衡量指标。那么如何拼写校订中使用这些度量方式呢?一种经验性的方法是,首先使用k-gram索引返回多是q的潜在正确拼写形式的词项集合,而后计算该集合中的每一个元素和q之间的编辑距离并选择具备较小距离的那些词项。orm
独立的词项拼写校订方法在面对诸如flew form Heathrow 中的输出错误时无能为力,所以这3个单词独立看来拼写都没有错误。当输入这类查询时,搜索引擎可能会发现返回的文档很是少,随后也许提供正确的查询建议flew form Heathrow。 这种功能的一种简单的实现方法就是,及时每一个单词拼写都是对的,仍然要对每一个单词找到可能的拼写正确词,而后尝试对短语中的每一个词进行替换。好比对于上面flew form Heathrow的例子,咱们可能会返回以下短语fled from Heathrow 和 flew fore Heathrow。对每一个替换后的短语,搜索引擎进行查找并肯定最后的返回数目。
对于单独的查询有多种可能的正确拼写形式,那么上述方法中穷举过程的开销会很是大,最后咱们就会面对很是多的拼写组合。有一些启发式方法能够减小可能的拼写结果空间。上述例子中,咱们对flew及from进行扩展时,咱们只保留文档集合或者查询日志中的高频组合结果。好比,咱们可能会保存flew from 而不是 fled fore 或 flea form,这是由于fled fore极可能比flew from 出现的次数少。接下来咱们仅仅根据高频双词(如flew from)来得到Heathrow的可能的正确拼写。计算双词频率的时候可使用文档集,也可使用用户的查询日志。索引
最后一项用户容错检索技术与发音有关,即拼写错误的缘由在于用户输入一个和目标词项发音类似的查询。该方法尤为适合用于人名的查找,其基本的思路是:对每一个词项,进行一个语音的哈希操做,发音类似的词项都被映射为同一值。该思路最先源于国际警察部门的工做,它们自20世纪初开始就在全球范围内寻找与罪犯嫌疑人发音类似的人名,而无论这些人名在不一样国家发音是否有所不一样。上述思路主要用于专有名词的语音校订。
这类通用语音哈希方法一般统称soundex算法(soundex algorithm)。其中,一个原始的soundex算法的构建方法以下。须要指出的是,该基本算法存在不少变形。ci