首页 > 其他分享 >从TF-IDF 到BM25, BM25+,一文彻底理解文本相关度

从TF-IDF 到BM25, BM25+,一文彻底理解文本相关度

时间:2024-02-02 15:33:22浏览次数:31  
标签:term weight BM25 doc TF 文档 IDF

相关性描述的是⼀个⽂档和查询语句匹配的程度。我们从搜索引擎召回时,肯定希望召回相关性高的数据,那么如何来量化相关度呢。

首先,我们定义,一个文档doc,由多个词语 term 组成。

最早,通过最简单的TF-IDF来衡量。

TF-IDF

朴素的思想,相关度应该是词语权重、文档权重的融合。

  • 词频 TF(Term Frequency)朴素的理解,一个词语term在一个doc中出现的频率越高,那么doc的相关性也越高。

$$ \text{TF}(t, d) = \frac{\text{词t在文档d中的出现次数}}{\text{文档d的总词数}} $$

  • 逆向文档频率 IDF(Inverse Document Frequency),通俗的解释每个检索词在索引中出现的频率,频率越高,相关性越低。 比如"的“ 这样的词语,可能每个doc都有,相反一些专业术语出现的文档数很少,这些文档的权重就很高。

$$ \text{IDF}(t, D) = \log\left(\frac{\text{文档集合D的总文档数}}{\text{包含词t的文档数} + 1}\right) $$

  • TF和IDF结合起来计算一个词的TF-IDF值,公式为:

$$ \text{TF-IDF}(t, d, D) = \text{TF}(t, d) \times \text{IDF}(t, D) $$

TF-IDF的优点在于简单有效,但它也有一些局限性,例如不考虑词序和上下文信息。

BM25(Best Matching 25)

BM25是一种用于文本信息检索的算法,是BM(Best Matching)系列中的一员。它在信息检索领域中广泛应用,特别是在搜索引擎中用于排序搜索结果。整体而言BM25 就是对 TF-IDF 算法的改进**,以下是BM25算法的公式:

$$ \text{BM25}(D, Q) = \sum_{i=1}^{n} \frac{{(k+1) \cdot f_i}}{{f_i + k \cdot (1 - b + b \cdot \frac{{\lvert D \rvert}}{{\text{avgdl}}})}} \cdot \log\left(\frac{{N - n_i + 0.5}}{{n_i + 0.5}}\right) $$

  • D:文档
  • Q:查询
  • n:查询中的term数
  • N:文档集中的文档数
  • fi​:文档中term i的频率
  • ni​:包含术语 term i 的文档数
  • DL:文档长度(term数)
  • AVG_DL:文档集的平均长度(term数量)

对于 TF-IDF 算法,TF(t) 部分的值越大,整个公式返回的值就会越大,如果一个doc文章很长,词语很多,tf频率就会很大。BM25 针对这个问题做了优化,通过b参数,对文档长度进行打压,随着TF(t) 的逐步加大,该算法的返回值会趋于一个数值。

BM25的优势在于它对于长文本和短文本的处理更为灵活,并且能够适应不同查询的特征。这些可调整的参数使得BM25能够通过调整来适应不同的信息检索场景。

  • b 参数 ,b 默认 0.75(经验值),主要是对长文档做惩罚,如果不希望文档长度更大的相似度搜索更好,可以把 b 设置得更大,如果设置为 0,文档的长度将与分数无关。从下图可以看到,b=0时,L与分数无关,b=1时,L越大,分数打压越厉害。

  • k 参数, 默认值 1.2,会影响词语在文档中出现的次数对于得分的重要性,如果希望词语出现次数越大,文档越相关,这个参数可以设置更大。

BM25+

BM只考虑了term和doc的维度,对query 里term的频率没有考虑,BM25+(Best Matching 25 Plus)正是基于这一点,来改进BM25算法,以下是BM25+的公式,以及每个参数的含义:

$$ \text{BM25+}(D, Q) = \sum_{i=1}^{n} \frac{{(k_1+1) \cdot f_i \cdot (k_3+1) \cdot qf}}{{(f_i + k_1 \cdot (1 - b + b \cdot \frac{{\lvert D \rvert}}{{\text{avgdl}}})) \cdot (k_3 + qf)}} \cdot \log\left(\frac{{N - n_i + 0.5}}{{n_i + 0.5}}\right) $$

