第3章 词典和容错式检索

3.1 用于词典的搜索结构

给定一个反向索引和一个查询,我们的第一个任务是确定每个查询词是否存在于词汇表中,如果是,则返回指向相应倒排记录表的指针。涉及在数据结构中定位词项。

数据结构:字典(dictionary )
两个解决方案:哈希表和搜索树(hashing and search trees.)

1.哈希表:在查询时,我们分别对每个查询词进行哈希操作,并返回一个指向相应倒排记录表的指针,并考虑解决哈希冲突。

√ 每个词项(键)被映射到一个整数上,在一个足够大的目标空间中,哈希结果的冲突可能性会减小;冲突可以通过辅助结构来解决,而辅助结构可以要求维护。
√ 优点:定位速度优于树的定位速度,时间复杂度为常数
√ 缺点:
(1)不能查询词项的变形(比如像resume这样的单词的重音和无重音的版本),因为它们可以被哈希映射成不同的整数。
(2)不能寻找带前缀的词项。
(3)随词汇量不断增长,为当前需求而设计的散列函数在几年内可能还不够。

2.搜索树:与哈希不同,搜索树要求文档集合中使用的字符有规定的顺序

(1)二叉树(binary tree):每个内部节点都有两个子节点。有效的搜索取决于树是否平衡:任何节点的两个子树下的词项的数量相等或是相差1。主要问题是再平衡,当从二叉搜索树中插入或删除词项时,需要重新平衡,以便保持平衡属性。为了减少再平衡,一种方法是允许内部节点下的子树的数量在一个固定的时间间隔内变化。
(2)B树(B-tree):B树被看作是将二叉树的多个层次折叠成一个,当某些字典是磁盘常驻时尤其有利。
√ 优点:支持前缀查询
√ 缺点:搜索速度低于哈希表,平衡树时间复杂度为O(log M),M为词汇表大小。

解决方案(哈希表或搜索树)的选择需要考虑如下:
(1)可能拥有多少个词项?
(2)词项数目会保持不变还是改变?在变化的情况下,只插入新的词项还是在字典中删除一些词项?
(3)各种词项的相对频率是多少?

3.2通配符查询(Wildcard queries)

在下列任何情况下使用通配符查询:
(1)不确定查询词的拼写(e.g., Sydney vs. Sidney, which leads to the wildcard query S*dney);
(2)拼写一个词项的多种变形,并寻找包含任何变形的文档(e.g., color vs. colour);
(3)用户寻找包含有可能被阻止的词项的变形的文档,但不确定搜索引擎是否执行了阻止 (e.g., judicial vs. judiciary, leading to the wildcard query judicia*);
(4)用户不确定正确的外来词或短语的翻译 (e.g., the query Universit* Stuttgart)。

·后通配符查询(trailing wildcard query):mon*形式的查询,遍历B树,列举一组词典中以mon为前缀的词项的集合W,使用反向索引检索包含W中任何词项的所有文档。
·前通配符查询(leading wildcard queries):*mon形式的查询,遍历反向b树,反向b树的每一个根到叶的路径对应于在字典中倒写的一个词项,沿着反向的b树遍历,然后列出词汇表中满足前缀的所有词项R。
·一般通配符查询:se*mon形式的查询,使用常规的b-树枚举以se为前缀和一个非空后缀的词项集合W,然后反向b-树枚举以后缀mon结束的词项集R。把两个集合W和R进行交集,得到以前缀se开始与以后缀mon结束的词项集。最后使用标准的反向索引检索包含这个交集中任何词项的所有文档。

1.通用通配符查询(General wildcard queries)

处理一般通配符查询的技术策略:在一个特殊构造的索引上,将给定的通配符查询q表示为布尔查询Q,使布尔答案是一个匹配q的词汇词项的超集。

·轮排索引:一种反向索引。在字符集中引入一个特殊的符号$,以标记一个词项的结束。构建一个轮排索引,在这个索引中,每个词项的各种旋转(增加$)都连接到原始的词汇表词项。(如hello的轮排索引: hello$,ello$h,llo$he,lo$hel,o$hell)。

