感知机对偶形式python实现

算法

输入:

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

输出:

  • w,b

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

  • 感知机模型 f ( x ) = s i g n ( ∑ j = 1 N α j y j x j ⋅ 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 , b 0 \alpha_0,b_0 α0,b0

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

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

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

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

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

题目

有一训练集T,其正实例的点是 x 1 = ( 3 , 3 ) T , x 2 = ( 4 , 3 ) T x_1=(3,3)^T,x_2=(4,3)^T x1=(3,3)T,x2=(4,3)T,负实例的点是 x 3 = ( 1 , 1 ) T x_3=(1,1)^T x3=(1,1)T

求感知机模型 f ( x ) = s i g n ( w ⋅ x + b ) f(x)=sign(w·x+b) f(x)=sign(wx+b),其中, w = ( w ( 1 ) , w ( 2 ) ) T w=(w^{(1)},w^{(2)})^T w=(w(1),w(2))T, x = ( x ( 1 ) , x ( 2 ) ) T x=(x^{(1)},x^{(2)})^T x=(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 = [ x i ⋅ x j ] N × N G = [x_i\cdot{x_j}]_{N\times{N}} G=[xixj]N×N,供下面计算判断使用

  3. 循环实例,若 y i ( ∑ j = 1 N α j y j x j ⋅ x i + b ) < = 0 y_i(\overset{N}{\underset{j=1}{\sum}}\alpha_jy_jx_j·x_i+b)<=0 yi(j=1Nαjyjxjxi+b)<=0
    α i ← α i + η b ← b + η y i \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、付费专栏及课程。

余额充值