bm25 是一种用来评价搜索词和文档之间相关性的算法,它是一种基于概率检索模型提出的算法。

它的出现主要是解决TF-IDF算法中 TF的影响可无限增大的不足,本质上 BM25是基于TF-IDF并做了改进的算法。

如图所示,传统的TF-IDF算法中 词频的影响程度是无限增大的,换而言之就是关键词出现的越频繁,TF-IDF相关度就越高。稍微有点简单粗暴;而BM25算法就是让词频的影响到达一定程度后趋于收敛,相比而已更加符合自然语言相关程度的实际逻辑。

参考:

《搜索中的权重度量利器: TF-IDF和BM25》:https://mp.weixin.qq.com/s/T9lFJDCCEwd_PfpPbjklDA

《NLP之TF-IDF与BM25原理探究》:https://www.cnblogs.com/johnnyzen/p/11298273.html

已经非常详细了,我这儿写了一个JAVA的实现,IDF字典是直接使用的 jieba分词项目中的文件。

公式:   Similarity(word|documents)=IDFScore∗(k+1)∗tf / k∗(1.0−b+b∗|D|avgDl)+tf

package com.zjf.seo.core.algorithm;import java.util.List;
import java.util.Map;import com.zjf.seo.core.utils.StringUtils;/*** BM25 相关度算法实现* @author zhaojunfu* * 公式:   Similarity(word|documents)=IDFScore∗(k+1)∗tf / k∗(1.0−b+b∗|D|avgDl)+tf* **/
public class BM25 {//常量k,用来限制TF值的增长极限 默认1.2private double k = 1.2;//b是一个常数,它的作用是规定L对评分的影响有多大 private double b;/*** BM25 相关度算法实现* @param k 常量k,用来限制TF值的增长极限 默认1.2* @param b b是一个常数,它的作用是规定L对评分的影响有多大 */public BM25(double k, double b) {super();this.k = k;this.b = b;}/*** BM25 相关度算法实现 k=1.2* @param b b是一个常数,它的作用是规定L对评分的影响有多大 */public BM25(double b) {super();this.b = b;}/*** 计算 关键词 在文档中的相关值* @param idf 关键词的逆文档频率* @param tf  关键词在文档中的词频* @param L  当前文档长度/平均文档长度* @return*/public double cal(double idf,double tf,double L){double v = 0;v= (idf*(k+1)*tf) /(k * (1.0-b+b*L)+tf);return v;}/*** 计算 关键词 在文档中的相关值* @param keywords 关键词* @param doc 关键词所在文档的全文* @param docs 所有文档集* @param idfMap idf字典表* @return*/public double cal(String keywords,String doc,List<String> docs,Map<String,Double> idfMap){Double idf = idfMap.get(keywords);if(null==idf) idf=1.0d;Double tf =  (double)StringUtils.count(doc, keywords)*keywords.length() / doc.length();double avgLength = calAvgLength(docs);Double L =  (double)doc.length()/avgLength;return cal(idf,tf,L);}private double calAvgLength(List<String> docs) {if(docs==null || docs.size()<=0) {throw new RuntimeException("给定文档集不能为空");}int s =  0;for(String d:docs){s+=d.length();}return (double)s/(double)docs.size();}
}

测试效果:

