机器学习笔记12——感知机模型原理以及python实现案例

分类和回归是机器学习的两大部分;接下来回顾一下分类模型。
对于不同的数据集,可选择的分类模型也是不同的。

【数据集的线性可分性】
给定一个数据集 T T T={ ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x N , y N ) {(x_1,y_1),(x_2,y_2),...,(x_N,y_N)} (x1,y1),(x2,y2),...,(xN,yN)},其中, x i ∈ R n x_i \in R^n xiRn, y i ∈ y_i\in yi{+1,-1},i=1,2,…,N,如果存在某个超平面S
w x + b = 0 wx+b=0 wx+b=0能够将数据集的正实例点和负实例点完全正确地划分到超平面的两侧,即对所有 y i = + 1 y_i=+1 yi=+1的实例i,有 w x i + b > 0 wx_i+b>0 wxi+b>0,对所有 y i = − 1 y_i=-1 yi=1的实例i,有 w x i + b < 0 wx_i+b<0 wxi+b<0,则称数据集T为线性可分数据集,否则,称数据集T线性不可分。

1、概述

感知机是由美国学者FrankRosenblatt 在1957 年提出来的,被看作为神经网络(深度学习)的起源的算法,同时也是支持向量机的基础。

严格讲,应该称为“人工神经元”或“朴素感知机”,但是因为很多基本的处理都是共通的,所以这里就简单地称为“感知机”。

感知机是二分类的线性模型,其输入是实例的特征向量,输出的是事例的类别,分别是+1和-1,属于判别模型

感知机要求数据集本身线性可分:感知机学习的目标是求得一个能够将训练数据集正实例点和负实例点完全正确分开的分离超平面。
在二维平面上,线性可分意味着能用一条直线将正、负样本分开;
在三维空间中,线性可分意味着能用一个平面将正、负样本分开;
在n维空间中,线性可分意味着能用n-1维超平面将正、负样本分开。
在这里插入图片描述

2、感知机模型

2.1 定义

