NLP—文本相似度算法BM25

BM25算法,通常用来做检索相关性评分。首先对一个查询Query进行分词得qi,对每个搜索结果文档d,计算qi与文档d的相关性得分。最后将所有的qi进行加权求和,从而得到查询Query与文档d的相关性得分。


公式中,Q表示查询Query,qi表示查询被解析得到的分词qi,d表示搜索结果文档d,Wi表示分词qi的权重,R(qi,d)表示分词qi与文档d的相关性得分。定义一个词与文档相关性的权重方法有很多,较常用的有IDF。


其中N表示全部文档数,n(qi)表示包含分词qi的文档数,从公式中可以发现当包含分词qi的文档数越多时,qi的权重越低,即当很多文档都有单词qi时,说明qi比较常用,没有特别代表意义,所以分词qi拿来做相关性判断时重要性比较低。下面是qi与文档d相关性得分R(qi,d)的计算公式。

NLP—文本相似度算法BM25_第1张图片

式子中,k1、k2、b为调节因子,通常根据经验设置为k1=2,b=0.75,fi为qi在d中出现的频率,qfi为qi在查询Query中出现的频率。dl为文档d的长度,avgdl为所有文档的平均长度。在多数情况下qi只在查询中出现一次,qfi=1,所以公式简化为:


从K的公式中发现,b越大文档长度对相关性得分的影响也越大,而文档的长度越长,K越大,则相关性得分越小。所以参数b用来控制文档长度对相关性得分影响的大小。所以当文档较长时,包含分词qi的概率越大,因此同等频率的情况下,长文档与qi的相关性不如短文档与qi的相关性高。综上BM25文档相关性计算公式:

NLP—文本相似度算法BM25_第2张图片

def init(self):
        for doc in self.docs:
            tmp = {}
            for word in doc:
                if not word in tmp:
                    tmp[word] = 0
                tmp[word] += 1
            self.f.append(tmp)
            for k, v in tmp.items():
                if k not in self.df:
                    self.df[k] = 0
                self.df[k] += 1
        for k, v in self.df.items():
            self.idf[k] = math.log(self.D-v+0.5)-math.log(v+0.5)
##计算出每个词的频次来,然后利用之前的公式计算idf

def sim(self, doc, index):
        score = 0
        for word in doc:
            if word not in self.f[index]:
                continue
            d = len(self.docs[index])
            score += 
            (self.idf[word]*self.f[index][word]*(self.k1+1)/      (self.f[index][word]+self.k1*(1-self.b+self.b*d/ self.avgdl)))

            #利用之前的计算bm25的公式计算。
        return score
def simall(self, doc):#该doc(也就是之前提到的搜索预料)与预保存的文档)逐个比较相似情况。返回相似值的列别。
        scores = []
        for index in range(self.D):
            score = self.sim(doc, index)
            scores.append(score)
        return scores

参考文档:https://blog.csdn.net/kamendula/article/details/51756396

你可能感兴趣的:(NLP,NLP,文本相似度,BM25,自然语言处理,文本处理)