技术标签: NLP
新版的lucence不再把TF-IDF作为默认的相关性算法,而是采用了BM25(BM是Best Matching的意思)。BM25是基于TF-IDF并做了改进的算法。
一句话概况其主要思想:对Query进行语素解析,生成语素qi;然后,对于每个搜索结果D,计算每个语素qi与D的相关性得分,最后,将qi相对于D的相关性得分进行加权求和,从而得到Query与D的相关性得分。
传统的TF-IDF是自然语言搜索的一个基础理论,它符合信息论中的熵的计算原理,虽然作者在刚提出它时并不知道与信息熵有什么关系,但你观察IDF公式会发现,它与熵的公式是类似的。实际上IDF就是一个特定条件下关键词概率分布的交叉熵。
BM25在传统TF-IDF的基础上增加了几个可调节的参数,使得它在应用上更佳灵活和强大,具有较高的实用性。
BM25同样使用词频,逆文档频率以及字段长度归一化,但是每个因子的定义都有细微差别
TF-IDF没有考虑词频上限的问题,因为高频停用词已经被移除了)
BM25 有一个上限,文档里出现5-10次的词会比那些只出现一两次的对相关度有显著影响),参见词频饱和度图:
BM25算法的一般性公式如下:
下面我们来看如何定义Wi。判断一个词与一个文档的相关性的权重,方法有多种,较常用的是IDF
。这里以IDF为例,公式如下:
Map<String, Double> idf = new TreeMap<String, Double>();
idf.put(word, Math.log(D - freq + 0.5) - Math.log(freq + 0.5));
根据IDF的定义可以看出,对于给定的文档集合,包含了qi的文档数越多,qi的权重则越低
。也就是说,当很多文档都包含了qi时,qi的区分度就不高,因此使用qi来判断相关性时的重要度就较低。
语素qi与文档d的相关性得分R(qi,d)。首先来看BM25中相关性得分的一般形式:
不像 TF/IDF ,BM25 有一个比较好的特性就是它提供了两个可调参数:
由于绝大部分情况下,qi在Query中只会出现一次,即qfi=1,因此公式可以简化为:
从K的定义中可以看到,参数b的作用是调整文档长度对相关性影响的大小。b越大,K值越小,文档长度的对相关性得分的影响越大,反之越小。而文档的相对长度越长,K值将越大,则相关性得分会越小
。这可以理解为,当文档较长时,包含qi的机会越大,因此,同等fi的情况下,长文档与qi的相关性应该比短文档与qi的相关性弱。
综上,BM25算法的相关性得分公式可总结为:
hanlp中的计算代码:
score = (idf.get(word) * tf * (k1 + 1) / (tf + k1 * (1 - b + b * d / avgdl)))
附录HanLP的BM25 算法的java实现代码 :
public class BM25
{
/**
* 文档句子的个数
*/
int D;
/**
* 文档句子的平均长度
*/
double avgdl;
/**
* 拆分为[句子[单词]]形式的文档
*/
List<List<String>> docs;
/**
* 文档中每个句子中的每个词与词频
*/
Map<String, Integer>[] f;
/**
* 文档中全部词语与出现在几个句子中
*/
Map<String, Integer> df;
/**
* IDF
*/
Map<String, Double> idf;
/**
* 调节因子
*/
final static float k1 = 1.5f;
/**
* 调节因子
*/
final static float b = 0.75f;
public BM25(List<List<String>> docs)
{
this.docs = docs;
D = docs.size();
for (List<String> sentence : docs)
{
avgdl += sentence.size();
}
avgdl /= D;
f = new Map[D];
df = new TreeMap<String, Integer>();
idf = new TreeMap<String, Double>();
init();
}
/**
* 在构造时初始化自己的所有参数
*/
private void init()
{
int index = 0;
for (List<String> sentence : docs)
{
Map<String, Integer> tf = new TreeMap<String, Integer>();
for (String word : sentence)
{
Integer freq = tf.get(word);
freq = (freq == null ? 0 : freq) + 1;
tf.put(word, freq);
}
f[index] = tf;
for (Map.Entry<String, Integer> entry : tf.entrySet())
{
String word = entry.getKey();
Integer freq = df.get(word);
freq = (freq == null ? 0 : freq) + 1;
df.put(word, freq);
}
++index;
}
for (Map.Entry<String, Integer> entry : df.entrySet())
{
String word = entry.getKey();
Integer freq = entry.getValue();
idf.put(word, Math.log(D - freq + 0.5) - Math.log(freq + 0.5));
}
}
/**
* 计算一个句子与一个文档的BM25相似度
*
* @param sentence 句子(查询语句)
* @param index 文档(用语料库中的下标表示)
* @return BM25 score
*/
public double sim(List<String> sentence, int index)
{
double score = 0;
for (String word : sentence)
{
if (!f[index].containsKey(word)) continue;
int d = docs.get(index).size();
Integer tf = f[index].get(word);
score += (idf.get(word) * tf * (k1 + 1)
/ (tf + k1 * (1 - b + b * d
/ avgdl)));
}
return score;
}
public double[] simAll(List<String> sentence)
{
double[] scores = new double[D];
for (int i = 0; i < D; ++i)
{
scores[i] = sim(sentence, i);
}
return scores;
}
}
一。混凝土弹塑性本构混凝土的受力非线性行为同时包含微裂缝(微缺陷)和塑性流动这两种微观机制的影响,导致混凝土材料具有以如下显著特征:1)峰值应力后存在不稳定区域并伴随明显的刚度退化和强度软化;2)加卸载时的滞回特性:变形超过定的阀值后,混凝土完全卸载后存在着不可恢复变形;3)有侧限(如双轴受压应力状态)时材料的强度和延性明显增大;4)由于拉应力的影响,二维拉压应力下混凝...
1.PHP实际项目中的应用主要有:a) 用于后台脚本编程,即以命令行(CLI)的方式进行。b) 用于网络应用编程,即以mod_php或者fastCGI的方式执行。(LAMP框架) 2.PHP是一门“弱类型”语言,null,‘’,0,false还有空数组,在php中都是可以直接相等的。当时用全等号可以区分他们:echo "null==0:";var_dump(null==
深入理解Android(一):Gradle详解
清理网站缓存的几种方法meta方法<meta http-equiv="pragma" content="no-cache"><meta http-equiv="Cache-Control" content="no-cache, must-revalidate"><meta http-equiv="expires" content="0"&...
ret = gpio_request_array(mx6q_sabresd_flexcan_gpios, ARRAY_SIZE(mx6q_sabresd_flexcan_gpios));static struct gpio mx6q_sabresd_flexcan_gpios[] = { { SABRESD_CAN1_STBY, ...
一.介绍 log4net库是Apache log4j框架在Microsoft .NET平台的实现,是一个帮助程序员将日志信息输出到各种目标(控制台、文件、数据库等)的工具。 二.寻找log4net 1.百度搜索log4net 2.点击进入 3.点击Download 4.点击log4net-2.0.8-bin-newke...
五种value类型:String,List,Hash,Set,ZSet(有序集)package com.realrainy.oa;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set;import redis.clients.jedis.Jedis;impo...
我们将编写程序,把数字和公式作为输入,进行一些计算,然后得到解或绘制出图形。其中一些程序能提供强大的计算功能来解决一些数学问题。这些程序能求出方程的解,计算数据集之间的相关性,确定函数的最大值,等等。在其他程序中,我们将模拟现实生活中的事件,如抛物运动、掷硬币或掷骰子。使用程序来模拟这样的事件,让我们可以用一个简单的方法来更好地分析和了解事情本身。也许你会发现一些不借助计算机程序会非常难于探索...
版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/CharlesSimonyi/article/details/52027563 如果说使用dex2jar和JD-GUI获得了一个APP反编译后的JAVA代码,再结合smali代码调试器来进行调试还不够爽,不够畅快的话,下面将介绍一个帮助分析代码执行流程的大神器。这个神器优点很多,不过遗憾的是它有一个致命...
gulp打包时报错 Error: ENOENT: no such file or directory, chmod 'E:\Practice\myWorld\build\img\bg'gulp任务顺序文件目录gulpfile.jsconsolegulp任务顺序task clean 在打包之前,先清空build文件夹gulp.task('clean', d => { if (chec...
使用AudioQueue录音时,回调方法中可以得到一个AudioBufferList类型的数据,每个frame里有inNumberFrames个数据,有inNumberChannels个channel。inNumberFrames*inNumberChannels的结果,就是AudioBufferList其中一个buffer里的数据量。AudioBufferList里的buffer里面的数据,...
一、简介最近客户提出需要使用PHP7的需求,第一次是给客户安装的是LNMP-full的集成环境,但是后面不便于添加扩展模块,以及本人对Nginx不是很了解,经协商后改用LAMP,以下内容为真实环境搭建完成后为了方便记忆在虚拟环境中的配置,和真是环境基本一样二、准备环境操作系统IP地址相关软件包Centos7.210.0.0.11php70w-common php70w...