我正在尝试计算正常的对数似然,由下式给出:
L = l1+l2+l3+...+ln,
其中
lk = log(1/(sqrt(2*PI)*sigma_k))-0.5*e_k*e_k
Sigmas在0.2
附近,而e_k
通常以均值0和单位方差分布,因此大多数都在-2和2之间;
我尝试了以下java代码(上面提到的sigma_k = sigmas.get(k)* Math.sqrt(dt)):
private double new1(List<Double> residuals, List<Double> sigmas, double dt) {
double a = 0;
for(int i=0; i<sigmas.size(); i++) {
a += Math.log(1.0/(Math.sqrt(2*Math.PI*dt)*sigmas.get(i)));
}
double b = 0;
for(int i=0; i<residuals.size(); i++) {
b += residuals.get(i)*residuals.get(i);
}
return a-0.5*b;
}
但是理论最大值低于我通过数值优化得到的最大值,所以我怀疑我的方法不是最理想的。
答案 0 :(得分:0)
我不确定它是否会大大提高数值稳定性,但使用对数定律可以简化方程式:
log(a*b) = log(a) + log(b)
log(1/a) = -log(a)
log(sqrt(a)) = log(a)/2
所以你有:
lk = -log(2*pi)/2 - log(sigma_k) - 0.5*e_k*e_k
= -log(2*pi)/2 - log(dt)/2 - log(sigmas.get(k)) - 0.5*e_k*e_k
= -log(2*pi*dt)/2 - log(sigmas.get(k)) - 0.5*e_k*e_k
首先是常数,所以在第一个循环中你只需要做a -= log(sigmas.get(k))
。
此外,看起来很可疑,第一个循环是sigmas.size()
,第二个循环是residuals.size()
,而等式表明它们应该具有相同的长度。
答案 1 :(得分:0)
<强>注:强> 在某些区域,计算概率/统计数据时不会采用 log ,例如在组合的语言频率中。
以下简化,变得不那么稳定,但之后将其转换回日志总和左右。
double a = 0;
for(int i=0; i<sigmas.size(); i++) {
a += Math.log(1.0/(Math.sqrt(2*Math.PI*dt)*sigmas.get(i)));
}
log(x)+ log(y)= log(x * y)
double a = 1.0;
for(int i=0; i<sigmas.size(); i++) {
a *= 1.0/(Math.sqrt(2*Math.PI*dt)*sigmas.get(i));
}
a = Math.log(a);
(1 / x)*(1 / y)= 1 /(x * y)
double a = 1.0;
for(int i=0; i<sigmas.size(); i++) {
a *= Math.sqrt(2*Math.PI*dt)*sigmas.get(i);
}
a = Math.log(1.0/a);
sqrt(x)^ n =(x ^ 0.5)^ n = x ^(n / 2)
static import Math.*;
double a = pow(2*PI*dt, sigmas.size() / 2.0);
for(int i=0; i<sigmas.size(); i++) {
a *= sigmas.get(i);
}
a = -log(a);