package com.zjf.seo.core;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import com.zjf.seo.core.algorithm.BM25;import junit.framework.TestCase;public class BM25Test  extends TestCase{public void test(){BM25 bm25= new BM25(1.2,0.75);String keywords = "租房";List<String> docs = new ArrayList<String>();docs.add("深圳保障房计划给出最新公租房、安居房消息!没房的赶紧来看!");docs.add("在深圳,有多少人每个月最大的一笔支出就是房租。所以大家都挺关心公租房消息的,毕竟公租房能让房租这笔支出少一些又或者是期待安居房能让自己有点买房的机会。");docs.add("深圳的保障房工作近几年进展就很不错。从最初的廉租房、公租房、经济适用住房,发展到今天的公租房、安居房和人才住房。");docs.add("保障群体从最初的户籍低收入家庭,扩展到现在的户籍中低收入家庭、人才家庭,以及为城市提供基本公共服务的公交司机、环卫工人和先进制造业职工等群体");docs.add("好消息,新版租房合同来袭,在深圳租房的你有福了!");Map<String,Double> idfMap = new HashMap<String,Double>();loadIDFMap(idfMap, this.getClass().getResourceAsStream("idf_dict.txt"));for(String doc:docs){System.out.println(keywords+"-bm25计算:"+bm25.cal(keywords, doc, docs, idfMap));}}private static void loadIDFMap(Map<String,Double> map, InputStream in ){BufferedReader bufr;try{bufr = new BufferedReader(new InputStreamReader(in));String line=null;while((line=bufr.readLine())!=null) {String[] kv=line.trim().split(" ");map.put(kv[0],Double.parseDouble(kv[1]));}try{bufr.close();}catch (IOException e){e.printStackTrace();}}catch (Exception e){e.printStackTrace();}}
}

测试结果: 使用参数 k=1.2  b=0.75     

可以看出文档5的“租房”相关度最高,而文档4因为根本没出现过“租房”相关度为0。

参数b的作用是调节文档长度的影响,值越大则最终值对于文档长度越敏感。

1、深圳保障房计划给出最新公租房、安居房消息!没房的赶紧来看!

租房-bm25计算:1.5994173445298407

2、在深圳,有多少人每个月最大的一笔支出就是房租。所以大家都挺关心公租房消息的,毕竟公租房能让房租这笔支出少一些又或者是期待安居房能让自己有点买房的机会。
租房-bm25计算:0.6491108274274898

3、深圳的保障房工作近几年进展就很不错。从最初的廉租房、公租房、经济适用住房,发展到今天的公租房、安居房和人才住房。
租房-bm25计算:1.5675707523417919

4、保障群体从最初的户籍低收入家庭,扩展到现在的户籍中低收入家庭、人才家庭,以及为城市提供基本公共服务的公交司机、环卫工人和先进制造业职工等群体
租房-bm25计算:0.0

5、好消息,新版租房合同来袭,在深圳租房的你有福了!
租房-bm25计算:3.8257399202973743

收敛效果测试:

docs.add("好消息,租房新版租房合同租房来袭,在深圳租房租房的你有福了租房!");docs.add("好消息,租房新版租房合同租房来袭,在深圳租房租房的你有福了租房!租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租");docs.add("好消息,租房新版租房合同租房来袭,在深圳租房租房的你有福了租房!租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租房租");

当这三个文档去计算 “租房”相关度时,结果如下:(此时 k=1.2 , b=0  忽略文档长度的影响)

租房-bm25计算:4.87433980096381
租房-bm25计算:8.507938561682286
租房-bm25计算:8.831724589865122

可以发现 词频到了一定程度就趋于收敛了,再使劲重复 租房  ,相关度提升地就不明显了。

如果将b 改回0.75  ,即考虑篇幅的因素,结果如下:

租房-bm25计算:7.659676830085987
租房-bm25计算:6.500512115234726
租房-bm25计算:4.717086835182325

可以发现  复读机式的重复关键词,相关度反而低了,这是因为后面两个文档篇幅远大于整个搜索集的平均篇幅,同时因为词频的影响收敛,所以整体值就降低了。

