SVM目标函数
SVM目标函数推导
函数间隔:
几何间隔:
SVM 算法就可以比较自然地叙述为:最大化(几何间隔)d、使得:
不妨假设函数间隔为1,这样就得到最开始的优化目标方程。
约束条件中:
y
i
(
w
.
x
+
b
)
−
1
>
=
0
y_i(w . x + b) -1 >=0
yi(w.x+b)−1>=0,那个“1”就是函数间隔,注意这里的目标是关注的是间隔,
y
i
(
w
.
x
+
b
)
−
1
=
0
y_i(w . x + b) -1 =0
yi(w.x+b)−1=0就是间隔直线上的点。
软间隔、松弛
在数学上就是做了如下操作:
ξ
i
\xi_i
ξi就是松弛变量,可以把函数间隔变量化,但是变化可以控制,如何控制了,使用惩罚因子来控制函数间隔。
约束条件为:
从常识来看这个优化问题的解存在,w的解唯一,但是b的解不唯一,也就是解是一组平行线
HingeLoss和软间隔
上述目标函数约束条件
ξ
i
\xi_i
ξi>=0,也就是函数间隔为1-
ξ
i
\xi_i
ξi,当
ξ
i
\xi_i
ξi<0时,函数间隔就为1,当
ξ
i
\xi_i
ξi>0时,函数间隔就为1-
ξ
i
\xi_i
ξi,等价为如下函数:
对应的目标函数为:
实际上我们一般见到的hingeLoss的目标函数是:
令
λ
\lambda
λ = 1\2C,他们二者是等价的。
Hinge Loss就相当于松弛因子ξ
对于间距大于一定程度的点,就没有loss,就不用松弛。
正则化的作用相当于把分类的距离拉大。
随机梯度下降算法
松弛因子ξ>=0转化为Hinge Loss之后使用随机梯度下降就比较方便了,针对单一样本(
x
i
x_i
xi,
y
i
y_i
yi)对w,b求偏导:
线性SVM的算法描述:
首先该算法是基于hingeloss的随机梯度下降算法,和感知机算法流程一致:遍历样本,找出误差最大的样本,也就是函数间隔比1小的最多的样本,然后在误差为正的样本里面,选出误差最大的样本,使用这个样本更新w和b,使用新的参数遍历样本,直到所有的样本误差为负,也就是所有的样本函数间隔大于1。
线性SVM算法实现:
import numpy as np
class LinearSVM:
def __init__(self):
self._w = self._b = None
def fit(self, x, y, c=1, lr=0.01, epoch=10000):
x, y = np.asarray(x, np.float32), np.asarray(y, np.float32)
self._w = np.zeros(x.shape[1])
self._b = 0.
for _ in range(epoch):
self._w *= 1 - lr
err = 1 - y * self.predict(x, True)
idx = np.argmax(err)
# 注意即使所有 x, y 都满足 w·x + b >= 1
# 由于损失里面有一个 w 的模长平方
# 所以仍然不能终止训练,只能截断当前的梯度下降
if err[idx] <= 0:
continue
delta = lr * c * y[idx]
self._w += delta * x[idx]
self._b += delta
def predict(self, x, raw=False):
x = np.asarray(x, np.float32)
y_pred = x.dot(self._w) + self._b
if raw:
return y_pred
return np.sign(y_pred).astype(np.float32)
这种使用最大误差样本更新w,b的方式,是随机梯度下降?预测一遍全部样本找误差最大的样本,为什么不使用全部样本的来更新w,b,我觉得随机梯度就应该随便找选择一个样本,使用这个样本来更新w,b,假如有误差就按照上述更新,没有误差就换一个样本。