`

《Introduce to IR》布尔检索模型

阅读更多

该系列文章是《An Introduce to Information Retrieval》Chapter 1 的读书笔记。

 

 

IR的概念很广泛,即使从钱包中拿出一张信用卡并输入卡号也是一种形式的信息检索。在学术领域,我们这样定义IR:


       信息检索(IR)就是一种从大量数据集合中(通常指存储在计算机中文档)寻找满足信息需求的非结构化(通常指文本)得数据(通常指文档)。

 

 

布尔检索模型(Boolean Retrieval)

 

要点: (1) 倒排/反向索引模型  inverted indexes

          (2) 简单的布尔表达式如何处理这些索引

 

1.1  词—文档的关联矩阵索引  a term-document matrix

 

(1) Unix/Linux  grep- 命令

 

      这个命令或许大家都用过,它是Unix/Linux中用于在指定文件中查找特定的搜索字符串的命令。它的原理是利用正则表达式 在文档集合中进行线性顺序扫描(sort of linear scan)。 这种方式对于现代计算机的运行速度而言,在有限的数据规模下做简单的查询足够应付了。

 

(2) Web data 的搜索面临的现实问题

 

      ▲ 网络在线数据量(web data/online data)巨大,其增长的速度远大于计算机的硬件发展速度。如何快速的检索需要查询的内容? 这一点线性顺序扫描时永远做不到的。

      ▲ web搜索面临的是广大用户群,其查询表达式的方式灵活多样(并不一定是布尔表达式)。甚至有的时候并没有准确的查询含义。比如查询query: Romans NEAR courtyman。 这里的NEAR到底是指Romans,courtyman这两词需要在文章中同一个句子里出现,还是相隔若干词。如何更好的响应用户的灵活多变的查询方法,提供更加人性化得服务呢?

      ▲ 检索结果的排序问题也是一个现实问题。用户需要看到的是最满意的答案,那么查询返回的若干文档,到底哪些与用户查询最相关呢?

 

(3)布尔模型的词—文档关联矩阵索引模型

 

       线性顺序扫面对于web data来说是不可能的。目前,解决高效检索大量非结构化的信息的公认最好手段就是建立索引(indexes) 。下面就是一个简单的索引模型——关联矩阵。

 

       1. 词—文档关联矩阵  如下图,列表示文档,行表示文档中的词。

 

 

           其中如果Term1出现在Doc1中,则矩阵(1,1)标示为1,否则为0。

 

       2. 建立布尔查询表达式(boolean query)。  Antony and Brutus not Caesar 也就是我们需要找到包含Antony ,Brutus同时不包含Caesar 词语的文档。

       3. 使用位运算:    Antony and Brutus not Caesar =  110001 & 110100 & (~110111) =000000. 很可惜,一篇都没有。

 

(4) 关联矩阵模型的缺陷

 

        上面这个简单索引模型并不适合Web data的检索。对于大数据量而言,这个矩阵实在是太大了,不可能全部放进内存。而且更严重的是矩阵太稀疏了。况且对于检索结果的排序问题也是解决不了的。

 

 

1.2  倒排索引  inverted index

 

倒排索引绝对是一个伟大的发现。当前很多搜索引擎或者开发包都使用了这个模型,比如Lucene。

 

(1) 倒排索引结构: 1. 词语组成的字典结构 ——Dictionary   如下图左侧

                            2. 文档组成的位置链 —— Postiong  如下图右侧

        

(2) 创建过程

      1. 将每一个文档中的词语与文档ID(唯一标示文档)组成一个Pair,存入index。如左图A

      2. 将index中的词语按字典序排序。如中图B

      3. 如果相同词语来自同一个文档,则只记录一次。相同词语来自不同文档,则合并成进posting。如右图C

 

(3) 索引存储方法

 

      很显然,对于倒排索引,我们必须把Dictionary和Posting都存储起来。一般Dictionary可以全部加载进内存中,而Posting存放在磁盘中,当需要查找Posting的时候,再会将某一个词语所指向的Posting加载进内存。

 

      Dictionary in menory

             很多时候使用Hash表的形式,也用连续存储的数组结构。

      Posting in menory: 

            1. 单链表( singly linked lists) ,在将新文档插入Posting中的时候付出的代价较少。这一点很适合高频率从网上抓取内容并更新文档。

            2. 可变长数组(variable length arrays),节约了指针所需要的额外空间。并且对于拥有内存缓存区的现代计算机而言,连续内存的结构无疑会增加查询的速度。

            3. 跳跃表(skip lists),一种很先进的存储结构。除了需要额外耗费一些指针空间之外,查找效率极高。Lucene就是用了这种结构。

 

1.3  布尔查询表达式的处理

 

(1)  Posting的合并算法(merge algorithm)

 

       假如我们需要在倒排索引上查找这样一个表达式: Brutus AND Calpurnia。很明显我们需要下面几个步骤:

       1. 在Dictionary中定位Brutus.

       2. 检索Brutus所指向的Posting:  1、2、4、11、31....

       3. 在Dictionary中定位Calpurnia.

       4. 检索Calpurnia所指向的Posting:  2、31、54....

       5. 合并两个Posting.

 

       对于两个有序表的合并算法,可以采用下面的算法: 时间复杂度为O(m+n)

//指针P1,P2分别指向两个Posting链
Posting intersect(p1,p2){

        Posting answer;
        while(p1!=null&&p2!=null){
                if(p1==p2){
                     add(answer, p1->docID);
                     p1=p1->next;
                     p2=p2->next;
                }
                if(p1>p2)  p2=p2->next;
                if(p1<p2)  p1=p1->next;

        }
}
 

(2) 布尔表达式的优化

 

      Brutus AND Caesar AND Calpurnia

 

      表达式的AND顺序按照每一个词的文档频率递增进行优化。 比如 Brutus‘s Ducument Frequence(Brutus所在文档的数量,符号表示DF(Brutus))。DF(Brutus)=1000,DF(Caesar)=10000,DF(Calpurnia)=100。那么查询表达式可以优化成: (Calpurnia AND Brutus) AND Caesar。

 

       理由很简单,Calpurnia AND Brutus的时间复杂度(利用上面的合并算法)为O(1100),其合并后的中间结果R=DF(Calpurnia AND Brutus)<DF(Calpurnia)=100。此时将这个中将结果R AND Caesar 的时间复杂度不会超过O(100+10000)。而且最后结果页不会操作DF<DF(Calpurnia AND Brutus)<100。总的时间复杂度为O(1100+10100)=O(11200)

       如果使用原表达式,Brutus AND Caesa的时间复杂度为O(11000),且中间结果为R=DF( Brutus AND Caesa )< DF(Brutus)=1000。然后R AND Calpurnia的时间复杂度可能达到O(1000+100)。两次AND操作的总时间复杂度为O(11000+1100)=O(12100)

       明显优化之后的时间复杂度会少。如果查询表达式更长,查询词语的DF差距更大,那么优化的效率会更明显

 

       根据上面的优化原理,对于更加复杂的查询表达式(madding OR crowd) AND (ignoble OR strife) AND (killed OR slain)。我们一般都会估算OR操作两个词的DF之和的数量,然后进行AND递增排序。

 

       事实上,对于任意的布尔表达式,每一次操作的中间结果(intermediate)越小越好。 这是我们进行优化的原则所在。

 

(3) 自然语言查询 AND 布尔查询表达式

 

       为什么我们对布尔表达式的操作只将AND,很少说OR或NOT呢?

 

       在搜索引擎实际应用的环境下,用户的查询都是自然语言叙述的,很少直接用布尔表达式(你不能要求所有的用户必须逻辑思维缜密吧)。那么对于用户提交的这些查询,都是纯粹的合并操作。

 

       正是这个原因,现实中很多搜索引擎的应用已经退化成了只有AND的布尔模型了。

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics