信息检索(IR)笔记1: 倒排索引(Inverted Index)

IR 专栏收录该内容
2 篇文章 0 订阅

建立索引是 information retrieval 的一个核心问题,这一节简单记录关于index的相关笔记.
所有内容均来自 stanford cs276 information retrieval & web search

text preprocessing

一些术语

  1. tokenization
    1. 将文本编程token流,通常处理 "I’m "…
  2. normalization
    1. text 和query term 映射统一(e.g. U.S.A USA)
  3. stemming
    1. 形式(中文通常没这个问题,e.g. authorize, authorization)
  4. Stop words
    1. omit 掉一些无用的,e.g a,an …

inverted index

term -> (frq,posting_list(docId))

frq = len(posting_list)

simple construction

text -> tokenstream -> list ( term, docId) -> sort->unique -> merge

IR 系统两个核心的问题是 index高效和storage 高效,

比如这种索引可以应对简单 boolean query,

也就是说 term1 & term2 的问题,仅需对两个term的posting list merge就行了,并且效率在 O ( f r q 1 + f r q 2 ) O(frq_1+frq_2) O(frq1+frq2)

注意可以证明 任意的boolean 查询都能保证在 O ( ∑ f r q i ) O(\sum frq_i) O(frqi) 也就是说linear on sum of size of posting_list

但是这种索引如果用来处理 短语查询(phase query) 是有问题的

一种简单的解决方案是建立positional index,着种索引类似 inverted index,不过还存储了位置信息,因此storage用的会更多

posional index

(term , frq[Int], List[(docId, List[post[Int]]])

trem : frq
- docId1 : list(pos in docId2)
- docId2 : list(pos in docId2)

查询也是高效的(POSITIONALINTERSECT(p1, p2, k), ref1 P42, 本质上还是基于有序list的merge)

index construction

由于index 通常非常大,不可能简单地把它全部存在memory中,肯定是要存到disk上的,(这里的计算机模型还是简单的PC机,没考虑集群),因此除了简单考虑memory中的算法效率外,还得尽量让算法具备disk-友好性(note 就是能够利用disk访问的时候询盘耗时的特点,多访问block少访问多的小数据)

简单总结几种index

Block sort-based index(BSBI)

回忆前面提到的 simple construction 方法,会存在一个问题,要将所有的文本集合产生的 term dict 放在memory中,当集合很大的时候就会导致memory不够用,因此必须要用second storage(简单起见,后面就称为disk)

BSBI 构造非常简单

algo

  1. 将text集合分成 n n n 个块(block), 每个块在memory中构造好inverted-index,然后写到disk

  2. 对每个block中的inverted-index做multi-way merge

block process

这个算法比较蠢的地方就在于每个block的处理,它采用的是上面提到的(simple construction 的做法) 先简单的 生成 List[(termID,docId)] 然后再排序,注意这是很慢的,有一个sort的过程,后面的SPIMI就是在这个上做了一些改进

multi-way merge

multi-way merge 的过程很简单,就是在memory中维护一个 buffer,存贮当前的term的posting_list,同时用一个priority-queue维护每个block的最小的 termId,每次却出queue中最小的termId,从磁盘中读取posting_list,合并到buffer中,当当前的term的posting_list处理完毕,或者,buffur到达给定的size,写到disk中
(note 注意这是一个非常典型的有限缓冲区读写问题)

简单实现

import heapq
class BSBIIndex(BSBIIndex):
    def merge(self, indices, merged_index,buffur_size=1024*1024):
        """Merges multiple inverted indices into a single index
        
        Parameters
        ----------
        indices: List[InvertedIndexIterator]
            A list of InvertedIndexIterator objects, each representing an
            iterable inverted index for a block
        merged_index: InvertedIndexWriter
            An instance of InvertedIndexWriter object into which each merged 
            postings list is written out one at a time
        """
        ### Begin your code
        cur_term=None
        buffer= []
    
        for merged_item in heapq.merge(*indices,key=lambda x : x[0]):
            if cur_term is None or cur_term == merged_item[0]:
                cur_term = merged_item[0]
                buffer.extend(merged_item[1])
            else :
                merged_index.append(cur_term,buffer)
                cur_term = merged_item[0]
                buffer=[]
                buffer.extend(merged_item[1])
            
            if len(buffer) > buffur_size:
                merged_index.append(cur_term,buffer)
                buffer = []
                

complexity

假设总的term 为 T T T, 分为 n n n

O ( n ∗ T / n l o g ( T / n ) + l o g ( n ) T ) O(n*T/nlog(T/n) + log(n)T) O(nT/nlog(T/n)+log(n)T)

同时 BSBI还用了一个map term-> termID,这个也是耗费存储的

single pass in memory indexing

其实我感觉这算法就是正常人的写法, ?

因为这个posting_list本来就是递增的所以在处理每个block的时候仅仅需要维护一个dict然后每次append到posting_list的末尾就行了,满了之后放到磁盘中

不太清楚 single-pass的意义,因为每个block仍旧需要merge的过程

可以加色blockmerge的过程近似线性,block很少啊
complexity Θ ( T ) \Theta(T) Θ(T)

index compression

这东西大概是研究index的编解码,不太感兴趣…

补充一个作业中用到的吧

variable-byte-code

很简单就是将一个数字按照7bit一个byte表示, 仅仅表示有效的byte(全0的byte就不要了),最后一个byte(最高位)做高bit为1,其他byte最高bit为0,这样就能分辨一个数字结尾了

e.g

11111000011111 -> 1111100 0011111 -> 00011111 11111100 

code

补充

这个算法对于assigment中的例子来说 57M-> 31M

code 简单实现

code

ref

  1. Introduction to Information Retrieval, by C. Manning, P. Raghavan, and H. Schütze (Cambridge University Press, 2008).

版权声明

本作品为作者原创文章,采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

作者: taotao

仅允许非商业转载,转载请保留此版权声明,并注明出处

  • 2
    点赞
  • 1
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
<p style="color:#666666;"> <span style="font-size:14px;">本门课程重实战,将基础知识拆解到项目里,让你在项目情境里学知识。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">这样的学习方式能让你保持兴趣、充满动力,时刻知道学的东西能用在哪、能怎么用。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">平时不明白的知识点,放在项目里去理解就恍然大悟了。</span> </p> <p style="color:#666666;"> <span></span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>一、融汇贯通</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本视频采用了前后端分离的开发模式,前端使用Vue.js+Element UI实现了Web页面的呈现,后端使用Python 的Django框架实现了数据访问的接口,前端通过Axios访问后端接口获得数据。在学习完本章节后,真正理解前后端的各自承担的工作。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>二、贴近实战</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本系列课程为练手项目实战:学生管理系统v4.0的开发,项目包含了如下几个内容:项目的总体介绍、基本功能的演示、Vuejs的初始化、Element UI的使用、在Django中实现针对数据的增删改查的接口、在Vuejs中实现前端增删改查的调用、实现文件的上传、实现表格的分页、实现导出数据到Excel、实现通过Excel导入数据、实现针对表格的批量化操作等等,所有的功能都通过演示完成、贴近了实战</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>三、课程亮点</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">在本案例中,最大的亮点在于前后端做了分离,真正理解前后端的各自承担的工作。前端如何和后端交互</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>适合人群:</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">1、有Python语言基础、web前端基础,想要深入学习Python Web框架的朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">2、有Django基础,但是想学习企业级项目实战的朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">3、有MySQL数据库基础的朋友</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><img alt="" src="https://img-bss.csdnimg.cn/202009070752197496.png" /><br /> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><br /> </span> </p>
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值