最简单机器学习算法入门__感知机算法及其实现(附原始python实现以及sk_learn实现)

感知机(perceptron)是一种二类分类的线性分类模型,其输入为特征向量,输出为实例的分类,取“-1”“+1”两值。
简单的来说:感知机便是一个超平面,将训练数据进行线性划分。借助训练出来的超平面,输入测试数据,便可以得到预测结果
话不多说:
原理解释走起!
准备:
假设输入空间(特征空间)是X∈R(n),输出空间是Y={-1,+1}.
x对应于X,表示实例的特征向量,对应于输入空间的点,输出y∈Y。有输入到输出,对应于函数f(x)=sign(w · x+b) (这里的w·x,表示内积,就是∑wi*xi)
w通常叫做权值(weight),b 叫做偏置(bias),sign是符号函数
即sign(x)={+1,x>=0; -1,x<0}

感知机是一种线性分类模型,属于判别模型。感知机模型的假设空间是一系列超平面的集合,即函数的集合{f|f(x)=w·x+b}。

为什么集合,不是一个超平面就够了吗?
解释一下:感知机由于选取测试例子的顺序不同,会导致产生不同的超平面,即所有超平面都可以单独进行判断。

感知机的几何解释:线性方程:w·x+b=0
感知机模型
key words:

  1. 数据的线性可分性:
    如果存在某个超平面能够将训练数据集完全正确的划分到其两侧,则称该数据集为线性可分数据集(linearly separable data set)
  2. 输入空间上一点x0到达超平面S的距离为:|w·x0+b|/||w||,这里||w||是w的L2范数,即||w|| = [w·w] = ∑ (wi*wi)
  3. loss——function: 对于一个误分类(xi,yi)的例子总满足-yi*(w·xi+b) > 0。因为
    ① w·xi+b>0,yi = -1 ② w·xi+b<0, yi = +1,因此误分类点到超平面的总距离是 -∑yi(w·xi+b)/||w||。 不必考虑||w||, 就得到了损失函数 L(w,b) = -∑yi(w·xi+b) ,容易看出,这是一个关于w,b的可连续求导函数,这也是为什么要选择它做损失函数的原因之一,后面的梯度下降,它将大显神威
    关于Noviloff的证明:
    欢迎走进Dr.cyr的知乎专栏
    algorithm:
    感知机原始算法
    这个算法并没有太难理解的东西,主要是遍历和迭代的思想
    重点讲参数(w,b)的更新:
    还记得损失函数L(w,b) = -∑yi(w·xi+b) 吧,对于它,我们要分别去偏导,
    ▽w = -∑yixi, ▽b= -∑yi
    为什么要求导?
    这个和随机梯度下降的方法是相似的。求导的目的是为了不断减小损失函数的值,设置学习率,可以理解成调整函数,关于学习率,不能设置过大,过大会导致容易错过最优选项,过小则造成运算时间过久,且容易陷入局部最优。对于新手而言,这个学习率的调整,主要靠尝试。

原理讲的差不多了,接下来开始代码实现
首先是python初始化版本实现:

import numpy as np
import matplotlib.pyplot as plt
class MyPerceptron:
    def __init__(self):
        self.w = None
        self.b = 0
        self.l_rate = 1
    def draw(self,x,y,w,b):
        fig = plt.figure()
        ax = fig.add_subplot(111)#从左往右读,把画布分割成1行1列,并绘制1幅图,
        ax.set_title('perceptron_show')
        plt.xlabel('x(1)')
        plt.ylabel('x(2)')
        #绘制散点图
        for i in range(np.shape(x)[0]):
            if y[i] == -1: #如果取反例,则以”-“画点
                ax.scatter(x[i][0],x[i][1],c = 'r',marker = '_')
            else:#如果取正例,则以”+“画点
                ax.scatter(x[i][0],x[i][1],c = 'r',marker = '+')
        #绘制超平面,算法中超平面:w·x+b=0,因此可由x1_new得到x2_new,注意这里只是二维的超平面的演示
        x1_new = np.arange(0,10,1)
        x2_new = (-b - w[0]*x1_new)/w[1]
        plt.plot(x1_new,x2_new,"b-")
        plt.show()
    #核心算法代码来袭
    def fit(self,X_train,y_train):
        self.w = np.zeros(np.shape(X_train)[1])#shape[1]表示列数
        times = 0
        while times < np.shape(y_train)[0]:#shape[0]表示行数
            x = X_train[times]
            y = y_train[times]
            if y*(np.dot(self.w,x)+self.b) <= 0:
                self.w = self.w + self.l_rate * np.dot(y,x)
                self.b = self.b + self.l_rate * y
                times = 0
            else:
                times += 1
if __name__=="__main__":
    X_train = [[3,3],[4,3],[1,1]]
    Y_train = [1,1,-1]
    perceptron = MyPerceptron()
    perceptron.fit(X_train,Y_train)
    print(perceptron.w)
    print(perceptron.b)
    perceptron.draw(X_train,Y_train,perceptron.w,perceptron.b)

下面还有sk_learn 实现
值得一提,关于perceptron的内部参数

  1. penalty是正则化项,可选“l1”或者“l2”,“elasticnet”, l1使得特征更稀疏,l2使得权重更均匀。(模型选择的典型方法是正则化,正则化是结构风险最小化策略的实现,是在经验风险上加一个罚项(正则化项))
  2. alpha是正则化系数,太小则没有约束效果,太大则约束过度,导致欠拟合*(正则化项一般是模型复杂度的单调递增函数,模型越复杂,正则化值越大)*
  3. eta是学习率,本次实验由于w,b初始为0,所以eta并不会对最终结果有任何影响,因为学习率总是在最后被消去
  4. max_iter 是最多迭代次数
  5. tol是终止条件,一般是loss达到一定范围启动,当它启动时,可停止迭代
from sklearn.linear_model import Perceptron
if __name__=="__main__":
    X_train = [[3, 3], [4, 3], [1, 1]]
    Y_train = [1,1,-1]
    #perceptron内部参数的默认值如下所示
    perceptron = Perceptron(penalty= None,alpha=0.001,eta0=1,max_iter = 5,tol=None)
    #fit函数用于训练
    perceptron.fit(X_train,Y_train)
    #"coef_"指的是特征向量,"intercept_"指的是偏置
    print("the wight :",perceptron.coef_,"\nbias:",perceptron.intercept_)
    #测试模型的准确率score()
    res = perceptron.score(X_train,Y_train)
    #n_iter是指迭代次数
    print("the n_iter: ",perceptron.n_iter_)
    print("correct rate:{:.0%}".format(res))

写在最后:
感知机有两种算法,一种是原始算法,如上,一种是对偶算法
当训练数据集N过大时,选择原始算法,当维度比较高时,选择对偶算法,可减小运算开销。
关于sk_learn对于感知机模型的选择,应该是正则化项(alpha值)的设置,如果设置比较大,就会增大结构风险,导致选择比较简单的模型。感知机的模型复杂度和维度有关,维度大而且我们设置较小的alpha,就会选择对偶模型
后续如果有空,再来写一写对偶算法的实现(溜了溜了)

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值