【机器学习笔记】《统计学习方法》第二章 感知机+随机梯度下降法

主要参考书目《统计学习方法》第2版,清华大学出版社
参考书目 Machine Learning in Action, Peter Harrington
用于考研复试笔记,所以写的很简洁,自己能看懂就行。有学习需求请绕道,参考吴恩达机器学习或以上书籍,讲得比大多数博客好。

概念

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

f ( x ) = s i g n ( w ⋅ x + b ) f(x)=sign(w·x+b) f(x)=sign(wx+b)
其中, s i g n ( x ) = { + 1 , x ≥ 0 − 1 , x < 0 sign(x)= \left\{ \begin{aligned} +1, && x \ge 0\\ -1, && x < 0 \end{aligned} \right. sign(x)={ +1,1,x0x<0

对于一个特征空间 R n R^n Rn中的一个超平面 S S S,其中 w w w是超平面的法向量, b b b是超平面的截距
S S S称为分离超平面(separating hyperplane)

线性可分数据集(linearly separable data set)
被划分在超平面的两侧。

原理

感知机的学习策略

首先写出输入空间 R n R^n Rn中任一点 x 0 x_0 x0到超平面 S S S的距离
1 ∣ ∣ w ∣ ∣ ∣ w ⋅ x 0 + b ∣ \frac{1}{||w||}|w·x_0+b| w1wx0+b

书上扯淡说了个二范数,就是距离公式而已,拓展到n维空间

不考虑 ∣ ∣ w ∣ ∣ ||w|| w感知机学习的损失函数
L ( x , b ) = − ∑ x i ∈ M y i ( w ⋅ x i + b ) L(x,b)=-\sum\limits_{x_i \in M}y_i(w·x_i+b) L(x,b)=xiMyi(wxi+b)
其中 M M M为误分类点的集合

为什么这里有一个-号?,因为认为 w ∗ x i + b > 0 , y i = − 1 w*x_i+b>0,y_i=-1 wxi+b>0yi=1其>0时,为+1,
比如这个图,认为超平面(分类的这根线)上面为+1,下面为-1 。 所以损失函数大于0的时候是分类正确的时候,小于或等于0则分类错误。
在这里插入图片描述
找到使损失函数最小的参数 w 、 b w、b wb就是感知机模型。

随机梯度下降法(stochastic gradient descent)

输入:训练集数据集 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 , y i ∈ Y = { − 1 , + 1 } , i = 1 , 2 , . . . , N x_i \in \chi=R^n,y_i \in Y=\{-1,+1\}, i = 1,2,...,N xiχ=Rn,yiY={ 1,+1},i=1,2,...,N学习率(learning rate)为 η ( 0 < η ≤ 1 ) \eta(0<\eta \leq1) η(0<η1)
输入: w 、 b w、b wb 感知机模型为 f ( x ) = s i g n ( w ⋅ x + b ) f(x)=sign(w·x+b) f(x)=sign(wx+b)
(1)选取初值为 w 0 , b 0 w_0,b_0 w0,b0
(2)在训练集中选取数据 ( x i , y i ) (x_i,y_i) (xi,yi)
(3)如果 y i ( w ⋅ x i + b ) ≤ 0 y_i(w·x_i+b) \leq 0 yi(wxi+b)0, // 小于等于0的时候说明分类错误,上面有提到
w ← w + η y i x i w \leftarrow w + \eta y_i x_i ww+ηyixi
b ← b + η y i b \leftarrow b + \eta y_i bb+ηyi
turn to (2) until 训练集中没有误分类点

此处《统计学习方法》是每一轮选择一个点进行随机梯度下降,但是记得在Andrew Ng的课上说是,没更新一次都要跑一边数据集,我当时的理解是用所有数据来更新一次权值。此处应该如何,还有待考察。

如何理解?
w ← w + η y i x i w \leftarrow w + \eta y_i x_i ww+ηyixi
b ← b + η y i b \leftarrow b + \eta y_i bb+ηyi
y i x i y_i x_i yixi y i y_i yi分别是损失函数对 w 、 b w、b wb的偏导,沿着梯度方向迭代。
就比如 b b b,如果 y i > 0 ( y i = 1 ) y_i>0 (y_i=1) yi>0(yi=1)认为是错的,说明这个点在超平面上方, b b b更新后会变大,联想 y = a x + b y=ax+b y=ax+b,那超平面就会稍微往上移动,试图把 ( x i , y i ) (x_i,y_i) (xi,yi)包括进去。

定理2.1(Novikoff)

设数据集 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 , y i ∈ { − 1 , + 1 } , i = 1 , 2 , . . . , N x_i \in \chi = R^n, y_i \in \{-1,+1\},i=1,2,...,N xiχ=Rn,yi{ 1,+1},i=1,2,...,N,则
(1)存在满足条件 ∣ ∣ w ^ o p t ∣ ∣ = 1 ||\hat{w}_{opt}||=1 w^opt=1的超平面 w ^ o p t ⋅ x ^ = w o p t ⋅ x + b o p t = 0 \hat{w}_{opt}·\hat{x}=w_{opt}·x+b_{opt}=0 w^optx^=woptx+bopt=0将训练集完全分开;且存在 γ > 0 \gamma>0 γ>0,对所有 i = 1 , 2 , . . . , N i=1,2,...,N i=1,2,...,N
y i ( w ^ o p t ⋅ x ^ i ) = y i ( w o p t ⋅ x i + b o p t ) ≥ γ y_i(\hat{w}_{opt}·\hat{x}_i)=y_i(w_{opt}·x_i+b_{opt})\geq\gamma yi(w^optx^i)=yi(woptxi+bopt)γ
(2)令 R = max ⁡ 1 ≤ i ≤ N ∣ ∣ x i ^ ∣ ∣ R=\max\limits_{1\leq i \leq N}||\hat{x_i}|| R=1iNmaxxi^,则感知机算法2.1在训练数据集上的误分类次数k满足不等式 k ≤ ( R γ ) 2 k\leq(\frac{R}{\gamma})^2 k(γR)2

扯了一堆,无非就是想说
(1)如果数据集是可分这一事实的前提下,那么他一定可分,如果可分,那么一定能找到这样的超平面
(2)误分类次数是有上界的,随机梯度下降一定收敛。

关于感知机的对偶形式,请绕道
https://www.zhihu.com/question/26526858/answer/131591887
在这里插入图片描述

课后习题

21.为什么感知机不能表示亦或。
在这里插入图片描述

代码

用C++写的,以后再也不用C++写机器学习的算法了。。
算个向量都得手算。。。

偷懒维度直接写的2,认真看应该不难看懂

#include <iostream>
using namespace std;
const double eta = 1;
const double eps = 1e-5;
struct point {
    
    
    double x[3];
    int y; 
};

int cnt = 1;
void pcpt_train(point* p, double* w, double &b, int n) {
    
    
    for (int i = 1; i <= n; i++) {
    
    
        double sum = 0;
        for (int j = 1; j <= 2; j++)
            sum += w[j] * p[i].x[j];
        sum += b;
        
        if (p[i].y * sum < eps) {
    
    
            for (int j = 1; j <= 2; j++)
                w[j] += p[i].y * p[i].x[j] * eta;
            b += p[i].y * eta;
            cout << cnt++ << "\t\tx" << i << "\t\t(" << w[1] << " " << w[2] << ")\t" << b << "\t" << w[1] << "x(1)+" << w[2] << "x(2)+" << b << endl;
            pcpt_train(p, w, b, n);
            return;
        }
    }
}

int main() {
    
    
    point p[10];
    p[1].y = p[2].y = 1, p[3].y = -1;
    p[1].x[1] = p[1].x[2] = 3;
    p[2].x[1] = 4, p[2].x[2] = 3;
    p[3].x[1] = 1, p[3].x[2] = 1;

    double w[10] = {
    
     0 }; double b = 0;
    int n = 3;

    cout << "迭代次数\t误分类点数\tw\tb\tw*x+b" << endl;
    pcpt_train(p, w, b, n);

    cout << w[1] << " " << w[2] << " " << b << endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43269437/article/details/112853608