赞
踩
1 什么是IR information retrieval
1.1 定义相关
- 1.1.1 结构相关
- 1.1.2 信息项
1.2 信息需求 information need
- 1.2.1 4阶段
- 1.2.2 查询query
1.3 IR作用功能
1.3.1 相关定义
- 1.3.1.1 具体
- 1.3.1.2 补充
1.3.2 相关性 Relevance
1.3.3 问答相关 Qustion Answering 非IR
1.3.4 信息提取 information extraction 非IR
2 有关查询
2.1 矩阵相关
- term-document incidence matrix
2.2 索引 indexing
2.2.1 inverted index
- 大纲
- 具体
- 代码相关
2.3 查询优化
2.3.1 skip pointers
- 2.3.1.1 相关代码
3 预处理 processing
3.1 引言,开始流程
3.2 方法措施,提高效率
stopwords 停词
stemming 提取词干
- 相关代码,使用porter提取法
lemmatisation 词形还原
3.3 phrase query 短语查询
- biword index 双字索引
- positional index 位置索引
4 向量模型的使用 vector space
4.1 introduction
4.2 权重 term weighting
TF-IDF
- 计算方式
4.3 优点和缺点
4.4 步骤
5 BM25 模型
- 5.1 TF
- 5.2 IDF
- 5.3 综合结果
- 5.4 俩变种
6 Evaluation 评估
6.1 引言
- 小概念
- 例子
6.2 Precision/Recall 精确度和召回率
6.3 Single value metric 单值度量 基于RelRet
- P@n
- R-precision
- MAP
6.4 bpref
6.5 NDCG
6.6 结果
7 IR pipelines和现代IR
8 Fusion
简单描述
- efficiency和scalability是关键
- 利用query在网络上找到自己想要的内容
- 就是搜索自己想要的内容,包括查找关键字等
简单定义
Information Retrieval (IR) deals with the representation, storage, organization of, and access to information items.
The representation and organization of the information items should provide the user with easy access to the information in which he is interested.
简而言之就是对于数据的存储和访问
非结构化
结构化
information item:非结构化形式的内容,比如书籍文档或书写的材料等,在IR系统中,使用document来指代信息项,而且不仅仅包含文字内容,还有音频图片等
在本pdf中所有文档或document的表述都是有关信息项的
representation
为了方便进行query,所以有某种表示方式
利用数学相关内容加速搜索:原始文本太多会非常慢,数学计算很快,以向量、集合、位串等形式来表示文档
query是提供给IR系统的对于信息需求的表达,用于解释需要什么样的信息
补充
上下文查询和关键字查询是信息检索和搜索引擎中的两种不同查询方式,它们的区别主要体现在以下几个方面:
查询依据 :
- 上下文查询 :依赖于查询的上下文环境,例如用户的搜索历史、个人偏好、地理位置、时间信息等。这种查询方式试图理解用户的查询意图,并据此提供更为准确和个性化的搜索结果。
- 关键字查询 :基于用户输入的具体关键词进行搜索,搜索引擎会匹配数据库中的内容与这些关键词,返回最相关的结果。
查询目的 :
- 上下文查询 :更多地关注于提供与用户当前需求高度相关的信息,它试图理解查询背后的“为什么”,而不仅仅是“是什么”。
- 关键字查询 :目的是找到与用户输入的关键词直接相关的信息,它侧重于关键词的匹配度。
查询结果 :
- 上下文查询 :可能会返回一系列多样化的结果,这些结果是根据用户可能的多种需求综合判断得出的。
- 关键字查询 :通常返回与关键词直接相关的结果,这些结果可能不如上下文查询那样个性化。
技术实现 :
- 上下文查询 :需要更复杂的算法来分析用户的查询上下文,包括自然语言处理、用户行为分析等。
- 关键字查询 :实现相对简单,主要是文本匹配和相关性排序算法。
用户交互 :
- 上下文查询 :可能需要用户在首次查询后进行一系列的交互来进一步明确需求。
- 关键字查询 :用户输入关键词后,系统直接返回结果,用户交互通常较少。
在实际应用中,现代的搜索引擎和推荐系统往往结合了上下文查询和关键字查询的优点,以提供更加智能和用户友好的服务。
IR系统不告知相关内容,而是告诉existence和whereabouts,就是告诉存不存在相关内容,如果存在需要去哪找,就类似搜索引擎搜出来的实际上是一个个的超链接。用户如果想知道具体内容就需要点进去了解
如果document的内容非常符合用户需求,那么相关性就很高。然后用户根据超链接读取具体内容。理论上来说这是主观概念,取决于人的判断。query只是对于information need的表达
判断IR好不好就可以从relevance的程度上来决定,但是主体上还是由人判断,而且如果想智能一些的话需要机器学习等
通过提供的非结构化文本来创建结构化数据
比如要查询 a AND b NOT c,此时会先把有关ab的都找到,然后去除c。这样不好,非常慢,而且复数过去式等会影响查询
然后可以得到关联向量incidence vector,然后进行与或运算从而找到合适的document,但是对于更大的文本来说非常麻烦,难以扩展,矩阵非常大而且很sparse稀疏
而且会出现ambiguous query模糊查询,因为一个词有多个意思,不知道具体想找啥
term:术语,就是所需的词
先把文档里的terms都拆开,重复的也拆开,然后按照顺序排,一个term对应一个dicID,从上到下应该是以docID为次序
按照term按照abcd进行排序
进行字典化然后展示相关doc list,同时记住frequency,也就是list的长度
排序在倒排索引中非常重要,因为它允许快速查找和比较。字典中的词汇是按字母顺序排列的,这使得查找特定词汇变得高效。同样,倒排列表中的文档也是有序的,这有助于在执行查询时快速定位到包含特定词汇的文档。排序是合并过程中的关键,因为它允许我们通过简单的比较操作来确定哪些文档是两个词汇共同出现的。如果没有排序,我们需要对每个词汇的所有文档进行配对检查,这将大大降低效率。排序将提高效率
此时想找a AND b NOT c就可以直接通过ab的list里共同的部分,然后在c去掉c的list的内容,就可以了
AND是交集,OR是并集,NOT是包含a自身去掉a and b
# 老师的 def mergeAND(list1, list2): i, j = 0 , 0 merged = [] while i < len(list1) and j < len(list2): if list1[i] < list2[j]: i += 1 elif list1[i] > list2[j]: j += 1 else: merged.append(list1[i]) i += 1 j += 1 return merged def mergeOR(list1, list2): i, j = 0, 0 merged = [] while i < len(list1) or j < len(list2): if i < len(list1) and j == len(list2): merged.append(list1[i]) i += 1 elif j < len(list2) and i == len(list1): merged.append(list2[j]) j += 1 elif list1[i] < list2[j]: merged.append(list1[i]) i += 1 elif list2[j] < list1[i]: merged.append(list2[j]) j += 1 else: merged.append(list2[j]) i += 1 j += 1 return merged def mergeNOT(list1,list2): i, j = 0 , 0 merged = [] while i < len(list1) and j < len(list2): if list1[i] < list2[j]: merged.append(list1[i]) i += 1 elif list1[i] > list2[j]: j += 1 else: i += 1 j += 1 while i < len(list1): merged.append( list1[i] ) i += 1 return merged
# 自己的 def mergeAND(list1, list2): answer = [] i = 0 j = 0 while i < len(list1) and j < len(list2): if list1[i] == list2[j]: answer.append(list1[i]) i += 1 j += 1 elif list1[i] < list2[j]: i += 1 else: j += 1 return answer # print(mergeAND(words_map["a"], words_map["aa"])) def mergeOR(list1, list2): answer = set() i = 0 j = 0 while i < len(list1): answer.add(list1[i]) i += 1 while j < len(list2): answer.add(list2[j]) j += 1 answer = sorted(list(answer)) # answer = set(list1) | set(list2) return answer # print(mergeOR(words_map["a"], words_map["aa"])) def mergeNOT(list1, list2): answer = mergeAND(list1, list2) for num in answer: list1.remove(num) # answer = list(set(list1) - set(list2)) return list1
会有一个term列表,每个term屁股后面都跟着一个docID的list,就很像图的邻接表一样。一般来说要是找AND, OR啥的会先从小的list一个个遍历到大的list,是一位一位的向后找
在常规的list里,就和链表结构一样,前一个指向后一个,此时可以通过引用一种skip pointer来跳过一些没必要的节点从而节省时间
Tradeoff
注意权衡的使用,如果跳的多,跳跃跨度小,会让结果更准确,但是会有更多的跳跃次数;如果跳的少,跳跃跨度大,可能会错失一些正确的结果,但是耗时少。所以如何选择合适的跳跃幅度是很重要的
一般采取 L \sqrt{L} L 的作为跳跃间距 L是list的长度
决定跳过指针的位置需要在跳过频率、跳过指针比较的成本以及I/O成本之间找到一个平衡点。在实际应用中,可能需要根据具体的数据集特性、硬件性能和查询模式来调整跳过指针的策略。此外,随着技术的发展,比如固态硬盘(SSD)的普及,I/O成本可能会降低,这可能会影响跳过指针策略的有效性。
#!/usr/bin/env python3 import math import timeit from unittest import skip # define a class called "SkipList" class SkipList: def __init__( self, elements ): size = len(elements) self.start = None self.length = 0 sorted_elements = sorted( elements, reverse=True ) skip_frequency = round( math.sqrt( size ) ) for elem in sorted_elements: self.start = SkipNode( elem, self.start ) if self.length == 0: skip_to = self.start elif self.length % skip_frequency == 0: self.start.skip = skip_to skip_to = self.start self.length += 1 if skip_to != self.start: self.start.skip = skip_to # define the nodes that a SkipList will store class SkipNode: def __init__( self, elem, next_node ): self.element = elem # element stored in this node self.next_node = next_node # reference to the next node in the list self.skip = None # skip pointer: None if it doesn't have a skip pointer, otherwise it's a reference to another node def intersect( list1, list2 ): answer = [] # a list to store the answer (for now: we will return a SkipList at the end) p1 = list1.start # start the first reference (p1) at the beginning list 1 p2 = list2.start # start the second reference (p2) at the beginning list 2 # haven't reached the end of either list while p1 is not None and p2 is not None: # if p1 and p2 point to the equal elements, add it to the answer and move both pointers if p1.element == p2.element: answer.append( p1.element ) p1 = p1.next_node p2 = p2.next_node # p1's element is smaller, so move p1 elif p1.element < p2.element: p1 = p1.next_node # p2's element is smaller, so move p2 else: p2 = p2.next_node return SkipList(answer) def intersect_skip( list1, list2 ): answer = [] p1 = list1.start p2 = list2.start while p1 is not None and p2 is not None: if p1.element == p2.element: answer.append( p1.element ) p1 = p1.next_node p2 = p2.next_node elif p1.element < p2.element: if p1.skip is not None and p1.skip.element < p2.element: p1 = p1.skip else: p1 = p1.next_node else: if p2.skip is not None and p2.skip.emement < p1.element: p2 = p2.skip else: p2 = p2.next_node return SkipList(answer) # good idea to define a function to print the contents of a skip list # i've included an option to include printing details of where the skip pointers are (if include_skips is True) def print_skip_list( skiplist, include_skips=False ): n = skiplist.start while n is not None: print( n.element, end=' ' ) if include_skips and n.skip is not None: print( '(skip to {})'.format( n.skip.element ) ) elif include_skips: print() n = n.next_node print() # This is the code that will run when you execute this file with Python. if __name__=='__main__': list1 = SkipList( range( 0, 100000 ) ) list2 = SkipList( [ 2, 3, 46, 70, 7222, 999999 ] ) # check that the output is ok print( 'Output for intersect(...)' ) print_skip_list( intersect( list1, list2 ) ) print( 'Output for intersect_skip(...)' ) print_skip_list( intersect_skip( list1, list2 ) ) # measure the time to run the intersect(...) function time_taken = timeit.timeit( 'intersect( list1, list2 )', number = 10, globals = globals() ) print( 'Execution took {:.4f} seconds'.format( time_taken ) ) print('Execution took {:.4f} seconds'.format( timeit.timeit( 'intersect_skip( list1, list2 )', number = 10, globals=globals() ) ) )
之前的步骤
tokenization
normalization
thesauri soundex
是一些很常见的词语,比如a the of 等,而且不会影响内容含义等的单词,所以预处理的时候可以直接去掉避免影响
import porter import time # 初始化词干提取器 p = porter.PorterStemmer() start_time = time.process_time() # 读取停用词列表 with open('stopwords.txt', 'r') as f: stopwords = set(f.read().split()) # 读取文档集合 documents = [] with open('npl-doc-text.txt', 'r') as f: for line in f: if line.strip().isdigit(): doc_id = line.strip() sentence = [] while True: line = next(f).strip() if line.startswith('/'): break sentence.extend(line.split()) documents.append((doc_id, sentence)) # 计算每个文档中每个词的频率 def findF(sentence): f = {} for word in sentence: if word not in stopwords: word = p.stem(word) f[word] = f.get(word, 0) + 1 return f # 对每个文档进行词干提取和词频统计 doc_freqs = [] for doc_id, sentence in documents: f = findF(sentence) doc_freqs.append((doc_id, f)) # 按要求打印每个文档的词频 for doc_id, f in doc_freqs: if any(freq > 1 for freq in f.values()): print(doc_id + ':', end=' ') for word, freq in sorted(f.items(), key=lambda d: d[1], reverse=True): if freq > 1: print(word + ' (' + str(freq) + ')', end=' ') print() end_time = time.process_time() print(f'Total time: {end_time - start_time:.2f} seconds')
将文本中连续的词对作为短语进行索引。abcdefg -> ab,bc,cd,de,ef,fg。但是这样做虽然可能搜到我们提供的查询语句的内容,但是只是盲目的匹配到了目标短语,实际上内容含义不一定符合需求。而且所需内存很大,占用空间
存储某个term被多少doc包含,在每个doc里的位置是多少
一般双字和位置搭档使用
之前提到的是布尔查询相关,只会看doc有没有包含所需的term,只有相关和不相关,而且没有部分匹配的概念,而且没有根据相关性进行ranking,所以不大好,接下来将介绍向量模型来优化
info
TF:是term frequency,术语频率。term在某一个doc出现的次数越多,则越相关
IDF:是逆文档频率。在越多的doc中出现的term越像停词,所以需要IDF来消除出现次数过多的情况
TF-IDF是TF和IDF的乘积,每个doc里的每个term都有这个值,是特定的
TF: 对于每一个doc,其中的每一个term都有自己的TF。同一个doc里出现次数更多的term更重要。是独有的,依赖于term在单个doc出现的频率
IDF: 出现在全部doc中次数更少的term更重要。对于整个集合来说,每个term都有自己的IDF。是公共的,依赖于term在所有doc中的分布情况
分子是某个term出现的次数,分母是在此doc中所有的频率中最大的那一个
N是doc总数,ni是包含此term的doc的数量
warn
为什么要除以最大频率呢? 是为了确保长文档中的术语不会因为出现次数多而获得不合理的优势。如果只计算词频,那么在长文档中频繁出现的术语可能会比在短文档中偶尔出现的术语具有更高的权重,这可能导致检索结果的不准确性。通过除以最大频率,我们可以使词频在不同的文档之间达到一个平衡点,从而更准确地反映每个术语的重要性。最大频率是某个文档去除所有停词后的拥有最大相同词的数量 a a a b b c的就是3
如何计算还是类似上面的vector的做法,但是把01的值换成TF×IDF即可
TF-IDF会让某doc中出现次数更多的term产生更大的影响;同时减少整体集合中出现次数过多的term的影响
BM
和TF-IDF流程很像,只不过一些计算上有区别。相对于TF-IDF表现更好。简称为best match。
其中的IDF和TF很类似,但是多了一个doc长度规范化,这个保证较长的doc在查询的时候不会获得不公平的优势
在BM25模型中,如果一个词在文档中出现的频率很高,那么它的评分提升会逐渐饱和,也就是说,这个词的频繁出现不会带来评分上的显著优势。在评估文档与查询的相关性时,一个词在文档中出现的次数确实很重要,因为它表示了该词与文档内容的关联程度。然而,如果一个词在文档中过于常见,那么它可能是一个常用词或停用词,对区分文档内容的作用不大。因此,BM25通过调整TF的计算方式,使得高频词的评分提升逐渐饱和,从而更准确地评估文档与查询的相关性。
k一般取1,b取0.75
Cranfield Paradigm
relevant docs是相关的文档,但是相不相关由主观决定,所以需要专家来判断系统的有效性,从而产生了standard text collections:标准语料库,标准查询,相关性判断
- C:所有的docs. collection/corpus
- Rel:相关的docs,由专家提供.relevant sets
- Ret:检索出来的docs,IR提供. answer set/retrieved set
一般来说Ret的结果是ranked后的结果
这是最基本最广泛的评估指标,是许多其他指标的基础
P = R e l R e t R e t P=\frac{RelRet}{{Ret}} P=RetRelRet, 就是交集除以IR的结果
R = R e l R e t R e l R=\frac{RelRet}{{Rel}} R=RelRelRet, 是交集除以专家的结果对照上面的结果就是 P = 5/15,R = 5/10
The two metrics of precision and recall are often inversely related: as one
increases the other decreases.Precision will be high whenever a system is good at avoiding non-relevant documents.
- A system can achieve very high precision by retrieving very few documents.
Recall will be high whenever a system finds many relevant documents.
- A system can achieve 100% recall simply by retrieving all the documents in the collection.
保证精度更重要目前,对于IR来说
虽然基础精确度是一个不考虑排名的指标,但大多数信息检索系统实际上返回的是排序后的列表,而不是无序的文档集合。因此,用户更有可能首先查看列表的顶部,这意味着排名靠前的结果的精确度尤为重要。
简单来说就是对于前n个结果的精度的值,就是在前n个中,有多少是相关的。
对照上面的结果就是 P@1=1, P@3=2/3, P@10=4/10, P@15=5/15
性能受到Rel的值的影响更大,因为Rel越大,找出来的结果越多,查到的机会越大
R-precision 是一个相对于查询相关文档集合大小的指标,它考虑了所有相关文档。
P@n 是一个固定的指标,它只考虑前 n 个文档,而不考虑查询相关文档集合的大小
R-precision 更能反映检索系统在整个相关文档集合上的性能,而 P@n 则更关注检索系统在最前面的几个结果上的性能
R-precision的结果和P@n挂钩,因为此时Rel一共有10个,所以R-precision=P@10, 如果有13个那就=P@13
是IR最常用的指标,Mean Average Precision 最小平均精度指标。对于list中前部的doc会有所奖励,增加对应的某种权重,对于排名靠后的doc的权重设计的较低
先计算AP,结果是所有相关的P的值之和/Rel的数量
MAP就是在多次查询后的各AP的平均结果
binary preference
由于资源限制和评估方法的局限性,我们通常只能对检索结果的一部分进行人工相关性判断,而不是对所有可能相关的文档进行判断。这种不完整的判断可能导致一些实际上相关的文档被遗漏。
上面的数据是基于完整的相关性判断的,但是对于更大的collection,完整的判断会越来越困难越来越不常见,会出现不完整的判断,这意味着存在一些doc是没有被判断相关性的,所以需要一种新方法来计算精度
作用体现在如果存在大量的未被判断相关性的doc,会有更稳定和精确的结果
由于上图里面的所有内容都是基于全部Rel都有所判断,但是要是有一个没有被判断,那么AP的结果会有改变。解决方法是忽略掉没有被判断的doc,只看被成功判断的doc。
如果要加强判断,可以采取bpref10,就是分母变成10+R,R不变
Normalised Discounted Cumulated Gain
归一化贴现累计增益由bpref可以知道doc可以被判断为rel和non-rel,但是rel也分为相关程度,NDCG的作用就是来分级的
rel-doc在list的前方;越rel的越靠前
和上面P@n那几个有类似的做法,只不过Rel里面的内容会有一个rank值表示相关程度
有一个G列表表示收益,各位置对应的值就是rank值
有一个CG列表表示累计收益,各位置对应的值就是自己的rank加上上一层的CG值。
C
G
[
i
]
=
{
G
[
1
]
,
i
=
1
;
G
[
i
]
+
C
G
[
i
−
1
]
,
i
>
1
CG[i]=
DCG的值就是改进后的,第一层的值是本身,以后的值都是自己的值除以log2i加上上一层的DCG。
D
C
G
[
i
]
=
{
G
[
1
]
,
i
=
1
;
G
[
i
]
l
o
g
2
i
+
D
C
G
[
i
−
1
]
,
i
>
1
DCG[i]=
IDCG的值应该是根据Rel的rank从大到小往后排列,如果Rel的长度小于Ret的话,后面的就补0
用于IR评估的collection包括:docs,标准query,标准query的相关性判断
一系列问题:
一词多义,如何解决
多次同义,如何找出我们需要的所有的内容
是否可以使用多个modal帮助我们建立良好的IR系统
如何保证IR的运行速度。很小的模型可以采用AI或大语言模型帮助我们,中等的可采用BM25,再大型的就只能boolean query了,因为最快...
经典信息检索管道 :涵盖预处理、建立索引、排序等步骤。这种管道存在词汇不匹配、歧义、同义等问题。
经典管道的问题 :仅考虑文档内容,没有利用网络链接结构、URL等信息。同时,也没有利用机器学习和深度学习等最新进展。
更复杂的IR管道 :包括伪相关反馈、查询扩展、融合、学习排序等步骤,用于提高检索效果。
特征学习排序 :介绍了一些特征,如文本特征、PageRank、URL深度等,用于学习排序模型。
神经网络语言模型 :提及了BERT等模型,并介绍了其优势。然而,大语言模型的速度较慢。
ChatGPT等大语言模型 :用于生成式回答,但存在缺乏知识、无法引用来源等问题,不太适合直接用于信息检索。
结论 :经典IR管道存在局限,现代IR利用了更多技术来提高检索质量,但响应时间也是一个重要考量。
经典IR流程 :接着,文档介绍了传统IR系统的基本流程,包括文档预处理(如分词、语言处理)、索引创建、查询处理和排名方法(例如BM25算法)。这个流程是一个线性的管道模型,每个阶段的输出成为下一个阶段的输入。
经典IR流程的问题 :文档指出了传统IR流程存在的问题,如词汇不匹配、多义性和同义词问题。此外,还提出了对检索模型选择的疑问,是否应该使用单一模型还是多种模型的组合。
现代IR的挑战 :讲义进一步讨论了传统IR流程未能充分利用现代技术,如机器学习、自然语言处理(NLP)和自然语言理解(NLU)的问题。特别提到了大型语言模型(LLMs)如BERT、T5和GPT-4在NLP、NLU和机器翻译任务中的巨大进步,但也指出了这些模型速度慢的问题。
更复杂的IR流程 :为了解决上述问题,文档提出了一个更复杂的IR流程,包括伪相关反馈、查询扩展、融合和学习排名等技术。这些技术旨在通过不同的方法改进检索结果,提高相关文档的匹配概率。
PageRank和文档重要性 :文档还介绍了PageRank算法,这是一种根据网页链接结构来衡量文档重要性的方法,由Google的创始人开发。如果一个内容越重要,那么会有更多的其他连接链接到此内容的链接,会让此内容被更多知道
学习排名 :学习排名是一种利用机器学习技术对初步检索结果进行重排的方法,目标是将最相关的文档放在排名列表的顶部。这一过程会考虑比初始排名分数更多的信息,如文本特征、非文本特征、查询清晰度等。
神经语言模型 :文档提到了基于Transformer的神经语言模型,如BERT,以及由OpenAI发布的ChatGPT。这些模型通过学习大量文本中词语和短语之间的模式和关系来进行文档理解。
ChatGPT的问题 :尽管ChatGPT等大型语言模型在NLP任务中取得了巨大成功,但在信息检索领域,它们还存在一些问题,如不能提供确切的知识来源,输出可能是错误的,并且不能引用其信息来源。
结论 :最后,讲义总结了传统IR流程在现代IR方面的局限性,并指出了提高检索质量的多种技术,但响应时间是关键,因为涉及的数据量巨大。
伪反馈: query drift是指在使用伪相关反馈(Pseudo-Relevance Feedback)时可能出现的问题。伪相关反馈是一种技术,它假设排名靠前的文档是相关的,并据此调整检索算法的权重,以期望找到更多与用户认为相关的文档相似的文档。然而,如果这个过程没有得到适当的控制,可能会导致查询的主题逐渐偏离用户最初的意图,从而使得检索结果与用户的实际需求不再匹配。Query drift(查询漂移)是一个信息检索领域的概念,它描述了在进行多次检索或者在检索过程中不断调整查询时,查询的语义和方向可能发生偏离的现象。这种偏离可能会导致检索结果不再与用户最初的信息需求紧密相关。例如,如果用户最初查询的是关于“苹果”(水果)的信息,但是系统根据伪相关反馈主要返回了关于“苹果公司”的信息,那么随着时间的推移和多次迭代,查询可能会逐渐漂移,最终主要返回与苹果公司相关的信息,而不是关于水果的信息。这就是query drift的一个例子。为了避免query drift,信息检索系统需要采用一些策略来确保查询的稳定性和准确性,例如限制迭代次数、引入用户反馈机制、使用更复杂的查询理解技术等。这样可以确保检索结果始终与用户的实际需求保持一致。
查询扩展:
查询扩展(Query Expansion)是信息检索(IR)中的一种技术,旨在通过增加与原始查询词相关的其他术语来提高检索系统的性能。这种方法的目的是扩大检索范围,以便更全面地覆盖用户的信息需求,并提高检索到相关文档的概率。
在文档中提到的查询扩展方法有以下几种:
使用手动构建的词典 :例如WordNet,它是一个大型的英语词典数据库,可以用来找到与原始查询词同义或相关的术语。通过这种方式,查询可以被扩展为包含更多可能与用户需求相关的词汇。
自动生成的词典 :通过从外部语料库(如网络爬取的数据或维基百科)中提取数据来构建词典。这种方法可以捕捉到更广泛和更新的词汇使用情况。
词嵌入 :利用词嵌入技术(如word2vec、GloVe、ELMo和基于BERT的嵌入)将词语表示为向量。这些向量能够捕捉词语之间的语义关系,从而帮助找到与查询词在语义上相近的其他词汇。
查询日志挖掘 :搜索引擎可以通过分析之前用户对于相同查询词的使用行为来挖掘相关术语。这种方法基于用户实际的搜索行为,可能更贴近用户的真实需求。
目标语料库基础的技术 :基于正在搜索的文档集合,这类技术可以分为两类:
查询扩展的好处在于能够提高检索系统的查全率(recall),即使用更广泛的词汇覆盖来捕获更多可能相关的文档。然而,这也可能导致查准率(precision)的下降,因为扩展的查询可能会检索到一些不相关的文档。因此,查询扩展需要谨慎使用,以确保在提高查全率的同时,不会过多地牺牲查准率。
Fusion:
data fusion,collection fusion results aggregatio越来越流行
combining the outputs of multiple 不同的IR系统或算法,把他们的结果合并成一个排序结果集,在响应式查询的时候显示给用户。大家希望这种组合出来的结果集比单个结果集的质量更好,higher precision higher recall...
过程大概是用户输入查询,fusion引擎利用多个IR系统进行查询,然后再对结果进行整合输出
返回的结果列表是根据每个doc的分数排序的,和内容无关,得分是根据每个IR自己的逻辑来得到的。算法之间的主要区别在于它们在分配分数时考虑了哪些信息。
- Metasearch:由自主的完整的搜索引擎返回的结果集的融合
- Distributed IR:多个小IR设计成co-operate的,每个IR处理collection的不同子集
- Internal Metasearch:许多算法对同一个collection进行搜索
开发fusion算法的时候要考虑到doc集合(corpora)有多少重叠,重叠的程度会让处理最终结果的时候有所影响。有三种类型
disjoint database 不相交的数据库。搜索的内容是独立的doc集合,互相之间没有共同文档。同一个doc不会被多个不同的IR返回。分布式IR采用这个实现。此形态的语料库被称作Collection Fusion
identical database 相同数据库。每个IR接收到的查询集合都是同一组doc,所以结果doc会出现在多个结果集里,同时出现在结果集里的doc会更被认为具有相关性Rel。Internal Metasearch更常用这个。这是重点方法,也被乘坐 *Data Fusion *
overlapping database 重叠数据库。这个是每个IR使用的doc集合有一定程度上的重叠,doc同样会出现在多个结果集中,但是重复出现的doc不一定是高度相关的。External Metasearch更多的涉及到这种。
Skimming effect
Chorus effect
Dark Horse 黑马effect
采取round robin的方法从每个input set的顶部取出一个doc,然后把他加到fusion的结果集中,选择的文档是尚未包含在fusion结果集中的排名最高的doc,但是效率比较低,因为它假设每个不同的结果集的质量是相等的,但是好的结果集的结果可能会被削弱
Borda-Fuse 是基于一个选举系统,当少数投票者(输入系统)为许多候选人(文档)投票时使用。
每个投票者按偏好顺序对一组候选人进行排名。
对于每个投票者,排名第一的候选人获得c点,排名第二的获得c-1点,以此类推。
如果候选人没有被投票者排名,投票者的剩余点数将平均分配给未排名的候选人。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。