《统计学习方法》——感知机

引言

本文主要介绍了感知机引入,并且附有一些实例代码和恰当的图片,让大家更容易理解。

首先介绍下什么是感知机。

感知机

感知机是二类分类的线性模型,其输入为实例的特征向量,输出为实例的类别,类别取+1,-1二值。

感知机对应于输入空间(特征空间)中将实例划分为正负两类的分离超平面,属于判别模型。

感知机分为原始形式和对偶形式。

感知机模型

假设输入空间时 X R n X \subseteq R^n ,输出空间时 Y = { + 1 , 1 } Y = \{+1,-1\} 。由输入空间到输出空间的如下函数:

f ( x ) = s i g n ( w x + b ) f(x) = sign(w \cdot x + b)

其中 w R n w \in R^n (属于 n n 维实数集)叫权值(weight,或叫权重,通常是个向量), b R b \in R ,叫偏置(或偏差)。
w x w \cdot x 表示这两个向量的内积。 s i g n sign 是符号函数,即

{ + 1 , x 0 1 , x < 0 \left\{ \begin{array}{c} +1, x \geq 0 \\ -1, x < 0 \end{array} \right.

感知机是一种线性分类模型,其假设空间时定义在特征空间中的所有线性分类模型(或线性分类器),即函数集合 { f f ( x ) = w x + b } \{f|f(x) = w \cdot x + b\}

它的几何解释是线性方程 w x + b = 0 w \cdot x + b = 0 ,该方程对应于特征空间 R n R^n 的一个超平面 S S w w 是超平面的法向量, b b 是超平面的截距。

超平面是n维欧氏空间中余维度等于一的线性子空间,也就是必须是(n-1)维度。这是平面中的直线、空间中的平面之推广(n大于3才被称为“超”平面)。

该超平面将特征空间划分为两个部分。位于两部分的点分贝被分为正、负两类。因此,超平面 S S 称为分离超平面

在这里插入图片描述

感知机学习的训练数据集(实例的特征向量及类别)是这样的:

T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , , ( x N , y n ) } T = \{(x_1,y_1),(x_2,y_2),\cdots,(x_N,y_n)\}

感知机学习策略

给定上面的数据集 T T ,如果存在某个超平面 S : w x + b = 0 S : w \cdot x +b =0 能将数据集的正实例点和负实例点完全正确地划分到超平面的两侧,即对所有 y i = + 1 y_i=+1 的实例 i i ,都有 w x i + b > 0 w \cdot x_i + b >0 ,对所有 y i = 1 y_i= -1 的实例 i i w x i + b < 0 w \cdot x_i + b <0 ,则称数据集 T T 线性可分数据集;否则,线性不可分。

假设训练数据集是线性可分的,感知机学习的目标是求得一个能够将训练集正实例点和负实例点完全正确分开的超平面。为了找出这样的超平面,即确定感知机模型参数 w , b w,b ,需要确定一个学习策略,即定义损失函数并最小化它。

损失函数一般是计算所有误分类点到超平面 S S 的总距离。为此,首先写出输入空间中任一点 x 0 x_0 到超平面的距离:

1 w w x 0 + b \frac{1}{||w||}|w \cdot x_0 + b|

这里 w ||w|| w w L 2 L_2 范数,或者说是模。

我们知道点 ( x , y ) (x,y) 到直线 A x + b y + C = 0 Ax+by+C =0 的距离为

A x + b y + C A 2 + B 2 \frac{Ax+by+C}{\sqrt{A^2+B^2}}

可以看到它的分母是 A 2 + B 2 A^2 +B^2 的开根号,也就是说,分母和截距无关。

拓展到 n n 维空间, w x + b = 0 w \cdot x + b = 0 ,得

w x + b w \frac{|w\cdot x +b|}{||w||}

w = w 1 2 + w 2 2 + + w n 2 ||w|| = \sqrt{w_1^2 + w_2^2 + \cdots + w_n^2} 因为距离是正的,所以取绝对值就得到了上面的式子。

对于误分类的数据 ( x i , y i ) (x_i,y_i) 来说,有 y i ( w x i + b ) > 0 -y_i(w \cdot x_i + b) > 0 。因为当 w x i + b > 0 w \cdot x_i + b >0 时, y i = 1 y_i = -1 (注意是误分类点);而当 w x i + b < 0 w \cdot x_i + b < 0 时, y i = + 1 y_i = +1 。它们乘起来在乘以 1 -1 一定是大于 0 0 的。

因此,我们把上面得到的距离公式乘以 y i -y_i 就得到了误分类点到超平面的距离公式:

1 w y i w x i + b -\frac{1}{||w||}y_i|w \cdot x_i + b|

因为 y y 的取值无非就是 + 1 , 1 +1,-1 ,然后上面又说了这个式子是一定大于0的,因此这个公式是成立的。

这样,假设超平面 S S 的误分类点集合为 M M ,那么所有误分类点到超平面 S S 的总距离为:

1 w x i M y i ( w x i + b ) -\frac{1}{||w||} \sum_{x_i \in M}y_i(w \cdot x_i + b)

如果不考虑 1 w \frac{1}{||w||} 的话,就得到了感知机 s i g n ( w x + b ) sign(w \cdot x +b) 学习的损失函数:

L ( w , b ) = x i M y i ( w x i + b ) L(w,b) = -\sum_{x_i \in M}y_i(w \cdot x_i + b)

注意, M M 是误分类点的集合,如果是正确分类的点,其损失直接为0,就不需要参与计算。

感知机学习的策略是在假设空间中选取使损失函数最小的模型参数 w , b w,b

感知机学习算法

感知机学习算法是误分类驱动的,采用随机梯度下降法。首先,任取一个超平面 w 0 , b 0 w_0,b_0 ,然后用梯度下降法不断地极小化目标函数 L ( w , b ) = x i M y i ( w x i + b ) L(w,b) = -\sum_{x_i \in M}y_i(w \cdot x_i + b) 。极小化过程一次随机选取一个误分类点使其梯度下降。

损失函数 L ( w , b ) L(w,b) 的梯度由:

w L ( w , b ) = x i M y i x i b L ( w , b ) = x i M y i \nabla_w L(w,b) = - \sum_{x_i \in M} y_ix_i \\ \nabla_b L(w,b) = - \sum_{x_i \in M} y_i

简单的证明一下:

L ( w , b ) w = ( x i M y i ( w x i + b ) ) w = ( x i M y i ( w x i ) ) w + ( x i M y i b ) w = x i M y i x i \begin{aligned} \frac{\partial L(w,b)}{\partial w} &= \frac{ \partial ( -\sum_{x_i \in M}y_i(w \cdot x_i + b))}{\partial w} \\ &= \frac{ \partial ( -\sum_{x_i \in M}y_i(w \cdot x_i ))}{\partial w} + \frac{ \partial ( -\sum_{x_i \in M}y_ib)}{\partial w} \\ &=- \sum_{x_i \in M} y_ix_i \end{aligned}

因为 y i , b y_i,b 是与 w w 无关的,所以微分就是 0 0 ,对 b b 求微分也同理。

随机选一个误分类点 ( x i , y i ) (x_i,y_i) w , b w,b 进行更新:

w w + η y i x i b b + η y i w \leftarrow w + \eta y_ix_i \\ b \leftarrow b + \eta y_i \\

其中 η \eta 是学习率。

学习算法原始形式为:

  1. 选取初值 w 0 , b 0 w_0,b_0 ;
  2. 在训练数据集中选取数据 ( x i , y i ) (x_i,y_i) ;
  3. 如果 y i ( w x i + b ) 0 y_i(w \cdot x_i + b) \leq 0 ,通过 w w + η y i x i , b b + η y i w \leftarrow w + \eta y_ix_i,b \leftarrow b + \eta y_i 更新:
  4. 跳转置2,直到训练集中没有误分类点

直观上的解释是:当一个实例点被误分类,也就是位于分离超平面的错误一侧时,调整 w , b w,b 的值,使分离超平面向该实例点的一侧移动,以减少误分类点与超平面的距离,直到超平面越过该误分类点使其被正确分类。

我们用iris数据集为例,用sepal length,sepal width作为特征。

# load data
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

# 加载数据
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']

plt.scatter(df[:50]['sepal length'], df[:50]['sepal width'], label='0')
plt.scatter(df[50:100]['sepal length'], df[50:100]['sepal width'], label='1')

plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()

只取里面的类别0和1,将它们的散点图画出来:
在这里插入图片描述

data = np.array(df.iloc[:100, [0, 1, -1]])#将这100数据转成np数组,最后一列是类别
x, y = data[:,:-1], data[:,-1] # 抽出两个特征放入x,抽出类别放入y
y = np.array([1 if i == 1 else -1 for i in y]) # 把类别  0 转换成 -1

class Model:
    def __init__(self):
    	# 选取初值w,b
        self.w = np.ones(len(data[0])-1, dtype=np.float32)
        self.b = 0
        self.l_rate = 0.1
    
    def sign(self, x, w, b):
        y = np.dot(x, w) + b # f(x)
        return y
    
    # 随机梯度下降法
    def fit(self, x_train, y_train):
        is_done = False
        while not is_done :
            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:
                	# 梯度下降更新w和b
                    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_done = True

模型写好了,接下来画出预测的结果:

perceptron = Model()
perceptron.fit(x, y)

x_points = np.linspace(4, 7,10) # 在4和7之间等距离生成10个点
y_ = -(perceptron.w[0]*x_points + perceptron.b)/perceptron.w[1] # w₀x₀ + w₁y + b = 0 => y = -(w₀x₀ + b)/w₁ 这里把x₁用y来代替,因为要画到二维坐标系上,就是两个维度,另一个当成y
plt.plot(x_points, y_)

plt.plot(data[:50, 0], data[:50, 1], 'bo', color='blue', label='-1')
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()

在这里插入图片描述

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

对偶形式的基本想法是,将 w w b b 表示为实例 x i x_i 和标记 y i y_i 的线性组合的形式,通过求解其系数而求得 w w b b 。其实就是将当前的 w w 用之前的累计更新来表示。

不失一般性,设初始值 w 0 , b 0 w_0,b_0 均为 0 0 ,对误分类点 ( x i , y i ) (x_i,y_i) 通过
w w + η y i x i b b + η y i w \leftarrow w + \eta y_ix_i \\ b \leftarrow b + \eta y_i

如果某个误分类点 ( x i , y i ) (x_i,y_i) 被多次选中,那么它对当前的参数就进行了 n n 次更新,就会使 w , b w,b 改变如下:

Δ w = n η y i x i Δ b = n η y i \Delta w = n\eta y_ix_i \\ \Delta b = n\eta y_i

对偶形式的参数更新就是更新某个误分类点参与更新的次数,就是更新这个 n n 。更新过程中被选中的每个误分类点都可以如上表示,将它们全部加起来,就可以表示由初始的 w 0 , b 0 w_0,b_0 到当前的 w , b w,b 之间的总变化,则 w w 的表示形式如下:

w = w 0 + n 1 η y 1 x 1 + n 2 η y 2 x 2 + + n i η y i x i w = w_0 + n_1\eta y_1x_1 + n_2\eta y_2x_2 + \cdots + n_i\eta y_ix_i

这个式子包含了训练集所有的点,如果某个点未被选中,则 n = 0 n=0 。我们把上式中的 n i η n_i\eta 改写为 α i \alpha_i ,而上面说了,初始值 w 0 , b 0 w_0,b_0 均为 0 0 ,所以可以写成:

w = i = 1 N α i y i x i w = \sum_{i=1}^N \alpha_iy_ix_i

因此上面的感知机模型可以写成下面的式子:

f ( x ) = s i g n ( j = 1 N α j y j x j x + b ) f(x) = sign (\sum_{j=1}^N\alpha_jy_jx_j \cdot x + b)

对偶形式的算法如下:

  1. 设置初值 α 0 , b 0 \alpha \leftarrow 0,b \leftarrow 0 ;
  2. 在训练集中选取数据 ( x i , y i ) (x_i,y_i) ;
  3. 如果 y i ( j = 1 N α j y j x j x i + b ) 0 y_i(\sum_{j=1}^N\alpha_jy_jx_j \cdot x_i + b) \leq 0 , 则 α i α i + η , b b + η y i \alpha _i \leftarrow \alpha_i + \eta,b \leftarrow b + \eta y_i ;
  4. 跳转到2直到没有误分类数据

b b 的更新方式和原始形式一样,这没问题。我们重点来看下 α \alpha 的更新方式。

α \alpha 表示的是 n i η n_i\eta ,当我们用上面的方式进行更新时,其实就是使 n i n_i 增加了 1 1 ,相当于
i = 1 N α i y i x i \sum_{i=1}^N \alpha_iy_ix_i 增加了 η y i x i \eta y_ix_i ,也就是:

i = 1 N α i y i x i + η y i x i \sum_{i=1}^N \alpha_iy_ix_i + \eta y_ix_i

再结合 w = i = 1 N α i y i x i w = \sum_{i=1}^N \alpha_iy_ix_i

这里的更新就等价于 w w + η y i x i w \leftarrow w + \eta y_ix_i

参考

  1. 李航.统计学习方法第二版
发布了148 篇原创文章 · 获赞 57 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/yjw123456/article/details/104735731
今日推荐