感知机对偶形式python实现

本文介绍了一种基于感知机模型的学习算法,特别关注于线性可分数据集上的应用。通过详细的步骤解析,展示了如何利用该算法找到最佳的分类超平面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法

输入:

  • 线性可分的数据集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

    其中w=∑j=1Nαjyjxj\overset{N}{\underset{j=1}{\sum}}\alpha_jy_jx_jj=1Nαjyjxj

  • 感知机模型f(x)=sign(∑j=1Nαjyjxj⋅x+b)f(x)=sign(\overset{N}{\underset{j=1}{\sum}}\alpha_jy_jx_j·x+b)f(x)=sign(j=1Nαjyjxjx+b)

流程:

  1. 选取初始值α0,b0\alpha_0,b_0α0,b0

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

  3. 如果yi(∑j=1Nαjyjxj⋅xi+b)<=0y_i(\overset{N}{\underset{j=1}{\sum}}\alpha_jy_jx_j·x_i+b)<=0yi(j=1Nαjyjxjxi+b)<=0
    αi←αi+ηb←b+ηyi \alpha_i\leftarrow{\alpha_i}+\eta\\ b\leftarrow{b+{\eta}y_i} αiαi+ηbb+ηyi

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

其中,每次实例仅以内积的形式出现,即公式中的xj⋅xix_j\cdot{x_i}xjxi,每次循环算一遍不方便

我们可以预先将所有的xj⋅xix_j\cdot{x_i}xjxi算好放到矩阵中存储,这个矩阵就是所谓的Gram矩阵
G=[xi⋅xj]N×N G = [x_i\cdot{x_j}]_{N\times{N}} G=[xixj]N×N

题目

有一训练集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. 选取αi=0,i=1,2,3,n=0,η=1\alpha_i=0,i=1,2,3,n=0,\eta=1αi=0,i=1,2,3,n=0,η=1

  2. 计算Grama矩阵存储,即G=[xi⋅xj]N×NG = [x_i\cdot{x_j}]_{N\times{N}}G=[xixj]N×N,供下面计算判断使用

  3. 循环实例,若yi(∑j=1Nαjyjxj⋅xi+b)<=0y_i(\overset{N}{\underset{j=1}{\sum}}\alpha_jy_jx_j·x_i+b)<=0yi(j=1Nαjyjxjxi+b)<=0
    αi←αi+ηb←b+ηyi \alpha_i\leftarrow{\alpha_i}+\eta\\ b\leftarrow{b+{\eta}y_i} αiαi+ηbb+ηyi

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

代码

# -*- 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.a = 0
        self.w = 0
        self.b = 0
        self.eta = 1 # 步长

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

        # 获取特征向量的个数
        temp = x.shape
        n = temp[0]

        # 计算gram矩阵  点积转置即可
        gram = np.dot(x,np.transpose(x))

        # 初始化alpha和b
        alpha = np.zeros(n)  # alpha表示每个实例更新了多少次w,所以长度和实例个数一致
        b = 0

        # 循环迭代
        flag = True  # 迭代条件
        while flag:
            flag = False
            # 对每个实例进行计算并更新alpha和b
            for i in range(n):
                res = y[i] * (np.dot(alpha*y,gram[i])+b)
                if res <= 0:  # 误分类时,更新alpha和b,并重新迭代
                    alpha[i] += self.eta
                    b += self.eta * y[i]
                    flag = True
                    break
        self.w = np.dot(alpha*y,x)
        self.b = b
        print("计算得到法向量w={0},b={1}".format(self.w, self.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、付费专栏及课程。

余额充值