感知机是二分类的线性分类模型,输入多个信号,输出一个信号(类别),属于判别模型。
感知机模型的公式:
其中w表示输入信号在模型公式中的权重,b输入信号在模型公式中的偏置,w•x表示w和x的内积。sign为激励函数,即激活函数:
感知机超平面的线性方程为:
假设训练数据是线性可分的,感知机的学习目标是求得一个能够将数据集正实例点和负实例点完全正确分开的超平面。为找出这样的超平面,需要确定感知机的模型参数w,b,定义一个损失函数并将其最小化。
损失函数的定义:损失函数是用来评估训练值和真实值不一致的程度。
损失函数优化的方法:梯度下降法、最小二乘法、牛顿法
确定损失函数:
我们将大于0的分为+1类,小于0的分为-1类,当有些值是大于0而分为-1类,因此就产生了误分类。在二维情况下,是用一条直线将类别分开,即误分类的个数就是它的损失情况,由于此次采用梯度下降法作为对损失函数的优化,而误分类的个数是离散化的,因此需要转换另一种思路,即误分类点到超平面的距离作为损失函数。
因此误分类点到超平面的距离公式为:
M为误分类点的数目
感知机学习的模型是最小化一个损失函数,因此损失函数为:
采用梯度下降法对模型参数的更新,梯度下降法的含义是沿梯段的负方向(负梯度),梯度减少的最快,越容易找到损失函数的最小值。
损失函数L(w,x)的梯度为
由于采用梯度下降法,因此下降的梯度为
当碰到一个误分类时,对w,b进行更新
感知机算法的求解步骤:
0.输入训练数据集(注意是线性可分的),并给输入的每个数据打上标签
输出:w,b,感知机模型
初始化w0、b0
2.在训练数据集中选取每个数据
3.如果碰到一个误分类,就需要更新模型参数
4.转至第2步,直至训练中没有误分类点为止
5.输出:w,b,感知机模型
#-*- coding=utf-8 -*-
"""
感知机:
感知机是二分类的线性分类模型,输入为实例的特征向量,输入为实例的类别(+1和-1)
#0.输入数据集
#1.选取初始值w0、b0
#2.在训练集中选取数据x,y
#3.如果y(wx+b)<=0,则更新权重和偏置参数
#4.转至第二步,直至训练数据集中没有误分类的点
#5.输出w,b,感知机模型
"""
from matplotlib import pyplot as plt
#0.输入数据集
x = [(1,2),(2.5,3),(1.5,1),(5,4.5),(6,3),(2,2),(3,5),(6,4),(5,3)]
y = [-1,-1,-1,1,1,-1,1,1,1] #标记数据类别
x1 = [ x[i][0] for i in range(len(x))]
x2 = [ x[i][1] for i in range(len(x))]
#用不同的颜色和形状将类别区分
color = [ "red" if i>0 else "blue" for i in y ]
maker = ["o" if i>0 else "x" for i in y ]
for x1_,x2_,color,maker in zip(x1,x2,color,maker):
plt.scatter(x1_,x2_,c=color,marker=maker)
plt.text(0.5,0.5,r"-1")
plt.text(6,6,r"+1")
plt.plot((6,0),(0,6),linestyle="-",linewidth=2) #假设超平面
plt.text(5,1,r"wx+b=0")
plt.title("感知机模型散点图",fontproperties ="SimHei")
plt.xlabel("x1")
plt.ylabel("x2")
#取除图形上方和右方边框
ax = plt.gca()
ax.spines["right"].set_color("none")
ax.spines["top"].set_color("none")
plt.savefig("数据集散点图.png")
plt.show()
#训练
#1.在训练集中选取数据x,y
#2.在训练集中选取数据x,y
w,b = [0,0],0
start = True
while start:
k = 1
for i in range(len(x)):
x_1,x_2 =x[i]
s = w[0]*x_1 + w[1]*x_2 + b
#3.如果y(wx+b)<=0,则更新权重和偏置参数
if (s>=0 and y[i]<0) or (s<=0 and y[i]>0): #说明是误分类
w[0] += x_1*y[i]
w[1] += x_2*y[i]
b += y[i]
print(w,b)
#4.转至第二步,直至训练数据集中没有误分类的点
else:
k += 1 #正确分类的个数
if k == len(x):
start = False
m = [ "o" if w[0]*x_1 + w[1]*x_2 + b > 0 else "x" for x_1,x_2 in x ]
c = [ "red" if w[0]*x_1 + w[1]*x_2 + b > 0 else "blue" for x_1,x_2 in x ]
for x1_,x2_,color,maker in zip(x1,x2,c,m):
plt.scatter(x1_,x2_,c=color,marker=maker)
#由于超平面上的线需要经过x轴,和y=6边界
xx = (-b/w[0],0)
yy = (-((b+6*w[1])/w[0]),6)
#print(xx,yy)
plt.plot([xx[0],yy[0]],[xx[1],yy[1]]) #此处的点需为x,y的列表
ax = plt.gca()
ax.spines["right"].set_color("none")
ax.spines["top"].set_color("none")
plt.savefig("感知机模型分类图.png")
plt.show()
print(f"f(x)=wx+b,其中w的值为:{w},b的值为:{b}")
#预测
test_set = [(1,2),(3,4),(6,3),(2,6)]
predict = ["+1" if test_set[i][0]*w[0] + test_set[i][1]*w[1] +b >0 else "-1" for i in range(len(test_set))]
print(f"预测数量的依次类别为:{','.join(predict)}")