咱们平常使用的搜索引擎源自现代信息检索系统学术界对现代信息检索的定义通常是: 从大规模非结构化数据的集合中找出知足用户信息、需求的资料的过程。数据库
这里的“非结构化”实际上是针对经典的数据库而言的数据库里的记录都有严格的字段定义(Scheme),是“结构化”数据的典型表明例如每道菜都有名字,想要吃鱼时,查询“水煮鱼”就很是高效。数据结构
相反,“非结构化”没有这种严格的定义,计算机世界存储的大量文本就是一个典型的表明一篇文章若是没有进行特殊处理,对于其描述的菜叫什么名字、须要准备哪些食材等信息,咱们是一无所知的,天然咱们也就没法将其中的内容和已经定义好的数据库字段进行匹配,这也是数据库在处理非结构化数据时很是乏力的缘由之一。搜索引擎
此时,信息检索的技术能够极大地帮助咱们非结构化数据的特性是没有严格的数据格式定义,这点决定了信息检索的以下两个核心要素:设计
假设我很是喜欢吃川菜中的水煮鱼,其香辣的味道使人难忘那么,若是我想看一篇介绍川菜文化的文章,最简单的方法莫过于看看其中是否提到关键词“水煮鱼”了。若是有(返回值为真),那么我认为就是相关的;若是没有(返回值假),那么我就认为其不相关。3d
就是最基本的布尔模型若是将本次查询转换为布尔表达式也很简单,就一个条件:cdn
水煮鱼blog
固然,你会以为,中华饮食源远流长,川菜经典怎么会只有水煮鱼呢?没错,我还很是喜好粉蒸排骨,它是小时候逢年过节的必备菜肴 那么,将条件修改一下排序
水煮鱼 OR 粉蒸排骨索引
哈哈,这下,不只仅是水煮鱼,谈到“粉蒸排骨”的文 也会认定为其与川菜文化相关 若是想看看在上海哪家店能够吃到这些美食呢?再修改下:文档
(水煮鱼 OR 粉蒸排骨) AND 上海
这里,“上海”是必要条件,而水煮鱼或粉蒸排骨,有同样就能够啦。最后,咱们能够看看哪些文章提到了上海的餐馆经营川菜,并且至少提供水煮鱼和粉蒸排骨两味佳肴中的一道只要理解了布尔表达式,就能理解信息检索中的布尔模型 近些年,除了基本的 AND、OR NOT 操做,布尔模型还有所扩展。
其中,最多见的是邻近操做符(Proximity),用于确保关键词出如今必定的范围以内。其假设就是不一样的搜索关键词,若是它们出现的位置越近,那么命中结果的相关性就越高。
整体上来看,布尔模型的优势是简单易懂,系统实现的成本也较低。不过,它的弱点是对相关性刻画不足。相关与否是个模糊的概念,有的文章和查询条件关系密切,很是符合用户的信息需求,而有些不尽然。仅仅经过“真”和“假”2个值来表示,过于绝对,也没有办法体现其中的区别 那么,有没有更好的解决方案呢?
为了加强布尔模型,须要考虑如何为匹配上的文档来打分。相关性越高的文档其得到的分数就越高。第一个最直观的想法就是:每一个词在不一样文档里的权重是不同的,能够经过这个来计算得分。这里介绍使用最为广泛的 tf- idf机制。
假设咱们有一个文档集合(Collection), c表示整个集合,d表示其中一篇文章,t表示一个单词。那么这里tf表示词频(Term Frequency),就是一个词t在文章中(或是文章的某个字段中)出现的次数。通常的假设是,某个词在文章中的tf越高,表示该词t对于该文而言越重要。固然,篇幅更长的文档可能拥有更高的tf值,咱们会在后面Lucene的介绍中讨论如何计算可使得tf更合理。
同时,另一个经常使用的是 idf,它表示逆文档频率(Inverse Document Frequency)。首先,df表示文档频率( Document Frequency ),即文档集合c中出现某个词t文档数量。通常的假设是,某个词t在文档集合c中,出如今越多的文档中,那么其重要性就越低,反之则越高。
刚开始可能会感受有点困惑,可是仔细想一想这并不难理解。比如“的、你、我、是”这种词常常会出现文档中,可是并不表明什么具体的含义。再举个例子,在讨论美食的文档集合中,“美食”可能会出如今上万篇文章中,但它并不能使得某篇文档变得特殊。相反,若是只有3篇文章讨论到水煮鱼,那么这3篇文章和水煮鱼的相关性就远远高于其余文章。 “水煮鱼”这个词在文档集合中就应该拥有更高的权重。对此,一般用df的反比例指标idf表示其重要性,基本公式以下:
其中N是整个文档集合中文章的数量,log 是为了确保 idf 分值不要远远高于tf而埋没tf的贡献,默认取10为底。因此单词t的df越低,其idf就越高,t的重要性就越高。那么综合起来, tf-idf的基本公式表示以下:
也就是说,一个单词t,若是它在文档中的词频tf越高,且在整个集合中的idf也很高,那么t对于d而言就越重要。
排序布尔模型是一种基于加权求和的打分机制,下面将介绍一个比排序布尔模型稍微复杂一点的向量空间模型。此模型的重点,就是将某个文档转换为一个向量 仍是以上面的文章为例。
统计其中的单词,假设去重后一共有50个不一样(Unique)的词,那么该文梢的向量就是50个纬度,其中每一个纬度是其对应单词的tf-idf值,看上去就像这样:
(四川 = 1.84 ,水煮鱼 = 6.30 ,专辑 = 6.80 ,…… )
固然,在系统实现的时候,不会直接用单词来代来表纬度,而是用单词的ID。如此一来,一个文档集合就会转换为 一组向量,每一个向量表明一篇文档。这种表示忽略了单词在文章中出现的顺序,能够大大简化不少模型中的计算复杂度 ,同时又保证了至关的准确性,咱们一般也称这种处理方式为词包(Bag Of Word),这点在第一篇的文本分类和聚类中已经有所说起。
同理,用户输入的查询也能转换为一组向量,只是和文档向量相比较,查询向量的维度会很是低。最后,相关性问题就转化为计算查询向量和文档向量之间的类似度了。在实际处理中,最经常使用的类似性度量方式是余弦距离。由于它正好是一个介于0和1之间的数,若是向盘一致就是1,若是正交就是0,这也符合类似度百分比的特性,具体的计算公式以下:
其图形化解释如图所示:
相对于标准的布尔数学模型,向量空间模型具备以下优势:
基于线性代数的简单模型,很是容易理解
词组的权重能够不是二元的,例如采用 tf-idf 这种机制
容许文档和索引之间连续类似程度的计算,以及基于此的排序,不限于布尔模型的 “真”“假”两值
容许关键词的部分匹配
固然,基本的向量空间模型也有不少不足之处:
例如对于很长的文档,类似度得分不会很理想;没有考虑到单词所表明的语义,仍是限于精准匹配;没有考虑词在文档中出现的顺序等。
通过前面的探讨,咱们发现:要解决相关性,就要根据需求设计合理的模型,越是精细模型,其计算的复杂度每每也就越高。同时,咱们又要保证很是高的查询效率。互联网时代,用户就是普通的冲浪者,“爽快”的体验相当重要。所以 搜索引擎的结果处理必须是秒级的,一般不能超过3秒。坐在电脑前等待几分钟只是为了知道明天广州的天气状况是没法想象的,也是没法接受的。相关性计算的复杂度和速度,看上去就成了一对没法调和的矛盾体,该如何解决呢?
这里必需要提到检索引擎最经典的数据结构设计一一倒排索引(或者称逆向索引)。先让咱们假想一下,你是一个热爱读书的人,当你进入图书馆或书店的时候,会怎样快速发现本身喜好的图书呢?没错,就是看书架上的标签。若是看到 个架子上标着“烹饪 ·地美食”,那么恭喜你,离介绍川菜的书就不远了。倒排索引作的就是贴标签的事情。看看下 面的例子,这是没有通过倒排索引处理的原始数据,固然实际中的文章不会如此之短。
对于每篇文章的内容,咱们先进行中文分词,而后将分好的词做为该篇的标签。例如对ID为1的文章“最上瘾的绝味川菜”进行分词,可分为以下5个词:
最,上瘾,的,绝味,川菜
那么文章1就会有5个关键词标签
再分析ID为2的文章“大厨必读系列:经典川菜”,它能够分为以下5个词:
大厨,必读,系列,经典,川菜
若是和第1次的标签结果合并起来
请注意ID为5的关键词“川菜”,它在文章1和2中都出现过,因此咱们会将其对应的文档ID写上“1,2”
如此逐个分析完全部5篇文章以后,咱们会获得表以下 ,这就是倒排索引的原型。
这里一共出现了18个不重复的单词,咱们将这个集合称为文档集合的词典或词汇(Vocabulary)。从上面这个结构能够看出,创建倒排索引的时候,是将文档一关键词的关系转变为关键词一文档集合的关系,同时逐步创建词典。有了这种数据结构,你会发现关键词的查询就像在图书馆里根据标签找书同样方便快捷,效率获得大大提高。例如,咱们查找:
川菜 AND 舌尖
经过查找“川菜”系统会返回文章ID:l、二、3;经过查找“舌尖”系统会返回文章ID:三、4,再取交集,咱们就能找到文章3并进行返回。取交集的归并操做在计算机领域已经很是成熟,速度快得惊人。
考虑到布尔模型的邻近(Proximity)操做,或者其余的计算模型,咱们还能够在数据结构中加上词的位置,以及tf-idf等信息,这里再也不深刻展开 此处最重要的结论是:咱们能够经过倒排索引保持超高的效率。