# -*- coding: utf-8 -*- from __future__ import unicode_literals import math class BM25(object): def __init__(self, docs): self.D = len(docs) self.avgdl = sum([len(doc)+0.0 for doc in docs]) / self.D self.docs = docs self.f = [] self.df = {} self.idf = {} self.k1 = 1.5 self.b = 0.75 self.init() 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) 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))) return score def simall(self, doc): scores = [] for index in range(self.D): score = self.sim(doc, index) scores.append(score) return scores