设输入空间(特征空间)为 X ⊆ R n X\subseteq\R^n XRn;输出空间为Y={−1,+1}
输入 x ∈ X x\in X xX 为实例的特征向量 输出 y ∈ Y y\in Y yY 为实例的类别
由输入空间到输出空间的如下函数称为感知机
f ( x ) = s i g n ( w x + b ) = { 1 wx+b  ≥  0 − 1 wx+b<0 f(x)=sign(wx+b)= \begin{cases} 1& \text{wx+b $\geq$ 0}\\ -1& \text{wx+b<0} \end{cases} f(x)=sign(wx+b)={11wx+b  0wx+b<0

其中w和b为模型参数, w ∈ R n w\in\R^n wRn称为权值, b ∈ R b\in\R bR称为偏置。sign是符号函数。

感知机模型有直观的几何解释:线性方程wx+b=0 对应于分离超平面S,其中w为超平面S的法向量,b为S的截距。求解感知机,就是要解出w和b,得到能正确分离所有正负样本的超平面S。

在这里插入图片描述

2.2 损失函数

为找出正确的分离超平面、确定感知机模型参数,需要确定一个学习策略。在监督学习中,使用某种策略即是选用相应的损失函数。

损失函数的一个自然选择是误分类点的总数。但是,这样的损失函数不是参数 w , b w,b w,b的连续可导函数,不易优化。见下图,当超平面在空间中由S1连续变化至S3时,相应的法向量w也连续变化,而误分类点数量则是不连续的。

在这里插入图片描述
为此感知机采用的损失函数为:误分类点到超平面S的总距离,该函数对w和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 \R^n xiRn, y i ∈ y_i\in yi Y={-1,+1},i=1,2,…,N;M为误分类点的集合。
感知机学习的损失函数为
L ( w , b ) = − ∑ x i ∈ M y i ( w x i + b ) L(w,b)=-\sum_{x_i\in M}y_i(wx_i+b) L(w,b)=xiMyi(wxi+b)

易知损失函数是非负的,误分类点越少,误分类点离超平面越近,损失函数值就越小。如果没有误分类点,则损失函数值时0。感知机学习的策略是在假设空间中选取使损失函数取值最小的模型参数。

推导:

  • 单个点 x i x_i xi到超平面S的距离为
    1 ∥ w ∥ ∣ w x i + b ∣ \frac{1}{\Vert w \Vert}\vert wx_i+b \vert w1wxi+b
    其中, ∥ w ∥ = w 1 2 + w 2 2 + . . . + w n 2 \Vert w \Vert=\sqrt{w_1^2+w_2^2+...+w_n^2} w=w12+w22+...+wn2
  • L p L_p Lp范数:
    ∥ w ∥ p = ( ∣ w 1 ∣ p + ∣ w 2 ∣ p + . . . + ∣ w n ∣ p ) 1 p \Vert w \Vert_p=(\vert w_1 \vert^p+\vert w_2 \vert^p+...+\vert w_n \vert^p)^{\frac{1}{p}} wp=(w1p+w2p+...+wnp)p1
  • 对于误分类点数据 ( x i , y i ) (x_i,y_i) (xi,yi),有 − y i ( w x i + b ) > 0 -y_i(wx_i+b)>0 yi(wxi+b)>0
    ,因为 y i y_i yi w x i + b wx_i+b wxi+b 异号.
  • 误分类点到超平面S的距离为
    − y i ( w x i + b ) ∥ w ∥ -\frac{y_i( wx_i+b)}{\Vert w \Vert} wyi(wxi+b)
    所有误分类点到超平面S的总距离为
    L ( w , b ) = − 1 ∥ w ∥ ∑ x i ∈ M y i ( w x i + b ) L(w,b)=-\frac{1}{\Vert w\Vert}\sum_{x_i\in M}y_i(wx_i+b) L(w,b)=w1xiMyi(wxi+b)
    1 ∥ w ∥ \frac{1}{\Vert w\Vert} w1为常数,不影响,去掉即为损失函数。

3、感知机算法

  • 目标: 感知机学习算法的原始形式是求解最优化问题
    m i n w , b L ( w , b ) = − ∑ x i ∈ M y i ( w x i + b ) {min}_{w,b}L(w,b)=-\sum_{x_i\in M}y_i(wx_i+b) minw,bL(w,b)=xiMyi(wxi+b)

    其中M为误分类点的集合

  • 优化方法:随机梯度下降法

3.1 原始形式

  • 算法过程:

    • 输入:线性可分的训练数据集 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 x_i\in X=\R^n xiX=Rn, y i ∈ Y = { − 1 , + 1 } y_i\in Y=\{-1,+1\} yiY={1,+1},i=1,2,…,N ;学习率 η ( 0 ≤ η ≤ 1 \eta(0\leq\eta\leq1 η0η1;

    • 输出:参数w,b;感知机模型 f ( x ) = s i g n ( w x + b ) f(x)=sign(wx+b) f(x)=sign(wx+b)
      (1)随机选取初值 w 0 , b 0 w_0,b_0 w0,b0,一般均选为0;
      (2)在训练集中选取数据 ( x i , y i ) (x_i,y_i) (xi,yi)
      (3)如果 y i ( w x i + b ) ≤ 0 y_i(wx_i+b)\leq0 yi(wxi+b)0即此点被误分类。

      w ← w + η y i x i w\leftarrow w+\eta y_ix_i ww+ηyixi,
      b ← b + η y i b\leftarrow b+\eta y_i bb+ηyi

      (4)转至(2),直至训练集中没有误分类点。

    每次根据 ( x i , y i ) (x_i,y_i) (xi,yi) 调整 w , b w,b w,b时,分离超平面将向该误分类点移动,以减少该误分类点与超平面的距离,越过该误分类点使其正确分类。

【代码实现】

class Perceptron_Model:
    def __init__(self):
        #len(data[0])表示数据集的列数n,特征向量个数通常为n-1,因此参数向量个数为n-1
        #初始化参数为0
        self.w = np.zeros(len(data[0]) - 1, dtype=np.float32)
        #初始化截距b为0
        self.b = 0
        #学习率
        self.l_rate = 0.1
        # self.data = data

    def sign(self, x, w, b):
        y = np.dot(x, w) + b
        return y

    # 随机梯度下降法
    def fit(self, X_train, y_train):
        is_wrong = False
        while not is_wrong:
            wrong_count = 0
            for d in range(len(X_train)):
                X = X_train[d]
                y = y_train[d]
                if y * self.sign(X, self.w, self.b) <= 0:
                    self.w = self.w + self.l_rate * np.dot(y, X)
                    self.b = self.b + self.l_rate * y
                    wrong_count += 1
            if wrong_count == 0:
                is_wrong = True
        return self.w,self.b

案例:
数据集:鸢尾花数据集共有150个样本,共有三个类别,比列为1:1:1;因此我们参用前一百个数据(只有两种类别)来建立感知机模型。

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
%matplotlib inline
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target#将目标转换为标签
df.columns = [
    'sepal length', 'sepal width', 'petal length', 'petal width', 'label'
]
#查看每个标签的数量
df.label.value_counts()
data = np.array(df.iloc[:100, [0, 1, -1]])#取前100个样本
X, y = data[:,:-1], data[:,-1]
perceptron =Perceptron_Model()
perceptron.fit(X, y)

画图:

x_points = np.linspace(4, 7, 10)
y_ = -(perceptron.w[0] * x_points + perceptron.b) / perceptron.w[1]
plt.plot(x_points, y_)

plt.plot(data[:50, 0], data[:50, 1], 'bo', color='blue', label='0')
plt.plot(data[50:100, 0], data[50:100, 1], 'bo', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()

在这里插入图片描述
scikit-learn模块实现上述例子

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
%matplotlib inline
import sklearn
from sklearn.linear_model import Perceptron#导入感知机
#获取数据:特征向量X,目标向量y
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target
data = np.array(df.iloc[:100, [0, 1, -1]])
X, y = data[:,:-1], data[:,-1]

clf = Perceptron(fit_intercept=True, 
                 max_iter=1000, 
                 shuffle=True)
clf.fit(X, y)
print(clf.coef_)#获取系数w
print(clf.intercept_)#截距b
#画图
# 画布大小
plt.figure(figsize=(10,10))

# 中文标题
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.title('鸢尾花线性数据示例')

plt.scatter(data[:50, 0], data[:50, 1], c='b', label='Iris-setosa',)
plt.scatter(data[50:100, 0], data[50:100, 1], c='orange', label='Iris-versicolor')

# 画感知机的线
x_ponits = np.arange(4, 8)
y_ = -(clf.coef_[0][0]*x_ponits + clf.intercept_)/clf.coef_[0][1]
plt.plot(x_ponits, y_)

# 其他部分
plt.legend()  # 显示图例
plt.grid(False)  # 不显示网格
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()

3.2 对偶形式

对偶形式的基本思想是,将w和b表示为实例 x i x_i xi和标记 y i y_i yi的线性组合的形式,通过求解其系数而求得参数w和b。
在这里插入图片描述

在这里插入图片描述
简而言之,感知机的对偶形式就是把对 w , b w,b w,b的学习变成了对 α , b α,b α,b的学习,原始形式中, w w w在每一轮迭代错分时都需要更新,而采用对偶形式时,对于某一点 ( x i , y i ) (x_i,y_i) (xi,yi)发生错分时,我们只需要更新其对应的 α i α_i αi即可。

【代码实现】

from __future__ import division
import random
import numpy as np
import matplotlib.pyplot as plt  


def sign(v):
    if v>=0:
        return 1
    else:
        return -1

def train(train_num,train_datas,lr):
    w=0.0
    b=0
    datas_len = len(train_datas)
    alpha = [0 for i in range(datas_len)]
    train_array = np.array(train_datas)
    gram = np.matmul(train_array[:,0:-1] , train_array[:,0:-1].T)
    for idx in range(train_num):
        tmp=0
        i = random.randint(0,datas_len-1)
        yi=train_array[i,-1]
        for j in range(datas_len):
            tmp+=alpha[j]*train_array[j,-1]*gram[i,j]
        tmp+=b
        if(yi*tmp<=0):
            alpha[i]=alpha[i]+lr
            b=b+lr*yi
    for i in range(datas_len):
        w+=alpha[i]*train_array[i,0:-1]*train_array[i,-1]
    return w,b,alpha,gram

def plot_points(train_datas,w,b):
    plt.figure()
    x1 = np.linspace(0, 8, 100)
    x2 = (-b-w[0]*x1)/(w[1]+1e-10)#超平面$wx+b=0$
    plt.plot(x1, x2, color='r', label='y1 data')
    datas_len=len(train_datas)
    for i in range(datas_len):
        if(train_datas[i][-1]==1):
            plt.scatter(train_datas[i][0],train_datas[i][1],s=50)  
        else:
            plt.scatter(train_datas[i][0],train_datas[i][1],marker='x',s=50)  
    plt.show()

if __name__=='__main__':
    train_data1 = [[1, 3, 1], [2, 2, 1], [3, 8, 1], [2, 6, 1]]  # 正样本
    train_data2 = [[2, 1, -1], [4, 1, -1], [6, 2, -1], [7, 3, -1]]  # 负样本
    train_datas = train_data1 + train_data2  # 样本集
    w,b,alpha,gram=train(train_num=500,train_datas=train_datas,lr=0.01)
    plot_points(train_datas,w,b)

4、感知机与其他算法

感知机模型简单、易学习,是基本的机器学习模型,很多机器学习模型是在感知机模型的基础上变化扩展而得到的。
感知机模型由于其简单,在应用时也有一定的局限,主要体现在以下几点。

  • 感知机只能处理线性可分的数据集,线性不可分的数据集会引起分离超平面的震荡而无法收敛。
  • 感知机是误分类驱动的模型,模型的解不唯一。离群点对结果影响很大。
  • 感知机的判别模型由符号函数给出,无法表示更复杂的非线性映射。
    为解决以上的局限性,其他算法从不同方向对感知机模型进行了扩展。

感知机与支持向量机

  • 相同点
    感知机与支持向量机都是求解能正确划分样例的超平面

  • 不同点
    感知机是误分类驱动的,其损失函数来源于误分类点到分离超平面的距离之和。数据集线性可分时,能正确划分样例的超平面有无穷多个。
    支持向量机不仅要求正确划分正负样例,还要求正负样例间隔最大,在最大间隔约束下,划分超平面(的法向量)有唯一解。

在这里插入图片描述
感知机优化目标:
m i n w , b L ( w , b ) = − ∑ x i ∈ M y i ( w x i + b ) {min}_{w,b}L(w,b)=-\sum_{x_i\in M}y_i(wx_i+b) minw,bL(w,b)=xiMyi(wxi+b)
支持向量机优化目标:

m a x w , b d max_{w,b}d maxw,bd


感知机与神经网络

感知机(Perceptron) 仅由两层神经元组成,如下图:

在这里插入图片描述
两层是指输入层和输出层,但 只有输出层是M-P神经元,也即 只有一层功能神经元(functional neuron)。

输入层只负责把每一个样本的各个属性传递给输出层(输入层的神经元数量等于样本的属性数目),不进行函数处理。其实说白了这个模型跟逻辑回归是一样的,不过按我的理解就是感知机的输出层可以有多个神经元,产生多个输出。而且线性模型中偏置项是和属性一起加权求和的,但神经网络中则是求属性加权和和预测的差。

感知机能容易的实现逻辑与、或、非运算,但不能解决异或(XOR)这样简单的非线性可分问题。【XOR:仅当x1 或x2 中的一方为1 时,才会输出1;“异或”是拒绝其他的意思。】要解决非线性可分问题,需考虑使用多层功能神经元。

当把感知机看成单个神经元时,该神经元的堆叠就形成了神经网络。最常用的前馈神经网络就是感知机分层堆叠而形成的,也叫多层感知机MLP.感知机的激活函数是阶跃函数(符号函数)

f ( x ) = s i g n ( x ) = { 1 x  ≥  0 − 1 x<0 f(x)=sign(x)= \begin{cases} 1& \text{x $\geq$ 0}\\ -1& \text{x<0} \end{cases} f(x)=sign(x)={11 0x<0

在这里插入图片描述
使用多层的功能神经元可以解决线性不可分问题,比方说两层(功能神经元)的感知机就可以解决异或问题(在二维平面中需要使用两条直线才能分隔开)。在输入层和输出层之间的层称为隐层或者 隐含层(hidden layer),隐含层的神经元也是功能神经元。

上图展示的最为常见的多层神经网络——多层前馈神经网络(multi-layer feedforward neural networks),它有以下特点:

  • 每层神经元与下一层神经元 全互连
  • 神经元之间 不存在同层连接
  • 神经元之间 不存在跨层连接

参考资料:
李航《统计学习方法》
深度学习
西瓜书

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值