1。综述
感知机(perceptron)是而分类的线性分类模型,输入为实例的特征向量,输出为实例的类别,取+1或-1值,即正类或负类。感知机对应于输入空间中的将输入特征分类的超平面,属于判别模型。
利用梯度下降对误分类的损失函数进行最小化,求的感知机模型。
输出空间为:
y={+1,-1}
感知机的从输入到输出的函数:
f(x) = sign(w*x+b)
其中,w,b为感知机的参数,w叫做权值,b称为偏置。
感知机的损失函数的定义为:
L(w,b)=∑yi(w∗xi+b)
L
(
w
,
b
)
=
∑
y
i
(
w
∗
x
i
+
b
)
感知机学习步骤:
输入:训练数据集
T=(x1,y1),(x2,y2).....(xN,yN)
T
=
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
.
.
.
.
.
(
x
N
,
y
N
)
其中, yi y i ={+1,-1},i=1,2……N,学习率(步长) η=(0,1] η = ( 0 , 1 ]
输出:w,b;感知机模型:f(x) = sign(w*x+b)
(1)选取初值 w0,b0 w 0 , b 0
(2)选取训练集中数据集 (xi,yi) ( x i , y i )
(3)如果 yi(w∗xi+b)<=0 y i ( w ∗ x i + b ) <= 0 ,则:
w=w+ηyixi
w
=
w
+
η
y
i
x
i
b=b+ηyi
b
=
b
+
η
y
i
(4)继续(2)直到没有误分点。
直观解释:
当一个实例点被误分类时,即位于分离超平面的错误一侧时,调整w,b的值,使其分离超平面向误分类的一侧移动,减少误分点到该平面的距离,直到该点被正确分类。
2。代码
#!/user/bin/env python
#-*- coding:utf-8 -*-
import copy
from matplotlib import pyplot as plt
from matplotlib import animation#绘制动图
training_set=[[[3,3],1],[[4,3],1],[[1,1],-1]]
#初值选择为0
w=[0,0]
b=0
history=[]
#对应于(3)
def update(item):
# 更新参数,步长为1
global w,b,history
w[0]+=1*item[1]*item[0][0]
w[1]+=1*item[1]*item[0][1]
b+=1*item[1]
print(w,b)
history.append([copy.copy(w),b])
def cal(item):#计算函数值y(w*x+b)
res=0
for i in range(len(item[0])):
res+=item[0][i]*w[i]
res+=b
res*=item[1]
return res
def check():
#检查是否需要继续更新
flag=False
for item in training_set:
if cal(item)<=0:
flag=True
update(item)
if not flag:
print("RESULT:w:"+str(w)+"b:"+str(b))
return flag
if __name__=="__main__":
for i in range(1000):
if not check():
break
#下面是绘图
fig=plt.figure()
ax=plt.axes(xlim=(0,2),ylim=(-2,2))
line,=ax.plot([],[],'g',lw=2)
label=ax.text([],[],'')
def init():
line.set_data([],[])
x,y,x_,y_,=[],[],[],[]
for p in training_set:
if p[1]>0:
x.append(p[0][0])
y.append(p[0][1])
else:
x_.append(p[0][0])
y_.append(p[0][1])
plt.plot(x,y,'bo',x_,y_,'r^')
plt.axis([-6,6,-6,6])
plt.grid()
plt.xlabel('x1')
plt.ylabel('x2')
plt.title('Perception')
return line,label
def animate(i):
global history,ax,line,label
w=history[i][0]
b=history[i][1]
if w[1]==0:return line,label
x1 = -7.0
y1 = -(b + w[0] * x1) / w[1]
x2 = 7.0
y2 = -(b + w[0] * x2) / w[1]
line.set_data([x1, x2], [y1, y2])
x1 = 0.0
y1 = -(b + w[0] * x1) / w[1]
label.set_text(str(history[i][0]) + ' ' + str(b))
label.set_position([x1, y1])
return line, label
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=len(history), interval=1000, repeat=True,blit=True)
#保存为动图需要安装imagemagick模块
anim.save('sin_dot.gif', writer='imagemagick', fps=30)
plt.show()
update过程
最终执行结果
3。sklearn库实现感知机
"""使用sklearn实现感知机"""
from sklearn.datasets import make_classification
x,y = make_classification(n_samples=1000,n_features=2,n_redundant=0,n_informative=1,n_clusters_per_class=1)
#print(x[1,0])
x_data_train = x[:800]#数组切片,开始到800
x_data_test = x[800:]
y_data_train = y[:800]
y_data_test = y[800:]
from sklearn.linear_model import Perceptron
clf = Perceptron(fit_intercept=False,max_iter=30,shuffle=False)
clf.fit(x_data_train,y_data_train)
print(clf.coef_)#w参数
print(clf.intercept_)#b参数,超平面截距
acc = clf.score(x_data_test,y_data_test)#使用测试集进行验证
print(acc)
positive_x1 = [x[i,0] for i in range(1000) if y[i] == 1]
positive_x2 = [x[i,1] for i in range(1000) if y[i] == 1]
negetive_x1 = [x[i,0] for i in range(1000) if y[i] == 0]
negetive_x2 = [x[i,1] for i in range(1000) if y[i] == 0]
from matplotlib import pyplot as plt
import numpy as np
#画出正例和反例的散点图
plt.scatter(positive_x1,positive_x2,c='red')
plt.scatter(negetive_x1,negetive_x2,c='blue')
#画出超平面(在本例中即是一条直线)
line_x = np.arange(-4,4)
#将x1,x2在数标柱表示
line_y = line_x * (-clf.coef_[0][0] / clf.coef_[0][1]) - clf.intercept_
plt.plot(line_x,line_y)
plt.show()
结果:
[[ 0.62410563 3.88740062]]
[ 0.]
0.995