相比BM25,增加k3 和qf,
其中:

  • qf:查询中词项的频率(Query Term Frequency)
  • k3:控制查询中词项频率对得分的影响程度的参数,下面是不同的k3,在不同的query weight情况下,对分数的影响

![[Pasted image 20240202151809.png]]

  • 注意k1就是BM25里的k

这里的qf,我们可以当做term weight来使用,训练term weight模型,来对重点的term做激励。

谷歌的End-to-End Query Term Weighting

谷歌在2023年发布了一篇论文,介绍如何端到端学习term weighting。

背景是term based recall的方法相对于embedding recall来说很繁琐,好处就是时延低且对基建要求低,向量召回会遇到分不清楚query中哪个词是核心词的问题,导致召回出现了非核心词的结果。

谷歌论文

在左侧,展示了传统的信息检索(IR),所有的term都是默认的权重,在右侧,我们插入了一个BERT模型来评估term的权重,BM25+ 打分时将这个weighting作为query freq,就是上面说的qf。

可以看谷歌论文的打分:

上面的$f(T_i, T,w)$ 就是模型学习的权重。

附录

可视化不同参数变化,BM25分数的变化

import numpy as np
import matplotlib.pyplot as plt


def calculate_bm25(tf, term_weight, corpus_freq, total_docs,
                   k1=1.5, k3=8, doc_len=100, avg_doc_len=120, b=0.75):
    idf = np.log((total_docs - corpus_freq + 0.5) / (corpus_freq + 0.5) + 1)  # IDF计算
    K = k1 * ((1.0 - b) + b * doc_len / avg_doc_len + tf)
    tf_term = tf * (k3 + 1) * term_weight / (K * (k3 + term_weight))  # TF计算

    return idf * tf_term  # BM25计算


def visualize_bm25_scores_k3(term_weight_values, tf_values, corpus_freq, total_docs, k1=1.5):
    # Plotting
    plt.figure(figsize=(12, 8))

    for k3 in np.linspace(2, 10, 5):
        scores = [calculate_bm25(5, query_weight, corpus_freq, total_docs, k1=k1, k3=k3)
                  for query_weight in term_weight_values]
        plt.plot(term_weight_values, scores, label=f'k3={k3}')

    plt.title('BM25 Scores with Different Query_freq Values (b=0)')
    plt.xlabel('Query weight')
    plt.ylabel('BM25 Score')
    plt.legend()
    plt.show()

def visualize_bm25_scores_b(term_weight_values, tf_values, corpus_freq, total_docs, k1=1.5):
    # b 用于惩罚文档长度
    plt.figure(figsize=(12, 8))

    doc_lens = np.linspace(100, 1000, 10)
    avg_doc_len = 100
    L = [doc_len /avg_doc_len for doc_len in doc_lens]
    for b in [0, 0.5, 0.75, 1.0]:
        scores = [calculate_bm25(5, 1, corpus_freq, total_docs, k1=k1, b=b, doc_len=doc_len)
                  for doc_len in doc_lens]
        plt.plot(L, scores, label=f'b={b}')

    plt.title('BM25 Scores with Different b')
    plt.xlabel('L(doc_length/avg_doc_length')
    plt.ylabel('BM25 Score')
    plt.legend()
    plt.show()



term_weight_values = np.linspace(0.1, 10, 10)  # query weight
corpus_freq = 500  # 包含term的文档数量,文档频率
total_docs = 5000000  # 总文档数量
tf_values = list(range(1, 101))
visualize_bm25_scores_k3(term_weight_values, tf_values, corpus_freq, total_docs)

visualize_bm25_scores_b(term_weight_values, tf_values, corpus_freq, total_docs)

标签:term,weight,BM25,doc,TF,文档,IDF
From: https://www.cnblogs.com/xiaoqi/p/18003267/bm25

