感知机 李航《统计学习方法》中的例题实现

该博客介绍了感知机的学习算法,包括原始形式和对偶形式,并提供了Python实现。原始形式通过不断调整权重和偏置来寻找正确分类的超平面,而对偶形式则通过更新核矩阵和权重向量来实现。文章还包含了测试感知机模型的函数和展示数据分布及超平面的图像绘制方法。

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

感知机的概念、算法请参照书本,这里只给出代码。

'''
##############感知机学习算法原始形式 开始##############

输入:训练数据集T={x1,y1},...,{xn,yn},学习率l
输出:w,b,感知机模型f(x)=sign(w·x+b)
(1)选取初始值w0,b0;
(2)在训练集中选取数据(xi,yi)     (i为下标,范围是1-n)
(3)如果yi(w·xi+b)<=0,
    w=w+lyixi
    b=b+lyi
(4)转至(2),直至训练集中没有误分类点

##############感知机学习算法原始形式 结束##############

##############感知机学习算法对偶形式 开始##############

输入:训练数据集T={x1,y1},...,{xn,yn},学习率l
输出:a,b,感知机模型f(x)=sign((累加ajyjxj(j从1到n))*x+b),其中a=(a1,a2,...,an)^T
(1)选取初始值a0,b0;
(2)在训练集中选取数据(xi,yi)     (i为下标,范围是1-n)
(3)如果((累加ajyjxj(j从1到n))*x+b)<=0,
    a=a+l
    b=b+lyi
(4)转至(2),直至训练集中没有误分类点

Gram matrix: G = [xi·xj]n*n
#######感知机学习算法对偶形式 结束#######
'''
import numpy as np
import matplotlib.pyplot as plt


class train():
    # f(x)=sign(wx+b)
    def originalTrain(self, x, y, w, b, dimension):
        wx = sum(x[j] * w[j] for j in range(dimension))
        f = y * (wx + b)
        return f

    def originalTrain(self, data, learning_rate, max_loop_cnt=10000):  # 训练集,学习率,最大迭代次数
        data_num = len(data)  # 数据集大小
        if data_num == 0:  # 没有数据,直接返回
            return None
        dimension = len(data[0][0])  # 特征向量的维度
        w = [0 for i in range(dimension)]  # 初始化w0,b0
        b = 0
        for k in range(max_loop_cnt):
            loop_end = True
            for i in range(data_num):  # 计算第(3)步
                x, y = data[i][0], data[i][1]
                wx = sum(x[j] * w[j] for j in range(dimension))
                f = y * (wx + b)  # 计算f=yi(w·xi+b)
                while f <= 0:
                    for j in range(dimension):
                        w[j] = w[j] + learning_rate * y * x[j]
                    b = b + learning_rate * y
                    wx = sum(x[j] * w[j] for j in range(dimension))
                    f = y * (wx + b)
                    print('i,x,y,w,b,f', i, x, y, w, b, f)
                    loop_end = False

            if loop_end:
                print("All data are classified correctly by using originalTrain")
                return w, b

        return None

    def dualTrain(self, data, learning_rate, max_loop_cnt=10000):  # 对偶形式
        data_num = len(data)
        dimension = len(data[0][0])
        gram = [  # 先计算gram matrix
            [
                sum([data[i][0][k] * data[j][0][k]
                     for k in range(dimension)])
                for j in range(data_num)
            ]
            for i in range(data_num)
        ]
        print('gram', gram)
        alpha = [0 for i in range(data_num)]
        b = 0
        print('alpha', alpha)
        for k in range(max_loop_cnt):  # 与原始形式的做法类似
            loop_end = True
            for i in range(data_num):
                y = data[i][1]
                tmp = sum(alpha[j] * data[j][1] * gram[j][i] for j in range(data_num)) + b
                f = tmp * y
                while f <= 0:
                    alpha[i] += learning_rate
                    b += learning_rate * y
                    tmp = sum(alpha[j] * learning_rate * data[j][1] * gram[j][i] for j in range(data_num)) + b
                    f = tmp * y
                    loop_end = False
                    print('dual change', i, data[i][0], data[i][1], alpha, b, f)

            if loop_end:
                print("All data are classified correctly by using dualTrain")
                return alpha, b

        return None


class perceptron():  # 感知机模型
    def __init__(self, w, b):
        self.w = w
        self.b = b

    def percept(self, x):  # 进行计算
        f = sum(self.w[i] * x[i] for i in range(len(x))) + self.b
        print(f)
        if f > 0:
            return 1
        elif f < 0:
            return -1


def test(data):  # 测试感知机模型,并输出w,b
    tr = train()
    w, b = tr.originalTrain(data, 1)
    alpha, b = tr.dualTrain(data, 1)
    print('w,b', w, b)
    # print('alpha,b',alpha,b)
    per = perceptron(w=w, b=b)
    print(per.percept((1, 1)))
    return w, b


def showPicture(data, w, b):  # 画出数据的图像以及分离超平面
    data = [data[i][0] for i in range(len(data))]
    # print(data)
    data = np.array(data)
    m, n = data.shape

    # 画出所有数据点
    for i in range(m):
        x, y = data[i][0], data[i][1]
        plt.annotate("(%s,%s)" % (x, y), xy=(x, y))
        plt.scatter(x, y)

    max_num = np.max(data)

    # 画出超平面
    x = np.linspace(0, max_num + 10)
    #w0x+w1y+b=0 1.如果w1=0,x=-1/w0,否则y=(-b-w0·x)/w1
    if w[1] == 0:
        x = -b / w[0]
    else:
        y = (-b - w[0] * x) / w[1]
    plt.plot(x, y)
    plt.show()


if __name__ == '__main__':
    data = [((3, 3), 1), ((4, 3), 1), ((1, 1), -1)]
    print('data', data)
    w, b = test(data)
    showPicture(data, w, b)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值