主要参考书目《统计学习方法》第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(w⋅x+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,x≥0x<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| ∣∣w∣∣1∣w⋅x0+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)=−xi∈M∑yi(w⋅xi+b)
其中 M M M为误分类点的集合
为什么这里有一个-号?,因为认为 w ∗ x i + b > 0 , y i = − 1 w*x_i+b>0,y_i=-1 w∗xi+b>0,yi=−1其>0时,为+1,
比如这个图,认为超平面(分类的这根线)上面为+1,下面为-1 。 所以损失函数大于0的时候是分类正确的时候,小于或等于0则分类错误。
找到使损失函数最小的参数 w 、 b w、b 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 , 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,yi∈Y={−1,+1},i=1,2,...,N学习率(learning rate)为 η ( 0 < η ≤ 1 ) \eta(0<\eta \leq1) η(0<η≤1)
输入: w 、 b w、b w、b 感知机模型为 f ( x ) = s i g n ( w ⋅ x + b ) f(x)=sign(w·x+b) f(x)=sign(w⋅x+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(w⋅xi+b)≤0, // 小于等于0的时候说明分类错误,上面有提到
w ← w + η y i x i w \leftarrow w + \eta y_i x_i w←w+ηyixi
b ← b + η y i b \leftarrow b + \eta y_i b←b+ηyi
turn to (2) until 训练集中没有误分类点
此处《统计学习方法》是每一轮选择一个点进行随机梯度下降,但是记得在Andrew Ng的课上说是,没更新一次都要跑一边数据集,我当时的理解是用所有数据来更新一次权值。此处应该如何,还有待考察。
如何理解?
w ← w + η y i x i w \leftarrow w + \eta y_i x_i w←w+ηyixi
b ← b + η y i b \leftarrow b + \eta y_i b←b+ηyi
y i x i y_i x_i yixi y i y_i yi分别是损失函数对 w 、 b w、b w、b的偏导,沿着梯度方向迭代。
就比如 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)包括进去。
设数据集 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^opt⋅x^=wopt⋅x+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^opt⋅x^i)=yi(wopt⋅xi+bopt)≥γ
(2)令 R = max 1 ≤ i ≤ N ∣ ∣ x i ^ ∣ ∣ R=\max\limits_{1\leq i \leq N}||\hat{x_i}|| R=1≤i≤Nmax∣∣xi^∣∣,则感知机算法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
用C++写的,以后再也不用C++写机器学习的算法了。。
算个向量都得手算。。。
偷懒维度直接写的2,认真看应该不难看懂
#include
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;
}