《统计学习方法》第 2 章“感知机”学习笔记

感知机模型

感知机是《统计学习方法》的介绍的第 1 个算法,是神经网络与 SVM 的基础。html

研究思路

一、模型:二分类问题,数据点分为“ + 1 +1 ”类和“ 1 -1 ”类,“超平面”为所求;python

二、策略:损失函数最小化,肯定参数 w w b b git

三、算法:随机梯度降低法。github

策略:随机梯度降低

用普通的基于全部样本的梯度和的均值的批量梯度降低法(BGD)是行不通的,缘由在于咱们的损失函数里面有限定,只有误分类的 M 集合里面的样本才能参与损失函数的优化。因此咱们不能用最普通的批量梯度降低,只能采用随机梯度降低(SGD)或者小批量梯度降低(MBGD)。web

感知机学习的对偶形式

w w b b 表示成实例 x i x_i y i y_i 的线性组合。算法

一、 w 0 = 0 w_0 = \vec 0 b 0 = 0 b_0 = 0 ,则 w w b b 就能够表示成 x i x_i y i y_i 的线性组合;网络

二、实现技巧:向量化代替 for 循环。app

对于损失函数的理解

感知机学习固定分母为 1 1 。咱们研究能够发现,分子和分母都含有 w w ,当分子的 w w 扩大 N N 倍时,分母的 L 2 L_2 范数也会扩大 N N 倍。也就是说,分子和分母有固定的倍数关系。那么咱们能够固定分子或者分母为 1 1 ,而后求另外一个即分子本身或者分母的倒数的最小化做为损失函数,这样能够简化咱们的损失函数。在感知机模型中,咱们采用的是保留分子,即最终感知机模型的损失函数简化为:
J ( θ ) = x i M y ( i ) θ x ( i ) J(\theta) = - \sum\limits_{x_i \in M}y^{(i)}\theta \cdot x^{(i)}
个人理解:反正最终都会收敛,因此损失函数收敛的时候必定为 0 0 ,所以分母是多少都无所谓,这就是书上说的“不考虑 1 w \cfrac{1}{||w||} ”。机器学习

手写笔记

"感知机"模型手写笔记-1
"感知机"模型手写笔记-2
"感知机"模型手写笔记-3
"感知机"模型手写笔记-4

编码实现

代码还能够在 这里 查看。svg

Python 代码:

import numpy as np


class Perceptron:
    """ 感知机分类器:假设数据集是线性可分的 """

    def __init__(self, eta=0.01, n_iter=10):
        """ :param eta: 学习率,between 0.0 and 1.0,float :param n_iter: 最大迭代次数,int """
        self.eta = eta
        self.n_iter = n_iter

    def fit(self, X, y):
        # 同李航《统计学习方法》P29
        # "1" 表示偏置,即若是变量有 2 个,学习的权重就会有 3 个
        # 感知机就是学习这一组参数向量
        # 这里 y 只有两个取值,1 或者 -1
        # target - self.predict(xi),predict 函数返回 1 或者 -1
        # 若是相同,则上式 = 0,即分类正确的点对权重更新没有帮助
        self.w_ = np.zeros(1 + X.shape[1])

        # print(self.w_)
        self.errors_ = []

        for _ in range(self.n_iter):
            # print('迭代次数', _)
            # 表示这一轮分错的数据的个数
            errors = 0
            # 把全部的数据都看一遍
            for xi, target in zip(X, y):
                # 【注意】这个处理就包括了 target 和 self.predict 相等的状况,
                # 若是相等,下面两行 self.w_[1:] 和 self.w_[0] 都不会更新
                # 若是不等,至关于朝着父梯度方向走了一点点
                # 随机梯度降低法,每次只使用一个数据更新权重

                # print('实际',target,'预测',self.predict(xi))
                if target == self.predict(xi):
                    continue
                update = self.eta * target
                # w
                self.w_[1:] += update * xi
                # b
                self.w_[0] += update

                errors += int(update != 0.0)
            # 若是这一轮分类都正确,则感知机学习能够中止了
            if errors == 0:
                break
            self.errors_.append(errors)
        return self

    def net_input(self, X):
        """ 计算输出 :param X: :return: """
        # X 是 m * n 型
        # self.w_[1:] 是 n * 1 型,能够 dot
        # + self.w_[0] 发生了广播
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def predict(self, X):
        """ 预测类别变量,只返回 1 或者 -1 :param X: :return: """
        return np.where(self.net_input(X) >= 0.0, 1, -1)

示例

例1:鸢尾花数据集可视化

例2:感知机算法的 Python 实现

参考资料

[1] 李航. 统计学习方法(第 2 版)第 2 章“感知机”. 北京:清华大学出版社,2019.

[2] 刘建平. 感知机原理小结梯度降低(Gradient Descent)小结.

[3] 码农场. 感知机的学习.

[4] 知乎网友. 如何理解感知机学习算法的对偶形式?.

说明:对偶形式把累加变成了乘法运算,而且引入了 Gram 矩阵。

[5] Sebastian Raschka. Python 机器学习 第 2 章. 北京:机械工业出版社,2019.

(本节完)