搜索引擎相关度算法 -BM25 JAVA实现相关推荐

  1. bm25算法Java代码_搜索引擎相关度算法 -BM25 JAVA实现

    bm25 是一种用来评价搜索词和文档之间相关性的算法,它是一种基于概率检索模型提出的算法. 它的出现主要是解决TF-IDF算法中 TF的影响可无限增大的不足,本质上 BM25是基于TF-IDF并做了改 ...

  2. 网页浏览器的搜索引擎及算法(包括网页,App内,后台数据等)

    网页上的搜索引擎,App内的应用框搜索及后台的数据搜索等? 中国两大主流搜索引擎:百度和Google.微软的搜索引擎:http://m2.cn.bing.com/ 搜索引擎要素:链接的质量和数量,排名 ...

  3. 【图】2015年Google搜索引擎排名算法(完整版)

    2015年中旬,国外SEO网站发布了一份2015年Google搜索引擎排名算法的最新数据,从各个角度看待搜索引擎算法排名影响因素的变化.其组织每两年都会成立一个SEO专家调查小组,针对"Go ...

  4. 有赞搜索引擎实践(算法篇)

    有赞搜索引擎实践(算法篇) 18 April 2016 1. 搜索算法总体架构 在上篇文章(工程篇)中, 我们介绍了有赞搜索引擎的基本框架. 搜索引擎主要3个部件构成. 第一, hadoop集群, 用 ...

  5. 【LeetCode-面试算法经典-Java实现】【015-3 Sum(三个数的和)】

    [015-3 Sum(三个数的和)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given an array S of n integers, are there ...

  6. java实现 k nn算法_数据挖掘(二)——Knn算法的java实现

    本文接数据挖掘-基于Kmeans算法.MBSAS算法及DBSCAN算法的newsgroup18828文本聚类器的JAVA实现(上). (update 2012.12.28 关于本项目下载及运行的常见问 ...

  7. 负载均衡算法及其Java代码实现

    负载均衡算法及其Java代码实现 什么是负载均衡 负载均衡,英文 名称为Load Balance,指由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须 ...

  8. 【LeetCode-面试算法经典-Java实现】【109-Convert Sorted List to Binary Search Tree(排序链表转换成二叉排序树)】...

    [109-Convert Sorted List to Binary Search Tree(排序链表转换成二叉排序树)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 ...

  9. 八大排序算法的java实现

    八大排序算法的java实现 有时间再贴算法分析图 JDK7的Collections.sort()的算法是TimSort, 适应性的归并排序, 比较晦涩难懂, 这里没有实现 public class m ...

最新文章

  1. Win10 通过cmd查看端口占用、相应进程、杀死进程等的命令
  2. 当微信小程序遇上TensorFlow:Server端实现补充
  3. python中f点flush是什么函数_Python文件操作及内置函数flush原理解析
  4. Java拆分字符串的函数——split
  5. java的static和private_static关键字什么意思?Java中是否可以覆盖一个private或者是static的方法?...
  6. Java程序员如何做到Java架构师
  7. powershell加win的dns服务器,解决网站负载均衡问题
  8. 威斯康星大学计算机案例,美国威斯康星大学麦迪逊分校CS硕士录取
  9. Mybatis注解的方式,如何实现MySQL ,update后,返回更新后的值
  10. Django 【第一篇】基础
  11. lzugis——Arcgis Server for JavaScript API在自己的定义InfoWindow
  12. java碳纤维折叠车评测_开启轻奢生活 SAVA Z1碳纤维折叠车 评测
  13. bat脚本学习——拖拽文件到bat下载
  14. php7 yar扩展,宝塔面板安装yar扩展
  15. hand crafted feature:histogram(直方图)
  16. Python吴恩达深度学习作业13 -- Keras教程
  17. JSP是什么?怎么使用?
  18. 西门子官网下载Eplan部件库
  19. input type=file 标签禁止让用户手动输入
  20. CSS选择器的优先级是怎么定义的?

热门文章

  1. 酒店vr全景展示拍摄提供更多合作和洽谈的机会
  2. 计算机视觉与模式识别 code
  3. [转载] 中国彩电业的危机、机遇和出路
  4. vfs文件体系结构图linux,VFS文件系统结构分析
  5. Optional int parameter ‘categoryId‘ is present but cannot be translated into a null value due to be
  6. mysql交集_MySQL交集INTERSECT运算符
  7. 数据库sql实用脚本
  8. 龙芯推出兼容IE的龙芯浏览器解决方案,全面支持ActiveX插件等应用类型
  9. _exit和exit的区别
  10. 概要设计与详细设计的区别(转)