·轮排词汇表(permuterm vocabulary):permuterm索引中旋转的词项的集合。

√ 基本思想:
(1)考虑通配符查询m*n,关键是要旋转通配符查询,以便*符号出现在字符串的末尾。因此,旋转通配符查询变成了n$m*。接下来,在轮排索引中查找这个字符串,寻找n$m*(通过搜索树)会等价于词项man和moron的旋转结果。因此可以用一个*符号来处理任何通配符查询。
(2)考虑fi*mo*er查询,首先列举字典中的词项,这些词项在er$fi*的轮排索引中。并不是所有的字典词项都有字符串mo,通过详尽的枚举过滤它们,检查每个候选者是否包含mo。在这个例子中,“fishmonger”这个词项会在过滤中留下,而filibuster不会。然后通过标准的反向索引来查找幸存的词项,用于文档检索。

√ 缺点:它的字典变得非常大,包括每个词项的所有旋转。

√ 轮排索引使我们能够识别与通配符查询匹配的原始词汇表,我们在标准的反向索引中查找这些词项,以检索匹配的文档。

√ B树和轮排索引之间密切相互作用。事实上,该结构应该被看作是一种“一棵树”。而我们遵循传统的词项描述轮排索引,它与B树不同,它允许我们用给定的前缀来选择旋转。

2.k-gram的通配符查询索引( k-Gram indexes for wildcard queries)

尽管轮排索引很简单,但它可能导致每一项的旋转次数大幅增加,另一种技术称为k-gram索引,用于处理通配符查询。

·k-gram:是k个字符的序列。因此,cas、ast和stl都是在castle的3-gram。使用一个特殊字符$来表示一个词项的开始或结束,所以为castle生成的3-gram的完整集合是:$ca,cas,ast,stl,tle,le$。

√ 在k-gram索引中,字典中包含了所有在词汇表中出现的k-grams。每个倒排记录表从k-gram指向包含k-gram的所有词汇表。例如,3-gram etr:

图3.1 一个3-gram索引的倒排记录表的例子。匹配的词汇表是在倒排记录表中按字母顺序排列的。

√ 基本思想:
考虑通配符查询re*ve,寻找包含任何以re开头以ve结尾的词项的文档。因此,运行布尔查询$re AND VE$。这是在3-gram索引中查找的,并生成一个匹配的词项列表,如relive、remove和retrieve。然后,在标准的反向索引中查找每一个匹配的词项,以生成匹配查询的文档。

√ 后置滤波(postfiltering):
使用k-gram索引处理有一个问题。考虑使用3-gram索引描述的查询red*。首先进行布尔查询$re AND RED。这就导致了如“retired”的词项匹配,它包含了两个3-grams $re and red 的连接,但与原来的通配符查询red*不匹配。
为解决这个问题,引入后置滤波,在3-gram索引上的布尔查询所枚举的词项将单独检查原始查询red*。这是一个简单的字符串匹配操作,并且淘汰了与原始查询不匹配的词项如retired。然后在标准的反向索引中搜索上下的词项。

√ 一个通配符查询可以导致多个词项被枚举,每一个词项都成为标准反向索引的单项查询。允许使用布尔运算符的通配符查询的组合,例如,re*d AND fe*ri这样的查询的恰当解释是,一个析取的连接:寻找所有包含任何匹配re*d和任何匹配的fe*ri的词项的文档。

*即使没有通配符查询的布尔组合,通配符查询的处理也可能相当昂贵,因为在特殊索引、过滤和最终标准的反向索引中增加了查找。搜索引擎可能支持这样丰富的功能,但最常见的是,该功能隐藏在大多数用户从未使用过的接口(比如高级查询接口)后面。在搜索界面中公开这些功能通常会鼓励用户在不需要的时候调用它(比如,通过输入查询的前缀a*),增加搜索引擎的处理负载。

