本文是参照:李航《统计学习方法》实现,如果遇到问题请参看书。
感知机是二分类的线性分类模型,在许多的机器算法模型中都可以找到它的影子,更是神经网络和支持向量机的基础,所以理解感知机模型就变得非常重要。
输入:实例的特征向量
输出:实例的类别(取值为+1,-1)
感知机学习目的:训练出一个分离超平面,将数据可以进行线性划分。
感知机学习策略:根据目的,我们可以导入基于误分类的函数,利用梯度下降法求误分类函数的极小化,进而得到感知机模型。
定义:假设特征空间(输入空间)是 χ⊆Rn χ ⊆ R n ,输出空间是 γ={+1,−1} γ = { + 1 , − 1 } ,输入 y∈γ y ∈ γ 表示实例的类别,由输入空间到输出空间的函数如下:
称其为感知机,其中我 w w 和 b b 为感知机模型参数, w⊆Rn w ⊆ R n 叫做权值或权值向量, b⊆R b ⊆ R 叫做偏置, w⋅x w ⋅ x 表示 w w 和 x x 的內积, sign s i g n 是符号函数.
输入: 训练数据集 T={(x1,y1),⋅⋅⋅,(xN,yN)} T = { ( x 1 , y 1 ) , ⋅ ⋅ ⋅ , ( x N , y N ) } 其中 xi∈χ=Rn,yi∈γ={−1,+1},i=1,2,⋅⋅⋅,N; x i ∈ χ = R n , y i ∈ γ = { − 1 , + 1 } , i = 1 , 2 , ⋅ ⋅ ⋅ , N ; 学习率 η(0<η≤1) η ( 0 < η ≤ 1 )
输出: w,b w , b 感知机模型 f(x)=sign(w⋅x+b) f ( x ) = s i g n ( w ⋅ x + b )
(1)选取初值 w0,b0 w 0 , b 0
(2)在训练集中选取数据 (xi,yi) ( x i , y i )
(3)如果 yi(w⋅x+b)≤0 y i ( w ⋅ x + b ) ≤ 0
转至(2),直至训练集中没有误分类点
在当一个实例点被误分类,就是当其位于分离超平面的错误的一侧,就是根据梯度下降的方法对 w,b w , b 进行调整,让分离超平面移动,使得它中所有的训练数据都被正确分类,
正实例点 x1=(3,3),x2=(4,3) x 1 = ( 3 , 3 ) , x 2 = ( 4 , 3 )
负实例点 x3=(1,1) x 3 = ( 1 , 1 )
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
x = np.array([[3, 3], [4, 3], [1, 1]])
y = np.array([[1], [1], [-1]])
w = [0,0]
b = 0
def train(x,y,w,b):
length = x.shape[0]
j = 0
while True:
count = 0 # 记录误分类点的数目
for i in range(length):
# 对矩阵进行运算
print("迭代次数:%d w:%d %d b:%d"%(j,w[0],w[1],b))
m = np.dot(w,x[i]) + b
# 如果是误分类点, 0 恰好在平面上
if m * y[i] <= 0:
w = w + y[i]*x[i]
b = b + y[i]
count += 1
j += 1
if count == 0:
print("\n最优参数",w,b)
f = "f(x) = sign(%d*x+%d*y+(%d)"%(w[0],w[1],b)
print("\n感知机模型:\n%s\n"%f)
return w, b, f
w,b,f = train(x,y,w,b )
# 绘图
def fun(x):
y = (-b -w[0] * x) / w[1]
return y
x_data = np.linspace(0, 5, 100) # 创建等差数组
y_data = fun(x_data)
plt.plot(x_data, y_data, color='r', label='y1 data')
plt.title("test")
for i in range(x.shape[0]):
if y[i] < 0:
plt.scatter(x[i][0], x[i][1], marker='x', s=50)
else:
plt.scatter(x[i][0], x[i][1], s=50)
plt.show()
迭代次数:0 w:0 0 b:0
迭代次数:1 w:3 3 b:1
迭代次数:1 w:3 3 b:1
迭代次数:2 w:2 2 b:0
迭代次数:2 w:2 2 b:0
迭代次数:2 w:2 2 b:0
迭代次数:3 w:1 1 b:-1
迭代次数:3 w:1 1 b:-1
迭代次数:3 w:1 1 b:-1
迭代次数:4 w:0 0 b:-2
迭代次数:5 w:3 3 b:-1
迭代次数:5 w:3 3 b:-1
迭代次数:6 w:2 2 b:-2
迭代次数:6 w:2 2 b:-2
迭代次数:6 w:2 2 b:-2
迭代次数:7 w:1 1 b:-3
迭代次数:7 w:1 1 b:-3
迭代次数:7 w:1 1 b:-3
最优参数 [1 1] [-3]
感知机模型:
f(x) = sign(1*x+1*y+(-3)
对偶感知机的策略和原始感知机的策略是一致的,唯一不同的是对 w,b w , b 两个参数的调整:
通过上面原始的感知机的练习我们很清晰的知道了求超平面,其实就是在不同修改函数系数 w,b w , b ,经过n次的修改后 w,b w , b 关于 (xi,yi) ( x i , y i ) 的增量变为了 αiyixi,αiyi α i y i x i , α i y i ,其中 αi=niη α i = n i η ,所以:
这样更新的的式子就可以变为,如果 yi{∑Nj=1αjyjxj⋅xi+b}≤0 y i { ∑ j = 1 N α j y j x j ⋅ x i + b } ≤ 0 :
技巧:
在对偶形式训练数据以內积的形式出现,为了方便可以先对其內积做计算,以矩阵的形式存储起来,用的时候调用即可。这个矩阵就是Gram矩阵
import numpy as np
import matplotlib.pyplot as plt
x = np.array([[3, 3], [4, 3], [1, 1]])
y = np.array([[1], [1], [-1]])
# 创建gram矩阵
z = np.transpose(x)
m = np.dot(x,z)
print("构建的Gram矩阵为:\n",m)
print("-------------------------")
a = np.zeros((x.shape[0], 1))
b = 0
def train(x,y,m,a,b):
length = x.shape[0]
while True:
count = 0
for i in range(length):
n = np.dot(m[i], a * y ) + b
if n* y[i] <= 0:
a[i] = a[i] + 1
b = b + y[i]
count += 1
if count == 0:
w = np.sum(x * a* y, axis=0)
print(w,b)
print("感知机模型:\nf(x) = sign(%dx+%dy+(%d))\n"%(w[0],w[1],b))
return w,b
w,b = train(x,y,m,a,b)
def fun(x):
y = (-b -w[0] * x) / w[1]
return y
x_data = np.linspace(0, 5, 100) # 创建等差数组
y_data = fun(x_data)
plt.plot(x_data, y_data, color='r', label='y1 data')
for i in range(x.shape[0]):
if y[i] < 0:
plt.scatter(x[i][0], x[i][1], marker='x', s=50)
else:
plt.scatter(x[i][0], x[i][1], s=50)
plt.show()
构建的Gram矩阵为:
[[18 21 6]
[21 25 7]
[ 6 7 2]]
-------------------------
[1. 1.] [-3]
感知机模型:
f(x) = sign(1x+1y+(-3))
End