BM25算法详解

BM25算法介绍

BM25(Best Matching)算法是当前信息检索领域主流的文本匹配算法,主要内容是计算query到文档集合的相似度得分。BM25可以视作Tf-IDF算法的优化。

TF-IDF算法

t f − i d f s c o r e = t f × i d f = 某文档中目标词出现的数量 某文档总词数 × l o g 文档总数 包含目标词的文档数量 tf-idf_{score}=tf×idf=\frac{{某文档中目标词出现的数量}}{{某文档总词数}}×log\frac{{文档总数}}{{包含目标词的文档数量}} tfidfscore=tf×idf=某文档总词数某文档中目标词出现的数量×log包含目标词的文档数量文档总数

BM25算法

BM25算法主要有下面三个部分组成:

  • query中每个单词的重要性(可以理解为idf部分)

  • query中每个单词与文档之间的相关性(对tf部分的优化,并考虑了文档的长度)

  • query中每个单词与query本身的相关性(该部分只有在当query很长时才会使用)

TF-IDF和BM25比较

  • BM25在tf-idf的基础上增加了几个可调节的参数,使其在应用中更具灵活性和实用性。

  • BM25对于词频、逆文档频率以及字段长度的归一化具有更合理的定义。

  • 在词频的重要性方面,BM25有一个上限,即随着词频增长,词的重要性增长程度会被限制。

BM25的公式

s c o r e ( Q , d ) = ∑ i = 1 n w i R ( q i , d ) {\rm{score}}(Q,d) = \sum\limits_{i = 1}^n {{w_i}R({q_i},d)} score(Q,d)=i=1nwiR(qi,d)

其中 Q Q Q表示一条query, q i q_i qi 表示query中的第 i i i 个词, w i w_i wi表示自身的重要性, d d d 表示待匹配的文档。

自身重要性

w i w_i wi 的计算方式同idf类似:

w i = i d f q i = l o g N − d f i + 0.5 d f i + 0.5 w_i=idf_{q_i}=log\frac {{N-df_i+0.5}}{{df_i+0.5}} wi=idfqi=logdfi+0.5Ndfi+0.5

其中 N N N表示待匹配的全部文档数, d f i df_i dfi为包含了 q i q_i qi的文档总数。对于某个 q i q_i qi,包含 q i q_i qi的文档数越多,说明该 q i q_i qi越不重要。 w i w_i wi 一定程度上可以用来刻画 q i q_i qi与文档之间的相关性。

单词与文档之间的相关性

单词与文档之间相关性的刻画依赖一个重要发现:词频和相关性之间的关系是非线性的。即每个词和文档的相关性分数不会超过某个阈值,当词出现的次数达到一个阈值之后,其影响就不再线性增长,而这个阈值和文档本身相关。因此在刻画单词与文档的相关性时,BM25时这么设计的:

S ( q i , d ) = ( k 1 + 1 ) t f q i d K + t f q i d S(q_i,d)=\frac {{(k_1+1)tf_{q_id}}}{K+tf_{q_id}} S(qi,d)=K+tfqid(k1+1)tfqid

K = k 1 ( 1 − b + b × L d L a v e ) K=k_1(1-b+b×\frac{L_d}{L_{ave}}) K=k1(1b+b×LaveLd)

其中 t f q i d tf_{q_id} tfqid表示单词 q i q_i qi在文档d中的词频, L d L_d Ld表示文档d的长度, L a v e L_{ave} Lave表示所有文档的平均长度,变量 k 1 k_1 k1表示为正的参数,用来标准化文章词频的范围。b是另一个参数且0

单词与query之间的相关性

只有当query很长时,才需要刻画单词与query之间的相关性。公式为:

S ( q i , Q ) = ( k 3 + 1 ) × t f q i q k 3 × t f q i q S(q_i,Q)=\frac {(k_3+1)×tf_{q_iq}}{k_3×tf_{q_iq}} S(qi,Q)=k3×tfqiq(k3+1)×tfqiq

其中 q i q_i qi表示query中的单词, t f q i q tf_{q_iq} tfqiq表示单词 q i q_i qi在query中出现的频数。 k 3 k_3 k3是一个可调节的正参数,用来矫正query中的词频范围.

整体公式

s c o r e ( Q , d ) = ∑ i = 1 n ( l o g N − d f i + 0.5 d f i + 0.5 × ( k 1 + 1 ) t f q i d K + t f q i d × ( k 3 + 1 ) × t f q i q k 3 × t f q i q ) {\rm{score}}(Q,d) = \sum\limits_{i = 1}^n ({{log\frac {{N-df_i+0.5}}{{df_i+0.5}}}×\frac {{(k_1+1)tf_{q_id}}}{K+tf_{q_id}}×\frac {(k_3+1)×tf_{q_iq}}{k_3×tf_{q_iq}}}) score(Q,d)=i=1nlogdfi+0.5Ndfi+0.5×K+tfqid(k1+1)tfqid×k3×tfqiq(k3+1)×tfqiq

参数经验值

根据实验, k 1 k_1 k1 k 3 k_3 k3一般取值1.2~2。b取值0.75。

实例程序 使用gensim下的bm25模块

from gensim.summarization import bm25
import jieba


def test_gensim_bm25():
    # 给定多个文档
    corpus = ["5万元资金,该做什么行业",
              "美增加汽车关税,为何汽车价格不降反升",
              "汽车销售人员的服务水准非常烂,该怎么解决",
              "未来房价会跌到什么程度",
              "十万元能上路的汽车,买什么比较好"]
    # 对每个文档切词(示例作用  不进行去停用词)
    corpus_cut = [jieba.lcut(line) for line in corpus]

    # 生成模型
    bm25Model = bm25.BM25(corpus_cut)

    test_query = "你想买汽车吗"  # query
    test_query_cut = jieba.lcut(test_query)

    scores = bm25Model.get_scores(test_query_cut)  # 计算相似度得分(与corpus_cut顺序对应)
    print("scores", scores)
    # 输出
    for i, j in zip(scores, corpus):
        print('分值:{},原句:{}'.format(i, j))
    print('\n')


if __name__ == '__main__':
    test_gensim_bm25()

你可能感兴趣的:(算法,机器学习,nlp)