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)的計算公式。
式子中,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文檔相關性計算公式:
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