感知机
- 感知机目标在于对线性可分的数据集,能够求出将训练数据进行线性划分的分离超平面。
从以上描述可以知道,分离超平面不止一个,也就是说,只要能找到其中一个分离超平面,模型就成功了。
而支持向量机,是在感知机的基础上,进一步要求寻找到划分超平面距离最近分类样点的距离之和达到最小,也就是不仅要经验风险最小,而且同时也要求结构风险最小化。
模型
- 输入空间是X∈Rn,输出空间是Y={+1,-1}
- 映射函数为 f(x)=sign(w*x+b)
要注意到,w与x均为n维向量。 sign(x)即为符号函数。
策略
为了找出w与b,首先要定义学习策略。在此,我们首先要定义(经验)损失函数。
比较明显的一个选择是看误分类点的总数,所以将所有误分类点到超平面S的距离之和(回忆下点到直线的距离是怎么算的?),作为我们的损失函数。
这里要注意到,为什么要用Yi*(w*Xi+b)?
1. 首先,这里的Yi并不是我们样本点里的某一维坐标值,它是样本点的标签,要么是1,要么是-1。
2. 接着可以看看,对于误分类的数据点来说,Yi*(w*Xi+b)的值始终是小于0的(这里假设前提是对于标签为+1的点,w*Xi+b的值大于0;标签为-1的点,w*Xi+b的值小于0)。
3. 最后,因为在以上损失函数中,w与b都同时伸缩1/||w||倍,故而可以不用考虑系数。得到我们真正的损失函数模型:
算法
我们的目标是 min L(w,b),这里采用随机梯度下降法。具体是,首先任意给定w0 及 b0,然后利用梯度下降法不断极小化目标函数,极小化过程中不是一次使M中所有误分类点的梯度下降,而是一次随机选取一个误分类点使其梯度下降。
对L分别求关于w及关于b的偏导数:
然后选取一个学习率η,对w及b进行更新 w←w+η*yi*xi ,b←b+η*yi。
再次强调,这里的 yi 指的是样本点的分类标签。
最后总结得到算法:
(摘自李航老师的《统计学习方法》)
代码实现
根据以上的算法,用Python实现了下算法过程。Python大法好,不过,感觉自己写的代码面向过程的味道还是太重了,面向对象的精髓都没体现出来,还需继续修炼啊!
from numpy import *
def FindTheWrongpots(FTranning,FTags,FnumPots,FnumDirections,Fw,Fb):
for i in range(FnumPots):
tmp=0
for j in range(FnumDirections):
tmp = tmp + Fw[j] * FTranning[i][j]
yy = FTags[i] * ( tmp + Fb)
if yy <= 0 :
return FTranning[i]
return 0
def Perceptron(Trainning,Tags,n):
numPots = len(Trainning)
numDirections = len(Trainning[0])
w=zeros(numDirections)
b=0.0
k=0
while k<100 :
wrongPot = FindTheWrongpots(Tranning,Tags,numPots,numDirections,w,b)
if(wrongPot == 0):
k=-1
break
key = Tranning.index(wrongPot)
for i in range(numDirections):
w[i] = w[i] + n * Tags[key] * wrongPot[i]
b = b + n * Tags[key]
k=k+1
if k == 100 :
print("Can't use perceptron model!")
elif k == -1 :
print "w=",w,"b=",b
if __name__=="__main__":
Tranning = [(3,3),(4,3),(1,1)]
Tags = [1,1,-1]
Perceptron(Tranning,Tags,1)
这里的每一次迭代,都从前到后找到第一个误分类点进行随机梯度下降。