式(1)是一个带约束的凸二次规划(convex quadratic programming)问题(凸问题就意味着必定能求到全局最优解,而不会陷入局部最优)。对这样一个问题,可以直接用现成的优化计算包求解,但这一小节介绍的是一种更高效的方法。
首先为式(1)的每条约束添加拉格朗日乘子 (对应m个样本的m条约束),得到该问题的拉格朗日函数:
%20%3D%20%5Cfrac%7B1%7D%7B2%7D%20%5CVert%20%5Cmathbf%7Bw%7D%20%5CVert%5E2%20%2B%20%5Csum%7Bi%3D1%7D%5Em%20a_i(1-y_i(%5Cmathbf%7Bw%7D%5ET%5Cmathbf%7Bx%7D_i%2Bb))%5Cqquad(2)%0A#card=math&code=L%28%5Cmathbf%7Bw%7D%2Cb%2C%5Cmathbf%7Ba%7D%29%20%3D%20%5Cfrac%7B1%7D%7B2%7D%20%5CVert%20%5Cmathbf%7Bw%7D%20%5CVert%5E2%20%2B%20%5Csum%7Bi%3D1%7D%5Em%20a_i%281-y_i%28%5Cmathbf%7Bw%7D%5ET%5Cmathbf%7Bx%7D_i%2Bb%29%29%5Cqquad%282%29%0A&id=lr2AU)
其中 #card=math&code=%5Cmathbf%7Ba%7D%20%3D%20%28a_1%3Ba_2%3B…%3Ba_m%29&id=KwQeL),对拉格朗日函数求
和
的偏导,并令偏导为0可以得到:
%5C%5C%0A0%20%26%3D%20%5Csum%7Bi%3D1%7D%5Em%20a_i%20y_i%5Cqquad(4)%0A%5Cend%7Bsplit%7D#card=math&code=%5Cbegin%7Bsplit%7D%0A%5Cmathbf%7Bw%7D%20%26%3D%20%5Csum%7Bi%3D1%7D%5Em%20ai%20y_i%20%5Cmathbf%7Bx%7D_i%5Cqquad%283%29%5C%5C%0A0%20%26%3D%20%5Csum%7Bi%3D1%7D%5Em%20a_i%20y_i%5Cqquad%284%29%0A%5Cend%7Bsplit%7D&id=uQp5A)
将式(3)代入式(2)可以消去 ,又因为式(2)中
的系数是
,由式(4)可知
也可以消去。然后再考虑式(4)的约束就得到了式(1)的对偶问题(dual problem):
%0A%5Cend%7Bsplit%7D#card=math&code=%5Cbegin%7Bsplit%7D%0A%5Cmax%7B%5Cmathbf%7Ba%7D%7D%20%5Csum%7Bi%3D1%7D%5Em%20ai%20-%20%5Cfrac%7B1%7D%7B2%7D%20%5Csum%7Bi%3D1%7D%5Em%5Csum%7Bj%3D1%7D%5Em%20a_i%20a_j%20y_i%20y_j%20%5Cmathbf%7Bx%7D_i%5ET%20%5Cmathbf%7Bx%7D_j%26%5C%5C%0A%5Ctext%7Bs.t.%7D%20%5Csum%7Bi%3D1%7D%5Em%20a_i%20y_i%20%26%3D%200%2C%20%5Cquad%20a_i%20%5Cgeq%200%2C%20%5Cquad%20i%3D1%2C2%2C…%2Cm%20%5Cqquad%20%285%29%0A%5Cend%7Bsplit%7D&id=UiU8G)
只要求出该对偶问题的解 ,就可以推出
和
,从而得到模型:
%20%26%3D%20%5Cmathbf%7Bw%7D%5ET%20%5Cmathbf%7Bx%7D%20%2B%20b%5C%5C%0A%26%3D%20%5Csum%7Bi%3D1%7D%5Em%20a_i%20y_i%20%5Cmathbf%7Bx%7D_i%5ET%20%5Cmathbf%7Bx%7D%20%2B%20b%20%5Cqquad%20(6)%0A%5Cend%7Bsplit%7D#card=math&code=%5Cbegin%7Bsplit%7D%0Af%28%5Cmathbf%7Bx%7D%29%20%26%3D%20%5Cmathbf%7Bw%7D%5ET%20%5Cmathbf%7Bx%7D%20%2B%20b%5C%5C%0A%26%3D%20%5Csum%7Bi%3D1%7D%5Em%20a_i%20y_i%20%5Cmathbf%7Bx%7D_i%5ET%20%5Cmathbf%7Bx%7D%20%2B%20b%20%5Cqquad%20%286%29%0A%5Cend%7Bsplit%7D&id=Iucxd)
不过实际计算时一般不会直接求解 ,特别是需要用核函数映射到高维空间时,因为映射后做内积很困难,而用少量支持向量进行表示,在原始空间进行计算显然更优,这点在后续章节会详细讲解。
注意,由于式(1)的约束条件是不等式约束,所以求解过程要求满足KKT(Karush-Kuhn-Tucker)条件:
-1%20%5Cgeq%200%3B%0A%5C%5Ca_i%20(y_i%20f(%5Cmathbf%7Bx%7D_i)-1)%20%3D%200.%0A%5Cend%7Barray%7D%0A%5Cright.#card=math&code=%5Cleft%0A%5C%7B%5Cbegin%7Barray%7D%0A%5C%5Ca_i%20%5Cgeq%200%3B%0A%5C%5Cy_i%20f%28%5Cmathbf%7Bx%7D_i%29-1%20%5Cgeq%200%3B%0A%5C%5Ca_i%20%28y_i%20f%28%5Cmathbf%7Bx%7D_i%29-1%29%20%3D%200.%0A%5Cend%7Barray%7D%0A%5Cright.&id=mDX9i)
这个KKT条件说明了,对任何一个样本 来说,
- 要么对应的拉格朗日乘子
为0,此时样本
对式(6)毫无贡献,不会影响到模型;
- 要么函数间隔
%20%3D%201#card=math&code=y_i%20f%28%5Cmathbf%7Bx%7D_i%29%20%3D%201&id=vLyug),此时样本
位于最大间隔边界上,是一个支持向量。
它揭示了SVM的一个重要性质:最终模型只与支持向量有关,因此训练完成后,大部分的训练样本都不需保留。
SMO算法
可以发现对偶问题式(5)是一个二次规划问题,可以使用通用的二次规划算法求解。但问题规模正比于样本数,因此开销相当大。为了避免这个开销,可以使用高效的SMO(Sequential Minimal Optimization)算法。
初始化参数 后,SMO算法重复下面两个步骤直至收敛:
- 选取一对需要更新的变量
和
- 固定
和
以外的参数,求解对偶问题式(5)来更新
和
怎么选取 和
呢?
注意到,只要选取的 和
中有一个不满足KKT条件,那么更新后目标函数的值就会增大。而且违背KKT条件的程度越大,则更新后导致目标函数增幅就越大。
因此,SMO算法先选取一个违背KKT条件程度最大的变量 ,然后再选一个使目标函数增长最快的变量
,但由于找出
的开销较大,所以SMO算法采用了一个启发式,使选取的两变量对应的样本之间间隔最大。这样两个变量差别很大,与选取两个相似变量相比,这种方法能为目标函数带来更大的变化,从而更快搜索到全局最大值。
由于SMO算法在每次迭代中,仅优化两个选定的参数,其他参数是固定的,所以会非常高效。此时,可将对偶问题式(5)的约束重写为:
%0A#card=math&code=a_iy_i%20%2B%20a_jy_j%20%3D%20c%2C%5Cquad%20a_i%20%5Cgeq%200%2C%20a_j%20%5Cgeq%200%20%5Cqquad%20%287%29%0A&id=cx8HU)
其中, 看作是固定的常数。
利用式(7),我们可以把 从式(5)中消去,这样就得到了一个单变量二次规划问题,只需考虑
这个约束。这样的问题具有闭式解,所以我们连数值优化方法都不需要了,可以直接算出
和
。
使用SMO算法计算出最优解之后,我们关注的是如何推出 和
,从而得到最终模型。获得
很简单,直接用式(3)就可以了。而位移项
则可以通过支持向量导出,因为对于任一支持向量
#card=math&code=%28%5Cmathbf%7Bx%7D_s%2C%20y_s%29&id=y3xwW),都有函数间隔等于1,所以有:
%20%3D%20ys(%5Csum%7Bi%20%5Cin%20S%7D%20ai%20y_i%20%5Cmathbf%7Bx%7D_i%5ET%20%5Cmathbf%7Bx%7D_s%20%2B%20b)%3D%201%20%5Cqquad%20(8)%0A#card=math&code=y_sf%28%5Cmathbf%7Bx%7D%29%20%3D%20y_s%28%5Csum%7Bi%20%5Cin%20S%7D%20a_i%20y_i%20%5Cmathbf%7Bx%7D_i%5ET%20%5Cmathbf%7Bx%7D_s%20%2B%20b%29%3D%201%20%5Cqquad%20%288%29%0A&id=drOpL)
这里的 是所有支持向量的下标集(事实上,用所有样本的下标也行,不过非支持向量的拉格朗日乘子等于0,对求和没贡献,这一点前面已经提到了)。
理论上,我们只要选取任意一个支持向量代入式(8)就可以把 算出来了。但实际任务中往往采用一种更鲁棒的做法:用所有支持向量求解的平均值。
%0A#card=math&code=b%20%3D%20%5Cfrac%7B1%7D%7B%7CS%7C%7D%20%5Csum%7Bs%20%5Cin%20S%7D%20%28%5Cfrac%7B1%7D%7By_s%7D%20-%20%5Csum%7Bi%20%5Cin%20S%7Da_i%20y_i%20%5Cmathbf%7Bx%7D_i%5ET%20%5Cmathbf%7Bx%7D_s%29%0A&id=p6DTq)