感知机算法python实现

感知器

  • 感知器是一种人工神经网络,其模拟生物上的神经元结构
  • 感知器是一个二分类器,其将净输入为:
    z = W T X = w 0 + w 1 x 1 + w 2 x 2 + ⋯ + w n x n z=W^{T}X=w^{0}+w^{1}x^{1}+w^{2}x^{2}+\cdots+w^{n}x^{n} z=WTX=w0+w1x1+w2x2++wnxn
    • 通过激活函数 φ ( z ) \varphi(z) φ(z),就可以将其映射为1或-1
    • φ ( z ) = { 1 z ≥ θ − 1 z < θ \varphi(z)=\begin{cases} 1 & z\geq \theta \\ -1 & z<\theta \end{cases} φ(z)={11zθz<θ
    • 其中 θ \theta θ是我们指定的一个值
import numpy as np
import pandas as pd
#还是使用鸢尾花数据集
data=pd.read_csv(r"F:\数据集\Iris数据集\iris.csv")
#删除“Unnamed: 0”列
data.drop("Unnamed: 0",axis=1,inplace=True)
#删除重复的记录
data.drop_duplicates(inplace=True)
#data["Species"].value_counts()
#分类别映射  之所以映射为1和-1而非之前的0 1 2 ,是因为感知器的预测结果为1和-1
#目的是为了与感知器的预测结果相符
data["Species"]=data["Species"].map({"versicolor":0,"virginica":1,"setosa ":-1})
#筛选预测结果为1和-1的数据
data=data[data["Species"]!=0]
len(data)
99

编写感知器类

class Perception:
    """
    使用python语言实现感知器算法,实现二分类
    """
    def __init__(self,alpha,times):
        """
        初始化方法:
        Parameters:
        -------------
        alpha:float
           学习率
        times:int
           最大迭代次数
        """
        self.alpha=alpha
        self.times=times
        
    def step(self,z):
        """
        阶跃函数
        
        Paraneters:
        -------------------
        z:数组类型。(或者是标量类型)
           阶跃函数的参数,可以跟据z值,返回1或-1(这样可以实现二分类)
           
        Return:
        -------------
        value:int
           如果z>=0,返回1,否则返回-1
        """
        #return 1 if z>=0 else -1  这是python写法,但只能用于标量,所以下面的更通用些
        #不论z是标量还是数组都行
        return np.where(z>=0 ,1,-1)
    
    def fit(self,X,y):
        """
        根据提供的训练数据,对模型进行训练
        Parameters
        -------------
        X:类数组类型。形状:[样本数量,特征数量]
           待训练的样本数据。
           
        y:类数组类型。形状:[样本数量]
           每个样本的目标值。(分类)
        """
        X=np.asarray(X)
        y=np.asarray(y)
        #创建权重的向量,初始值为0,长度比特征多1,(多出的一个就是截距)
        self.w_=np.zeros(1+X.shape[1])
        #创建损失列表,用来保存每次迭代后的损失值
        self.loss_=[]
        #循环指定的次数
        for i in range(self.times):
            #感知器与逻辑回归的区别:逻辑回归中使用所有样本计算梯度,然后更新权重
            #而感知器中,是使用单个样本,依次进行计算梯度,更新权重
            loss=0
            for x,target in zip(X,y):
                #计算预测值  x是矩阵X 中的一行
                y_hat=self.step(np.dot(x,self.w_[1:])+self.w_[0])
                #若预测值不等于真实值,loss加1
                loss+=y_hat!=target
                #更新权重  更新公式:w(j)=w(j)+学习率*(真实值-预测值)*x(j)
                self.w_[0]+=self.alpha*(target-y_hat)
                self.w_[1:]+=self.alpha*(target-y_hat)*x
            #将循环中增加的误差值增加到误差列表中
            self.loss_.append(loss)
            
    def predict(self,X):
        """
        根据参数传递的样本,对样本数据进行预测。(1或-1)
        Parameters:
        --------------
        X:类数组类型,形状为:[样本数量,特征数量]
           待预测的样本特征。
        
        Returns:
        ---------------
        result:数组类型
            预测的结果值(分类值1或-1)
        """
        return self.step(np.dot(X,self.w_[1:])+self.w_[0])
                
    

测试与可视化

#分离出两个类别的数据
t1=data[data["Species"]==1]
t2=data[data["Species"]==-1]
#对两类数据进行洗牌
t1=t1.sample(len(t1),random_state=0)
t2=t2.sample(len(t2),random_state=0)
#构建训练集和测试集
train_X=pd.concat([t1.iloc[:40,:-1],t2.iloc[:40,:-1]],axis=0)
train_y=pd.concat([t1.iloc[:40,-1],t2.iloc[:40,-1]],axis=0)
test_X=pd.concat([t1.iloc[40:,:-1],t2.iloc[40:,:-1]],axis=0)
test_y=pd.concat([t1.iloc[40:,-1],t2.iloc[40:,-1]],axis=0)
p=Perception(0.1,10)
p.fit(train_X,train_y)
result=p.predict(test_X)
display(result)
display(test_y.values)
display(p.w_)
display(p.loss_)
array([1, 1, 1, 1, 1, 1, 1, 1, 1])



array([1., 1., 1., 1., 1., 1., 1., 1., 1.])



array([0., 0., 0., 0., 0.])



[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rcParams["font.family"]="SimHei"
mpl.rcParams["axes.unicode_minus"]=False
#绘制真实值
plt.plot(test_y.values,"go",ms=15,label="真实值")
#绘制预测值
plt.plot(result,"rx",ms=15,label="预测值")
plt.title("感知器-二分类")
plt.xlabel("样本序号")
plt.ylabel("类别")
plt.legend()
plt.show()

在这里插入图片描述

#绘制目标函数损失值
plt.plot(range(1,p.times+1),p.loss_,"o-")
[<matplotlib.lines.Line2D at 0x4c13bb7c08>]

在这里插入图片描述


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值