上篇博客证明了关于“违反对”拉格朗日乘子选择问题,其实问题还没有结束,因为剩下如何计算G[ ]和G_bar[ ]两个数组,以及每次迭代拉格朗日乘子问题并没有解决,只是解决了关于乘子的选择问题。这篇博客就是着重解决上述问题。如果不清楚问题的话可参考(http://blog.csdn.net/zhuyue3938199/article/details/7469868)。
乘子选择问题变成以下优化问题:

优化问题进一步推导可得到如下变形:


可求得取得极值点是

为了推导方便将进行如下定义:
并且由于
将(3)式代入:

那么我们就可以得到迭代后的拉格朗日
的值了。

接下来对两种情况进行讨论:
(1)如果
则根据(3)和(6)可得


在Libsvm中,
在后面的源码解释可以看到:

(2)如果
,则根据(3)和(6)可得


同理,
因此可以得到:

在这里基本已经推导出了Libsvm中每一次拉格朗日乘子的迭代过程。但还有一些细节没有完全解决。如果记得优化问题的对偶问题的限制条件中有,
为了保证这个约束条件的成立,因此还要进行进一步的深入讨论。其实有两种情况的,(1)
(2)
我们这里就只讨论
这种情况。
对偶问题中的另一个约束条件是
我们每次只取里面两个乘子来进行优化,因此有:

注意:这里的这里的constant’和constant并不一样哦!!!
由上述(12)和(11)可得,
的取值并不是任意,必须满足约束条件:

在LibSVM的技术文档中,给出了这样一幅图:
在上图中,
的取值只能上述四个区域,而不可能取到右下角和左上角的值。证明如下:
(1)
位于左上角,那么有:

明显可以看出(13)与(14)式子是矛盾的,因此不可能取到上述的取值。同理
(2)
位于左上角,那么有:
也可以看出(15)与(13)式子是矛盾的。因此
不可能位于NA区域。因此
必然位于上述四个区域之一或在四方形的内部。如果位于四方形的内部,则不需进行进一步的讨论,如果是位于四个区域之一,则必须对
的取值进行纠正,保证满足式子(11)。
(1)在局域1有:
满足
为了满足约束条件(11),将数值调整为:

(2)在局域2有:
满足
为了满足约束条件(11),将数值调整为:

(3)在区域3有:
满足
为了满足约束条件(11),将数值调整为:
(4)在区域4有:
满足
为了满足约束条件(11),将数值调整为:

至此,我们已经讨论了
时,拉格朗日乘子迭代的全过程。同样道理,
的情况也是类似的。这里就不再详细讨论了。接下来就看下Solve函数源代码。
if(y[i]!=y[j])//
{
double quad_coef = QD[i] + QD[j] + 2*Q_i[j]; //这里计算上述的(4)中的
if (quad_coef <= 0)
quad_coef = TAU; //如果,则用很小的正数代替
double delta = (-G[i]-G[j]) / quad_coef; //计算delta
double diff = alpha[i] - alpha[j]; //计算
alpha[i] += delta; //迭代计算
alpha[j] += delta; //迭代计算
if(diff > 0)
{
if(alpha[j] < 0) //在区域3,按(18)进行更新
{
alpha[j] = 0;
alpha[i] = diff;
}
}
else
{
if(alpha[i] < 0) //在区域4,按(19)进行更新
{
alpha[i] = 0;
alpha[j] = -diff;
}
}
if(diff >C_i - C_j)
{
if(alpha[i] >C_i) //在区域1,按(16)进行更新
{
alpha[i] =C_i;
alpha[j] =C_i - diff;
}
}
else
{
if(alpha[j] > C_j) //在区域2,按(17)进行更新。
{
alpha[j] = C_j;
alpha[i] = C_j + diff;
}
}
}
else
{
double quad_coef = QD[i] + QD[j] - 2*Q_i[j];
if (quad_coef <= 0)
quad_coef = TAU;
double delta = (G[i]-G[j]) / quad_coef;
double sum = alpha[i] + alpha[j];
alpha[i] -= delta;
alpha[j] += delta;
if(sum > C_i)
{
if(alpha[i] > C_i)
{
alpha[i] = C_i;
alpha[j] = sum - C_i;
}
}
else
{
if(alpha[j] < 0)
{
alpha[j] = 0;
alpha[i] = sum;
}
}
if(sum > C_j)
{
if(alpha[j] > C_j)
{
alpha[j] = C_j;
alpha[i] = sum - C_j;
}
}
else
{
if(alpha[i] < 0)
{
alpha[i] = 0;
alpha[j] = sum;
}
}
}


1757

被折叠的 条评论
为什么被折叠?