3.3拼写校正(Spelling correction)

大多数拼写校正算法两个基本原则:
(1)选择与拼写错误最接近的词项
(2)当两个正确拼写的查询被绑定时,选择一个更常见的查询。最简单的是考虑集合中词项的出现次数,许多搜索引擎中(如web)更常见的是使用在其他用户输入的查询中最常见的进行更正。

拼写校正的方法:

1.词独立法( isolated-term ):纠正单个查询词。

基本思想:使用k-gram索引列举一组可能修正的q的候选词汇表词项。然后计算从q到这组集合的每一项的编辑距离,从对于q小编辑距离的集合中选择词项。

两种处理技术:编辑距离(edit distance )和k-gram重和度(k-gram overlap)

(1)编辑距离(Edit distance)

·编辑距离:给定二个字符串s1和s2,它们之间的编辑距离是将s1转换为s2所需的编辑操作的最小数量。也称为Levenshtein距离。

√ 允许的编辑操作:

  • 将一个字符插入一个字符串
  • 从一个字符串中删除一个字符
  • 用另一个字符替换字符串的字符;

√ 动态规划算法,伪代码:

图3.2 计算字符串s1和s2之间的编辑距离的动态规划算法

√ C++代码:


√ 给定词项词汇表V和查询字符串q,寻找V中与q具有最小编辑距离的字符串,得到候选的“正确”单词词汇表。
(1)最明显的方法是在选择最小编辑距离的字符串之前,计算从q到V中的每个字符串的编辑距离。这种搜索成本非常高。
(2)最简单的启发式方法:将搜索限制在字典词项中,以与查询字符串相同的字母开头(希望查询的第一个字符不出现拼写错误)。
(3)这种启发式更复杂变形:使用一个版本的轮排索引,在索引中省略了单词尾符号$。考虑查询字符串的所有旋转q。对于每一个旋转r,遍历b - tree进入轮排索引,从而检索所有以r开头的词项。
(4)旋转方案改进:
如果q是mase,考虑旋转r =sema,将检索词项如sematic和semaphore等,没有一个小的编辑距离问。不幸的是,我们会错过更多的相关的词项如mare和mane。
为了解决这个问题,对于每次旋转,在执行b树遍历之前省略l字符的后缀。确保从字典中检索到的集合R中的每一项都包含一个与q相同的长子串(l的值取决于q的长度,也可以将它设置为一个固定不变的常量,比如2)。

(2)K-gram重合度(k-gram overlap)

为进一步限制计算编辑距离后的词汇词项集大小,调用k-gram索引来协助检索与查询q编辑距离较低的词项。

√ 检索过程:本质上是单一扫描查询字符串q中的k-grams的倒排记录表。

Eg. 图3.3中的2-gram索引显示了查询bord中三个双字母组的倒排记录表。假设想要检索至少包含这些三个字母组中的两个的词汇表。对这些倒排记录表进行单一扫描,可以列举出所有词项,如图将列举出aboard、boardroom和border。


图3.3查询bord中三个双字母组的倒排记录表

√ 简单地要求从查询q中包含一个固定数量的k-grams匹配词汇表的缺点是像boardroom这样的词项被枚举。因此需要更微妙的词项和q之间的k-grams中的重叠测量。

·Jaccard系数(Jaccard coefficient ):定义为|A ᴖ B| /|A ᴗ B|,我们考虑的这两个集合是查询q中的k-grams,以及词汇表中的k-grams集合。

√ 基本思想:随着扫描的进行,我们从一个词汇表t开始,到下一个词汇表,在q和t之间计算Jaccard系数,如果系数超过了预设的阈值,我们就把t加到输出中;如果没有,我们将继续下一词项的倒排记录表。