相关文章

  • Run a tfx pipeline using kubeflow pipeline
    1.whatiskubeflowpipelinefortfxpipeline?kubeflowpipelineisanochetratoroftfxpipeline,whichrunsonakubernetescluster.LocalDagRunerisanorchetratoroftfxpipeline,whichrunslocal.#runatfxpipelineusgingLocalGagRunnertfx.orc......
  • ‘utf-8’ codec can’t decode byte 0xe5 in position 1023: unexpected end of data
    使用pycharm在本地调试项目的时候,发现偶尔会出现下面的错误,导致项目无法继续执行下去。但是不适用debug模式,而使用运行模式的时候不会有这样的问题。E:\pycharm_pro\PyCharm2019.2.3\helpers\pydev\_pydevd_bundle\pydevd_comm.pyr=r.decode('utf-8')UnicodeDecodeError:......
  • 【Loading】ctfshow_WriteUp | _萌新
    萌新_密码1题目密文:53316C6B5A6A42684D3256695A44566A4E47526A4D5459774C5556375A6D49324D32566C4D4449354F4749345A6A526B4F48303D提交格式:KEY{XXXXXXXXXXXXXX}分析所有字符由数字和ABCDEF组成,先用HEX解码得到S1lkZjBhM2ViZDVjNGRjMTYwLUV7ZmI2M2VlMDI5OGI4ZjRkOH0=。......
  • 执行./ch-mount.sh -m rootfs/时报错: /bin/bash^M 解释器错误: 没有那个文件或目录
    执行./ch-mount.sh-mrootfs/时报错:/bin/bash^M解释器错误:没有那个文件或目录原因是./ch-mount.sh这个文件在Windows下编辑过,在Windows下每一行结尾是\n\r,而Linux下则是\n,所以才会有多出来的\r。 解决办法:先执行下面的命令sed-i's/\r$//' ch-mount.sh该指令会把......
  • [BJDCTF2020]The mystery of ip
    [BJDCTF2020]Themysteryofiphint页面的源代码里发现提示应该是和IP相关,有可能用到XFF请求头,遂用BP抓包修改了XFF之后,被成功执行,XFF可控,代码是php代码,推测:PHP可能存在Twig模版注入漏洞Smarty模板的SSTI漏洞(主要为Flask存在Jinjia2模版注入漏洞)添加模板算式,{{7*7}}成......
  • GLTF OverView
    ​​​​​​​​​​​​​​​​参考glTF™2.0Specification(khronos.org)ReferenceGuides-TheKhronosGroupInckhronos.org/files/gltf20-reference-guide.pdfgltfOverview中文翻译-腾讯云开发者社区-腾讯云(tencent.com)......
  • Ctfer-Sql注入从0到0.1
    一、判断是否存在sql注入漏洞1.单引号判断http://www.xxx.com/xxx.asp?id=10'如果出现错误提示 youhaveanerrorinyoursqlsyntax则该网站可能就存在注入漏洞。二、判断注入类型字符型and数字型数字型:Or判断(or跟and判断方法不一样的,and是提交返回错误才有注入点,......
  • 外汇资金盘HTFX与盈开量化科技内外勾结,篡改服务器数据,欺诈客户
    近期,神探不断收到各大投资人与技术大咖的投稿曝光:外汇资金盘HTFX与盈开量化内外勾结,通过篡改服务器数据,来实现其盈利的商业模式,存在欺诈客户的行为。早前神探已经多方位分析过券商HTFX的一些前世今生,并对此提出了几大疑点与判断。再次声明,文中所提出的所有资料皆是从世界各大权威性......
  • Pass Artifact between tfx compoents when running with kubeflow pipeline
    WhatisArtifact?AnArtifactisafileordirectoryproducedbyatfxcomponent,whichcanbepassedtoadownstreamcomponent,andthenthedownstreamcomponentcanuseit.HowdoestfxpassanArtifactbetweencomponents?tfxpipelinehasanargument......
  • golang中 UTF-8 和GBK格式的转换
    funcmain(){ str:="测试" utf8By:=[]byte(str) gbkBy,_:=Utf8ToGbk(utf8By) //直接打印用string转类型的gkb字节数组,会乱码 fmt.Println("打印GBK",string(gbkBy)) fmt.Println("UTF8字节长度:",len(utf8By),"GBK字节长度:",len(gbkBy)) ......