感知机python实现

算法

输入:

  • 线性可分的数据集T=(x1,y1),(x2,y2),...,(xN,yN)T={(x_1,y_1),(x_2,y_2),...,(x_N,y_N)}T=(x1,y1),(x2,y2),...,(xN,yN),其中xi∈X=Rn,yi∈Y={−1,1},i=1,2,...,Nx_i∈X=R^n,y_i∈Y=\{-1,1\},i=1,2,...,NxiX=Rn,yiY={1,1}i=1,2,...,N
  • 学习率η(0<η<=1)\eta(0<\eta<=1)η(0<η<=1)

输出:

  • w,b
  • 感知机模型f(x)=sign(w⋅x+b)f(x)=sign(w·x+b)f(x)=sign(wx+b)

流程:

  1. 选取初始值w0,b0w_0,b_0w0,b0

  2. 在训练集中选取数据(xi,yi)(x_i,y_i)(xi,yi)

  3. 如果yi(w⋅xi+b)<=0y_i(w·xi+b)<=0yi(wxi+b)<=0
    w←w+ηyixib←b+ηyi w\leftarrow{w+{\eta}y_ix_i}\\ b\leftarrow{b+{\eta}y_i} ww+ηyixibb+ηyi

  4. 跳转至2,直到训练集中没有误分类点

题目

有一训练集T,其正实例的点是x1=(3,3)T,x2=(4,3)Tx_1=(3,3)^T,x_2=(4,3)^Tx1=(3,3)T,x2=(4,3)T,负实例的点是x3=(1,1)Tx_3=(1,1)^Tx3=(1,1)T

求感知机模型f(x)=sign(w⋅x+b)f(x)=sign(w·x+b)f(x)=sign(wx+b),其中,w=(w(1),w(2))Tw=(w^{(1)},w^{(2)})^Tw=(w(1),w(2))T,x=(x(1),x(2))Tx=(x^{(1)},x^{(2)})^Tx=(x(1),x(2))T

解法

  1. 构建最优化问题
    minw,bL(w,b)=−∑xi∈Myi(wi⋅xi+b) \underset{w,b}{min}L(w,b) = -\sum_{x_i∈M}y_i(w_i·x_i+b) w,bminL(w,b)=xiMyi(wixi+b)

  2. 选取步长η\etaη为1

  3. 初始化w0=0,b0=0w_0=0,b_0=0w0=0,b0=0

  4. 循环实例x,如果yi(w⋅xi+b)<=0y_i(w·x_i+b)<=0yi(wxi+b)<=0
    w←w+ηyixib←b+ηyi w\leftarrow{w+{\eta}y_ix_i}\\ b\leftarrow{b+{\eta}y_i} ww+ηyixibb+ηyi

  5. 重复执行第四步,直到没有误分类的点

代码

# -*- coding: UTF-8 -*-
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

class PERCEPTRON:
    def __init__(self):
        # 这里写死数据,可自行改为动态读取
        df = pd.read_excel('../data/perceptronExample.xlsx')
        self.df = pd.DataFrame(df)

        # 最终的结果
        self.w = 0
        self.b = 0

    '''训练'''
    def train(self):
        df = self.df
        x = df.values[:, :-1]  # 提取所有特征向量
        y = df.values[:, -1]  # 提取分类结果

        # 获取特征向量的个数以及每个特征向量的长度
        temp = x.shape
        n = temp[0]
        m = temp[1]

        # 初始化w和b
        w = np.zeros(m)  # w的长度与特征向量长度相同
        b = 0

        # 循环迭代
        flag = True
        while flag:
            flag = False
            # 对每个实例进行计算并更新w和b
            for i in range(n):
                res = y[i] * (np.dot(w, x[i]) + b)  # y(w * x + b),注意w和x是点积
                if res <= 0:
                    w = w + np.dot(y[i], x[i])
                    b = b + y[i]
                    flag = True  # 有失误,待继续迭代
        self.w = w
        self.b = b
        print("计算得到法向量w={0},b={1}".format(w, b))

    '''可视化展示'''
    def show(self):
        y = self.df.values[:, -1]
        x1 = self.df.values[:, 0]
        x2 = self.df.values[:, 1]

        # 点
        for i in range(len(self.df)):
            if (y[i] == 1):
                s1 = plt.scatter(x1[i], x2[i], c='red')
            else:
                s2 = plt.scatter(x1[i], x2[i], c='blue')
        plt.legend([s1, s2], ['正类', '负类'])

        # 线
        xmin = self.df.values[:, :-1].min()
        xmax = self.df.values[:, :-1].max()
        xstep = (xmax - xmin) * 0.5  # 步长
        xx = np.linspace(xmin - xstep, xmax + xstep, 3)  # 横坐标
        yy = -self.w[0] * xx - self.b  # 根据得到的参数计算纵坐标
        plt.plot(yy, xx)
        plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文乱码问题
        plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
        plt.show()


if __name__ == '__main__':
    perceptron = PERCEPTRON()
    perceptron.train()
    perceptron.show()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值