0 参考资料
机器学习之感知机模型
《统计学习方法》笔记之感知机模型及代码实现
《统计学习方法》之感知机代码实现(原始形式和对偶形式)
1 算法流程
2 代码实现
'''
日期:2022.04.15
作者:城主
功能:代码实现感知机
'''
'''
算法 2.1 感知机学习算法的初始形式
输入:训练数据集T={(x1,y1),(x2,y2),...,(xn,yn),其中y只取正负1,学习率r}
输出:w,b; 感知机模型f(x)=sign(w.x+b)
(1) 选取初值w0,b0;
(2) 在训练集中选取数据(xi,yi);
(3) 如果yi(w.xi+b)<=0:(说明错误判断的点)
w<---w+r.yi.xi
b<---b+r.yi
(4) 移至(2),直到训练集中没有误分类的点;
补充。测试数据的话,直接带入感知机模型,如果大于0就标记为1,否则就标记为-1
'''
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import Perceptron
# 生成数据集
def creatData():
# np.array,将列表转化为数组
x=np.array([[3, 3], [4, 3], [1, 1]])
y=np.array([1, 1, -1])
return x, y
pass
# 感知机学习算法实现
# shape[0]与shape[1]描述的是矩阵的行数和列数
def perceptronTrain1(x, y, r):
# 选取初值w0,b0
w=np.zeros(x.shape[1])
b=0
# 在训练集中选择数据点,计算yi.(w.xi+b),如果小于等于0,则更新w,b,并从头计算,直到没有误判点
i=0
while i < x.shape[0]:
xt=x[i]
yt=y[i]
if yt*(np.dot(w, xt)+b) <= 0:
w=w+r*np.dot(yt, xt)
b=b+r*yt
i=0
else:
i+=1
return w, b
pass
# 感知机模型的对偶式算法实现
def sign(X, Y, x, y, alpha, b, r):
result=np.sum(alpha*Y*np.dot(X, x))+b
if result >= 0:
return 1
else:
return -1
pass
def perceptronTrain2(x, y, r):
# 选取初值w0,b0
alpha=np.zeros(len(x), dtype=np.float32)
flag=False
w=0
b=0
# 在训练集中选择数据点,计算yi.(w.xi+b),如果小于等于0,则更新w,b,并从头计算,直到没有误判点
while not flag: # not false等于true的意思
wrongCnt=0
for i in range(len(x)):
xt=x[i]
yt=y[i]
if yt*sign(x, y, xt, yt, alpha, b, r) <= 0:
alpha[i]=alpha[i]+r
b=b+r*yt
w=np.dot(alpha*y, x) # 主要是每一步计算后显示W ,可以在最后计算
# print("误分类点:{} a[{}]:{} w{} b:{}".format(x, i, alpha[i], w, b))
wrongCnt+=1
if wrongCnt==0:
flag=True
w=np.dot(alpha*y, x)
return w, b
pass
# 绘制超平面上的图像
def draw(X, w, b):
# 生成分离超平面上的两点
X_new=np.array([[0], [6]])
y_predict=-b-(w[0]*X_new)/w[1]
# 绘制训练数据集的散点图
plt.plot(X[:2, 0], X[:2, 1], "g*", label="1")
plt.plot(X[2:, 0], X[2:, 1], "rx", label="-1")
# 绘制分离超平面
plt.plot(X_new, y_predict, "b-")
# 设置两坐标轴起止值
plt.axis([0, 6, 0, 6])
# 设置坐标轴标签
plt.xlabel('x1')
plt.ylabel('x2')
# 显示图例
plt.legend()
# 显示图像
plt.show()
pass
def makeByOwn():
# 在下面的代码行中使用断点来调试脚本。
[x, y]=creatData()
[w, b]=perceptronTrain2(x, y, 1)
print("f(x)=sign("+str(w)+".x+"+str(b))
draw(x, w, b)
pass
# 调用系统提供的函数来进行感知机算法的学习
def makeBySystem():
[x, y]=creatData()
# 构建Perceptron对象,训练数据并输出结果
perceptron=Perceptron()
perceptron.fit(x, y)
print("w:", perceptron.coef_, "\n", "b:", perceptron.intercept_, "\n", "n_iter:", perceptron.n_iter_)
# 测试模型预测的准确率
res=perceptron.score(x, y)
print("correct rate:{:.0%}".format(res))
# draw(x, perceptron.coef_, perceptron.intercept_)
# 绘制
# 画出正例和反例的散点图
plt.plot(x[:2, 0], x[:2, 1], "g*", label="1")
plt.plot(x[2:, 0], x[2:, 1], "rx", label="-1")
# 画出超平面(在本例中即是一条直线)
line_x=np.arange(-4, 4)
# 出现错误
# divide by zero encountered in double_scalars
# invalid value encountered in multiply
line_y=line_x*(-perceptron.coef_[0][0]/perceptron.coef_[0][1])-perceptron.intercept_
plt.plot(line_x, line_y)
plt.show()
pass
# 按间距中的绿色按钮以运行脚本。
if __name__=='__main__':
# makeByOwn()
makeBySystem()
3 小结
纸上得来终觉浅,绝知此事要躬行。
本次代码还有一些小瑕疵,在makeBySystem()函数中,没有成功画出预测线条。目前还不知道如何修改。先挖个坑,以后完善。