矩阵的对数运算公式_HanLP-对数概率转概率

fb0d00bdbdaf1f909f65b02c018bb4a3.png

这篇文章除了给出HanLPv1.7.6的对数概率转概率的计算过程,同时给出sklearn中的转概率计算过程。

计算文本属于China和不属于China的概率
P(c=China| Chinese Chinese Chinese Tokyo Japn)=
P(c=China)*P(Chinese|c=China)*P(Chinese|c=China)*
P(Chinese|c=China)*P(Tokyo|c=China)*P(Japan|c=China)
=0.75*0.429*0.429*0.429*0.071*0.071=0.000299

P(c!=China| Chinese Chinese Chinese Tokyo Japn)=
P(c!=China)*P(Chinese|c!=China)*P(Chinese|c!=China)*
P(Chinese|c!=China)*P(Tokyo|c!=China)*P(Japan|c!=China)
=0.25*0.222*0.222*0.222*0.222*0.222=0.000135

我们用sklearn计算得到的概率为[0.68894009, 0.31105991],实际上sklearn就是对概率值做了归一化操作,也就是先对[0.000299, 0.000135]求总和,之后再用[0.000299, 0.000135]除以总和。

我们计算一下,看看怎么从[0.000299, 0.000135]得到[0.68894009, 0.31105991],这里为了防止溢出,我们也是先对概率[0.000299, 0.000135]取对数。

In [1]: import numpy as np
In [2]: log_prob = np.array([np.log(0.000299), np.log(0.000135)])
In [3]: prob = np.exp(log_prob)/np.sum(np.exp(log_prob))
In [4]: prob
Out[4]: array([ 0.68894009,  0.31105991])

显然,对数概率p(y_k|x)的转换公式为:

e6ed1bf5c72114650481c0fc6bbd743d.png

以上为sklearn中对数概率转为概率的计算公式,接下来我们看看 HanLP中的转换公式。

由于概率值相乘会造成溢出,因此HanLP在计算一篇文本属于某个类目的概率时,对预测概率公式两端取对数,这样就将概率值相乘变成取对数后的概率值相加,用朴素贝叶斯预测类目的公式如下:

3349f11991c40ba97bfa2feda165e97f.png

如果用户要求输出概率值而不是对数概率值,则对上边等式的两边做指数运算,于是

c6c83142eedddc50a502362b00ee568b.png

为了防止指数运算溢出,HanLP首先求对数概率最大值,然后将每个对数概率值都减掉最大值,之后再进行指数运算,

fbddc2dce3a71a1b025929c94b36a0b5.png

最后做归一化操作:

7d2ba94c9587842aa5b16ecfb3759b21.png

综上,HanLP与sklearn计算的唯一区别就是在指数运算之前减掉了max。

HanLP中实现上述计算的代码在com/hankcs/hanlp/utility/MathUtility.java类中的normalizeExp方法

/**
* 使用log-sum-exp技巧来归一化一组对数值
*
* @param predictionScores
*/
public static void normalizeExp(Map<String, Double> predictionScores)
{
	Set<Map.Entry<String, Double>> entrySet = predictionScores.entrySet();
	double max = Double.NEGATIVE_INFINITY;
	for (Map.Entry<String, Double> entry : entrySet)
	{
	    max = Math.max(max, entry.getValue());
	}

	double sum = 0.0;
	//通过减去最大值防止浮点数溢出
	for (Map.Entry<String, Double> entry : entrySet)
	{
	    Double value = Math.exp(entry.getValue() - max);
	    entry.setValue(value);

	    sum += value;
	}

	if (sum != 0.0)
	{
	    for (Map.Entry<String, Double> entry : entrySet)
	    {
	        predictionScores.put(entry.getKey(), entry.getValue() / sum);
	    }
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值