讲完了感知机,我们就可以看SVM了
港真,当时看SVM的时候整个人属于懵比状态<( ̄3 ̄)>
(为什么要转化成对偶形式!神经病!
(为什么要用SMO求解!神经病!
我们先来看看这个神经病在线性模式下的面板属性:
目的:二分类
思想:最大化间隔(我不仅要分开,我还要分得好!不能随便了事!
损失函数:
方法:SMO?神经病啊
我们先来看这个损失函数前面这撮,好家伙,加个1就唬人不是么= =
想想感知机的损失函数,实质上感知机的损失函数就少了这个1啊(什么,你质问我没有感知机的损失函数没有那个+的下标?欸欸欸,感知机我们也只取分错的样本进行权重调整好么!)
再看看后面这撮,这这这,这不就加了个L2正则项嘛!(是的,在我看来SVM就是正则项的集大成体现)
于是乎我们可以对感知机动手改造了(此处应响起数码宝贝中进化的插曲brave heart~)
感知机————进化————线性SVM!!!
class SVM:
def __init__(self):
self._w = self._b = None
def fit(self, x, y, batchsize=128, l2=0.001, lr=0.1, epoch=1000):
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/10
err = 1-y * self.predict(x, True)
idx = np.argsort(err)[::-1]
err = err[idx]
batchsize = min(batchsize, len(y))
err = err[:batchsize]
if err[0] <= 0:
continue
mask = err > 0
idx = idx[mask]
delta = lr * y[idx]
self._w += np.mean(delta[..., None] * x[idx], axis=0) - lr*l2*self._w
self._b += np.mean(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)
看一下效果
这个是SVM的效果
这个是感知机的效果
基本达到了要求,收工~