*计算Jaccard系数,只需要t的长度。以图3.3为例,考虑当倒排记录表扫描查询q=bord,t =boardroom。如果这些倒排记录表存储boardroom中bigrams的数量(即8),就有了需要的所有信息计算Jaccard系数:2/(8+3-2)(分子是从倒排记录表数获得的(2来自bo和rd);分母是bord和boardroom中bigrams的数量的总和。)

2.上下文敏感法(Context-sensitive):考虑上下文单词。

词独立法将无法纠正如flew form Heathrow的输入错误,三个查询词的拼写都是正确的。当这样的短语检索出很少的文档时,搜索引擎可能会提供flew from Heathrow的修正查询。
(1)最简单的方法是即使每个查询词都拼写正确,仍枚举三个查询词中的每一个的修正,然后尝试替换短语中的每一个词项。从flew form Heathrow的例子中可列举了一些如fled form Heathrow 和 flew fore Heathrow的短语。对于每一个这样的替代短语,搜索引擎运行查询并确定匹配结果的数量。
(2)如果我们查找单个词项的许多修正,这个枚举成本可能很大;我们可能会遇到大量的替代方案。一些启发式方法被用来减小解空间:只保留集合中最常见的组合或者在查询日志中用户以前的查询。(使用用户发出的查询日志将包括带有拼写错误的查询。)

3.4语音校正(Phonetic correction)

由于用户输入的查询听起来像目标项,所以出现了拼写错误。这种算法尤其适用于对人名的搜索。
√ 主要思想:为每个词项生成一个语音映射(phonetic hash),以便类似的词项映射到相同的值。

·soundex算法:
(1)原始的soundex算法方案:

  • 将每一项都转换成一个四字符(soundex指数)的简化形式,从这些简化的形式构建一个反向索引到原始的词项。
  • 对查询词项执行相同的操作。
  • 当查询需要一个soundex匹配时,搜索这个soundex索引。
    (2)soundex算法的变化:
    与将词项转换为四字符形式有关。常用的转换结果是一个四字符的代码,第一个字符是字母表中的字母,另外三个是0到9之间的数字。
  • 保留词项的第一个字母。
  • 将下列字母的所有出现更改为0(零):A、E、I、O、U、H、W和Y。
  • 将字母改为数字如下:
    B,F,P,V -> 1
    C,G,J,K,Q,S,X,Z -> 2
    D,T -> 3
    L -> 4
    N -> 5
    R -> 6
  • 反复地从每一对连续相同的数字中取出一个。
  • 从产生的字符串中删除所有的0。用后面的0填充结果字符串,并返回前四个位置,包含一个字母和三个数字。

√ 对于一个soundex映射(soundex map)的例子,赫尔曼映射(Hermann maps)到H655。给定一个查询(比如Herman),计算它的soundex code,然后从soundex索引中检索所有与soundex code匹配的词汇表,然后在标准的反向索引上运行结果查询。
√ 基于算法的一些观察结果:
(1)在转录名称时,元音被视为可互换的;
(2)发音相似的辅音(如D,T)被放入等价类,导致相关的名称通常有相同soundex代码。

