2012-01-06 109 views
1

我试图用以计算给出了正常数似然:数值稳定的方法来计算正常数似然

L = l1+l2+l3+...+ln, 

其中

lk = log(1/(sqrt(2*PI)*sigma_k))-0.5*e_k*e_k 

Sigma的周围0.2,并e_k是正态分布平均为0和单位方差,所以大多数在-2和2之间;

我尝试以下的Java代码(如上= sigmas.get提到sigma_k(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

我不知道这是否会大大提高数值稳定性,但你的方程可以用对数法进行简化:

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(),而方程式表明它们应该具有相同的长度。

0

备注: 在一些地区可能/是没有组合的语言频率服用日志,例如计算统计。

以下简化,变得不太稳定,但之后一个将其转换回日志总和左右。


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))); 
} 

日志(X)+日志(Y)=日志(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);