QxRed » 日志 » CRF++中l1范式的处理
CRF++中l1范式的处理
风暴红QxRed 发表于 2008-01-03 13:45:10
/*
s[j]为lbfgs得到的lambda[j](即wa[j])的方向
g[j]为lambda[j]的导数
p为考虑l1范式后得到的lambda[j]的移动方向
a)lambda[j]!=0,且p==s[j],则p为移动方向,如果lambda[j]移动时穿过0,那么lambda[j]=0,因为到0另一边,lambda[j]不一定下降(见图4)
b)lambda[j]!=0,且p!=s[j],则lambda[j]不变
c)lambda[j]==0,且g-1/C>0(即g+1/C>g-1/C>0,见图1)则lambda[j]向左边移动,其上的导数为g-1/C
d)lambda[j]==0,且g+1/C<0(即g-1/C<g+1/C<0,见图2)则lambda[j]向右边移动,其上的导数为g+1/C
e)lambda[j]!=0,且g-1/C<0<g+1/C,则lambda[j]=0(见图3)
*/
for (int j = 1; j <= size; ++j) {
double grad_neg = 0.0;//lambda[j]左导数
double grad_pos = 0.0;//lambda[j]右导数
double grad = 0.0;//考虑l1后的导数
if (wa[j] == 0.0) { //wa[j]即lambda[j]
grad_neg = g[j] - 1.0 / C;//0左边导数
grad_pos = g[j] + 1.0 / C;//0右边导数
} else {
grad_pos = grad_neg = g[j] + 1.0 * sigma(wa[j]) / C;//lambda[j]!=0,左导数=右导数
}
if (grad_neg > 0.0) {//左右导数都<0,则向左边移动,见图1
grad = grad_neg;
} else if (grad_pos < 0.0) {//左右导数都>0,则向左边移动,见图2
grad = grad_pos;
} else {
grad = 0.0;//左右导数异号,则不移动,见图3
}
const double p = pi(s[j], -grad);//如果l1后的负导数和lbfgs给的方向s[j]一致,则沿着s[j]移动,否则不移动,情况b)
const double xi = wa[j] == 0.0 ? sigma(-grad) : sigma(wa[j]);//xi为移动前lambda[j]的符号
x[j] = pi(wa[j] + *stp * p, xi);//如果移动前后lambda[j]变号,则lambda[j]=0