《introduction to information retrieval》信息检索学习笔记3 词典和容错式检索相关推荐

  1. Information Retrieval 倒排索引 学习笔记

    一,问题描述 在Shakespeare文集(有很多文档Document)中,寻找哪个文档包含了单词"Brutus"和"Caesar",且不包含"Cal ...

  2. 【信息检索导论】第三章 容错式检索

    总览 本章主要解决以下几个问题: 根据用户的询问,如何找到用户询问中的词语对应的倒排表? 如果用户不记得某个单词怎么拼写,如何实现模糊查询(通配符查询)? 如果用户写错了某个字, 怎么样帮助他纠正,以 ...

  3. 【学习笔记】求解简单递归式的一般方法

    [学习笔记]求解简单递归式的一般方法 手动博客搬家: 本文发表于20180618 15:53:06, 原地址https://blog.csdn.net/suncongbo/article/detail ...

  4. 【信息检索】词典、倒排记录表和容错式检索

    博客地址:https://www.codingshen.com/archives/%E4%BF%A1%E6%81%AF%E6%A3%80%E7%B4%A2%E8%AF%8D%E5%85%B8%E5%8 ...

  5. 《introduction to information retrieval》信息检索学习笔记1 布尔检索

    第1章 布尔检索 信息检索的定义:信息检索(IR)是从大型集合(通常存储在计算机上)中寻找满足信息需求的非结构化性质(通常是文本)的材料(通常是文档). 1.1一个信息检索的例子 问题描述:确定莎士比 ...

  6. 《introduction to information retrieval》信息检索学习笔记4 索引结构

    第4章 索引结构(Index construction) 4.1 硬件基础知识(Hardware basics) √为了最大化数据传输速率,一起读取的数据块应在磁盘上连续存储. √操作系统通常读取和写 ...

  7. 《introduction to information retrieval》信息检索学习笔记2 词项词汇和倒排记录表

    第2章 词项词汇和倒排记录表 回顾建立倒排索引的主要步骤: 1.收集要索引的文档. 2.词条化文本. 3.对词条进行语言预处理,生成标准化词条. 4.建立倒排索引,索引每个词项出现的文档. 2.1文档 ...

  8. javascript深入浅出——学习笔记(六种数据类型和隐式转换)

    在慕课之前学过JS深入浅出,最近发现很多东西都记不太清楚了,再复习一遍好了,感觉这个课程真的超级棒的,做做笔记,再添加一些学习内容?随时补充 课程大纲 1.数据类型 2.表达式和运算符 3.语句 4. ...

  9. 【C++ STL学习笔记】C++ STL序列式容器(array,vector,deque,list)

    文章目录 C++ STL容器是什么? 迭代器是什么,C++ STL迭代器(iterator)用法详解 迭代器类别 迭代器的定义方式 C++序列式容器(STL序列式容器)是什么 容器中常见的函数成员 C ...

最新文章

  1. 深度学习-语义分割总结
  2. shell脚本之case用法
  3. 利用Httponly提升web应用程序安全性
  4. 通过ribbon 根据服务名获取所有服务实例的IP和端口列表
  5. envoy实现_如何利用 Envoy 的 Postgres 过滤器实现网络可观察性
  6. Java行业情景分析_Java 设计模式情景分析——单例模式
  7. C++学习之路 | PTA乙级—— 1034 有理数四则运算 (20 分)(精简)
  8. Java集合框架之Collection实例解析
  9. 企业员工管理系统封面html,单页面模板
  10. 前端绝对路径不显示图片_[锋利web前端开发]sass小技巧图片版本号和绝对路径引用...
  11. Spring 各种包功能
  12. unity3d怎么让模型动起来_Unity动画系统详解1:在Unity中如何制作动画?
  13. IEEE模板如何在abstract和keywords之间加一个段落Note to Practitioners
  14. Android开发之渐变效果gradient属性
  15. 从黑暗到光明,LED照明演变史知多少?内有彩蛋
  16. 腾讯云轻量应用服务器搭建即时通信 IM系统
  17. spring boot 引用 shiro 认证AD域
  18. 手把手教你写第一个C语言程序
  19. 揭秘“1200工程”:苏宁如何培养企业接班人? | 一点财经
  20. 安装配置群晖 DS918+ NAS及常用技巧

热门文章

  1. 2022-2028年中国绝热隔音材料行业投资分析及前景预测报告
  2. 2022-2028年中国防水橡胶布行业市场发展模式及投资前景分析报告
  3. 并发 vs 并行 (Concurrency Is Not Parallelism)
  4. mybatis配置文件解析
  5. ipykernel_launcher.py: error: unrecognized arguments: -f /Users/apple/Library/Jupyter/runtime/kernel
  6. x86 cpu卷积网络的自动调谐
  7. H265与ffmpeg改进开发
  8. 交换机应用寻找10个完美的因素
  9. 用测试驱动开发状态机
  10. 目标检测数据集The Object Detection Dataset