机器学习之感知机算法原理及python实现

一、感知机的定义

感知机是二分类的线性分类模型,输入多个信号,输出一个信号(类别),属于判别模型。

二、感知机模型

感知机模型的公式:
在这里插入图片描述
其中w表示输入信号在模型公式中的权重,b输入信号在模型公式中的偏置,w•x表示w和x的内积。sign为激励函数,即激活函数:
在这里插入图片描述
感知机超平面的线性方程为:
在这里插入图片描述

在这里插入图片描述
为什么说w为超平面S的法向量?
在这里插入图片描述

三、感知机的学习策略

假设训练数据是线性可分的,感知机的学习目标是求得一个能够将数据集正实例点和负实例点完全正确分开的超平面。为找出这样的超平面,需要确定感知机的模型参数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)}")

注:纸上得来终觉浅,绝知此事要躬行。

  • 17
    点赞
  • 126
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值