感知机学习算法


前言

感知机是感知机是一个二分类线性判别模型,其输入为实例的特征向量,输出为实例的类别,取+1和-1二值。感知机对应输入空间(特征空间)中将实例划分为正负两类的分离超平面,属于判别模型。

一、感知机模型

假设输入 x ∈ R n x\in \mathbb{R}^n xRn,输出 y ∈ { − 1 , + 1 } y\in\{-1,+1\} y{1,+1},感知机为如下函数:
f ( x ) = s i g n ( w T x + b ) , s i g n ( z ) = { 1 x ≥ 0 − 1 x < 0 f(x)=sign(w^Tx+b), \\sign(z)=\left\{\begin{aligned} 1 \qquad \quad x\ge0\\ -1 \qquad\quad x<0 \end{aligned}\right. f(x)=sign(wTx+b),sign(z)={1x01x<0
其中,w叫做权重,是分类超平面的法向量;b叫做偏置,是超平面的截距。
设数据集线性可分,感知机的损失函数为所有误分类点到分类超平面的函数间隔,即:
L ( w , b ) = − ∑ x i ∈ M y i ( w T x + b ) L(w,b)=-\sum_{x_i\in M}y_i(w^Tx+b) L(w,b)=xiMyi(wTx+b)

二、感知机学习算法的原始形式

输入:训练数据集 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 ∈ R n x_i\in \mathbb{R}^n xiRn Y i ∈ { − 1 , 1 } Y_i\in\{-1,1\} Yi{1,1};学习率 η ∈ ( 0 , 1 ] \eta\in(0,1] η(0,1]
输出:w,b;感知机模型 f ( x ) = s i g n ( w T x + b ) f(x)=sign(w^Tx+b) f(x)=sign(wTx+b)

  • 随机任选一个超平面 w 0 , b 0 w_0,b_0 w0,b0,一般都初始化为0
  • 在训练集中选取数据 ( x i , y i ) (x_i,y_i) (xi,yi)
  • 如果 y i ( w T x i + b ) ≤ 0 y_i(w^Tx_i+b)\le 0 yi(wTxi+b)0,则更新w和b:
    w = w + η y i x i b = b + η y i w=w+\eta y_ix_i \\b=b+\eta y_i w=w+ηyixib=b+ηyi
  • 转至第二步,直到训练集中没有误分点

三、感知机学习算法的对偶形式

对偶形式的基本想法是,将w和b表示为实例 x i x_i xi和标签 y i y_i yi的线性组合的形式,通过求解其系数而求得w和b。由感知机算法的原始形式可以得出,修改n次过后w,b关于 ( x i , y i ) (x_i,y_i) (xi,yi)的增量分别是 α i y i x i \alpha_iy_ix_i αiyixi α i y i \alpha_iy_i αiyi,这里 α i = n i η \alpha_i=n_i\eta αi=niη。这样,最后学习到的w和b可以分别表示为:
w = ∑ i = 1 N α i y i x i b = ∑ i = 1 N α i y i w=\sum_{i=1}^N\alpha_iy_ix_i \\b=\sum_{i=1}^N\alpha_iy_i w=i=1Nαiyixib=i=1Nαiyi
具体算法为:

输入:训练数据集 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 ∈ R n x_i\in \mathbb{R}^n xiRn Y i ∈ { − 1 , 1 } Y_i\in\{-1,1\} Yi{1,1};学习率 η ∈ ( 0 , 1 ] \eta\in(0,1] η(0,1]

输出: α \alpha α,b;感知机模型 f ( x ) = s i g n ( ∑ i = 1 N α i y i x i x + b ) f(x)=sign(\sum_{i=1}^N\alpha_iy_ix_ix+b) f(x)=sign(i=1Nαiyixix+b),其中 α = ( α 1 , α 2 , . . . , α N ) T \alpha=(\alpha_1,\alpha_2,...,\alpha_N)^T α=(α1,α2,...,αN)T

  • α = 0 , b = 0 \alpha=\boldsymbol 0, b=0 α=0,b=0
  • 在训练集中选取数据 ( x i , y i ) (x_i,y_i) (xi,yi)
  • 如果 y i ( ∑ j = 1 N α j y j x j x i + b ) ≤ 0 y_i(\sum_{j=1}^N\alpha_jy_jx_jx_i+b)\le 0 yi(j=1Nαjyjxjxi+b)0,则更新w和b:
    α = α + η b = b + η y i \alpha=\alpha+\eta \\b=b+\eta y_i α=α+ηb=b+ηyi
  • 转至第二步,知道训练集中没有误分点

四、收敛性和依赖性

收敛性:对于线性可分的T,经过有限次搜索,可将T正确分开的分离超平面,对于线性不可分的T,算法收敛。
依赖性:不同的初值选择,或者迭代过程中不同误分类点的选择顺序,可能得到不同的分离超平面。(为了得到唯一的分离超平面,需要约束条件)

五、代码实现

代码如下(示例):

"""
感知机
"""
import numpy as np
from sklearn.datasets import load_digits

class Perceptron(object):
    def __init__(self, m):
        self.w = np.zeros(m)  # 权重
        self.b = 0  # 偏置

    def traditional_train(self, train_x, train_y, batch_size,
                          epochs, test_x=None, test_y=None, learning_rate=1):
        """
        感知机学习算法的原始形式
        """

        num = train_x.shape[0]   # 训练集大小

        for epoch in range(epochs):
            cur = 0
            while cur < num:
                if cur+batch_size < num:
                    batch_xs = train_x[cur:cur+batch_size, :]
                    batch_ys = train_y[cur:cur+batch_size]
                else:
                    batch_xs = train_x[cur:, :]
                    batch_ys = train_y[cur:]

                pred = np.dot(batch_xs, self.w) + self.b
                pred = pred.reshape((-1,))
                pred[pred >= 0] = 1
                pred[pred < 0] = -1

                err_index = pred != batch_ys

                self.w += np.mean(batch_xs[err_index] * batch_ys[err_index].reshape(-1, 1), 0) * learning_rate
                self.b += np.mean(batch_ys[err_index]) * learning_rate

                cur += batch_size

            # 每个epoch结束输出在测试集上的精度
            if test_x is not None and test_y is not None:
                accuracy = self.test(test_x, test_y)
                print('Epoch:%d, accuracy:%.4f' % (epoch + 1, accuracy))

    def test(self, test_x, test_y):
        '''
        测试函数
        :param test_x:
        :param text_y:
        :return:
        '''
        p = np.dot(test_x, self.w) + self.b
        pred_y = (p >= 0).astype(int)
        pred_y[pred_y == 0] = -1
        accuracy = (pred_y == test_y).sum() / test_x.shape[0]

        return accuracy


if __name__ == '__main__':

    digits = load_digits()
    features = digits.data
    # 0~4为类别05~9为类别1
    targets = (digits.target > 4).astype(int)
    targets[targets == 0] = -1

    shuffle_indices = np.random.permutation(features.shape[0])
    features = features[shuffle_indices]
    targets = targets[shuffle_indices]

    # 划分训练、测试集
    train_count = int(len(features)*0.8)
    train_x, train_y = features[:train_count], targets[:train_count]
    test_x, test_y = features[train_count:], targets[train_count:]

    percetron = Perceptron(train_x.shape[1])

    batch_size = 64
    epochs = 20

    percetron.traditional_train(train_x, train_y, batch_size, epochs, test_x, test_y)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值