笔记参考及引用了部分机器学习基石内容及 https://zhuanlan.zhihu.com/p/25358695
近期在看林轩田的机器学习基石,第一个模型就是这个最基础的PLA算法 (Perceptron Learning Algorithm)。虽然视频中已经讲的比较详细了,但是对于公式推理的许多细节还是一脸懵。反反复复看了几遍,查了资料,才有比较清晰的理解。所以整理了一下,并对里面一些卡住我的细节作一些补充。
1.补充笔记(机器学习流程图)
这里f表示最理想的方案。x为特征值,y为结果值。
我们认为训练集D是由理想方案f生成的。g为我们求解的用来预测的假设,H包括的所有的预测函数,称为假设空间。通过学习算法,我们希望得到可以无限接近f的预测函数g。
2.感知器
首先,我们有用户数据如下(这段数据引用文首博主的文章数据)
年龄 x 1 x_{1} x1 | 商品价格 x 2 x_{2} x2 | 是否点击y(1为是,-1为否) |
---|---|---|
10 | 300 | -1 |
15 | 377 | -1 |
50 | 137 | 1 |
65 | 92 | 1 |
45 | 528 | -1 |
61 | 542 | 1 |
26 | 394 | -1 |
37 | 703 | -1 |
39 | 244 | 1 |
41 | 398 | 1 |
53 | 495 | 1 |
32 | 119 | 1 |
先看训练的目标:我们希望通过样本集,找到用户年龄与商品价格与用户是否点击商品的联系,从而为每个用户推送其最有可能点击的商品。
样本集包含两项特征:年龄,商品价格。我们将每一样本表示为x=( x 1 x_{1} x1, x 2 x_{2} x2), x 1 x_{1} x1、 x 2 x_{2} x2分别代表年龄和商品价格。用y表示用户是否点击商品。y=1为点击,y=-1为未点击。(特征值可以有更多)
将特征与结果的联系公式化,每个特征值
x
i
x_{i}
xi都会有对应的权重
w
i
w_{i}
wi,表示该特征对结果影响的程度。通过计算所有特征值与权重的乘积和,也可以称作分数,当分数超过某个阈值,则用户会点击该商品,否则不会。这样就得到了以下的公式
y
=
{
1
i
f
∑
i
=
1
n
w
i
x
i
>
t
h
r
e
s
h
o
l
d
−
1
i
f
∑
i
=
1
n
w
i
x
i
<
t
h
r
e
s
h
o
l
d
y = \left\{\begin{matrix} 1 & if \sum_{i=1}^{n}w_{i}x_{i} > threshold\\ -1 & if \sum_{i=1}^{n}w_{i}x_{i} <threshold \end{matrix}\right.
y={1−1if∑i=1nwixi>thresholdif∑i=1nwixi<threshold
我们将加权后的特征分数与阈值相减,再取其符号(sign 是取符号函数, sign(x) = 1 if x>0, -1 otherwise),即可得到结果值y。这一过程使用线性函数h(x)表示为。
$h(x) = sign((\sum_{i=1}^{n}w_{i}x_{i})-threshold) $
因为实际上我们不知道各个特征的权值与阈值的最优取值,所以w和阈值的取值存在无穷的可能性,由此会产生无穷种h。所有情况的h(x)函数构成了假设空间。而我们需要在假设空间中找出最优解。
为了方便实现,将负阈值看作w的第0维收入公式中进行化简,这样我们找到了最优的h(x),就等于是找到了w (结尾乘积和简化成向量的内积,
W
T
W^T
WT为w列表的转置矩阵)
那这个函数的图像究竟是怎样的?
我们将样本数据的特征值表示为n维空间中的点,h(x)=0为分割正负两类的线或者平面。
以上面的用户数据集为例
h
(
x
)
=
s
i
g
n
(
w
0
+
w
1
x
1
+
w
2
x
2
)
h(x) = sign(w_{0} +w_{1}x_{1} + w_{2}x_{2})
h(x)=sign(w0+w1x1+w2x2)
即 h ( x ) = s i g n ( w 1 x 1 + w 2 x 2 − t h r e s h o l d ) h(x) = sign(w_{1}x_{1} + w_{2}x_{2}-threshold) h(x)=sign(w1x1+w2x2−threshold)
红点代表点击,蓝叉代表未点击,学习算法后得到的理想模型用图像表示如下图,。图像中的直线为h(x) = 0。直线往左为h(x) = -1,往右为h(x) = 1,h(x)刚好将数据分成两类。
3.感知器学习算法
PLA属于二值分类算法。一开始没有弄明白这一点,所以对h(x)函数的定位有些云里雾里。
PLA的目标:通过PLA求得的g应该要与理想的f十分接近,可以根据用户数据的特征值推测用户是否点击商品,且至少要保证这一推测在训练的样本集中是准确的。
基本的算法 一共有三步
- 随意选择一个初始向量 w 0 w_{0} w0,可以设置为0向量
- 找到 w t w_{t} wt向量中分错的点 ( x n ( t ) , y n ( t ) ) (x_{n(t)},y_{n(t)}) (xn(t),yn(t)) (t表示第t轮迭代 。即对于错误点 s i g n ( w t T x n ( t ) ) ≠ y n ( t ) sign(w_{t}^T x_{n(t)}) \neq y_{n(t)} sign(wtTxn(t))=yn(t)。
- 修正偏差 w t + 1 ← w t + y n ( t ) x n ( t ) w_{t+1} \leftarrow w_{t} + y_{n(t)}x_{n(t)} wt+1←wt+yn(t)xn(t)
不断重复第2,3步。直到再没有错误的点,算法结束。
>>为什么修正偏差是 w t + y n ( t ) x n ( t ) w_{t} + y_{n(t)}x_{n(t)} wt+yn(t)xn(t)?
我们分两种情况可以更加清楚地讨论。
-
用户点击了商品
此时 y n ( t ) y_{n(t)} yn(t)应该为1, s i g n ( w t T x n ( t ) ) > 0 sign(w_{t}^T x_{n(t)}) > 0 sign(wtTxn(t))>0,这说明w与x之间的夹角大于90°。但是它被分在了-1一边,使 s i g n ( w t T x n ( t ) ) = − 1 < 0 sign(w_{t}^T x_{n(t)}) = -1 <0 sign(wtTxn(t))=−1<0,于是夹角错误地小于90°。此时我们希望通过使其夹角变大来进行修正,通过向量的运算原理, w t + y n ( t ) x n ( t ) w_{t} + y_{n(t)}x_{n(t)} wt+yn(t)xn(t) = w t − x n ( t ) w_{t} - x_{n(t)} wt−xn(t),夹角增大。
-
用户没有点击商品
此时 y n ( t ) y_{n(t)} yn(t)应该为-1, s i g n ( w t T x n ( t ) ) < 0 sign(w_{t}^T x_{n(t)}) < 0 sign(wtTxn(t))<0,这说明w与x之间的夹角小于90°。但是它被分在了1一边,使 s i g n ( w t T x n ( t ) ) = 1 > 0 sign(w_{t}^T x_{n(t)}) = 1 >0 sign(wtTxn(t))=1>0,于是夹角错误地大于90°。此时我们希望通过使其夹角变小来进行修正,通过向量的运算原理, w t + y n ( t ) x n ( t ) w_{t} + y_{n(t)}x_{n(t)} wt+yn(t)xn(t) = w t + x n ( t ) w_{t} + x_{n(t)} wt+xn(t),夹角缩小。
>>为什么h(x)是w取法向量?
机器学习基石中有给出简单的算法运行过程。其中算法确认了
w
0
w_{0}
w0后,取其法向量作为分割线,再判断错误点。有人疑惑为什么会取法向量。
前面我们知道这条分割线实际上为h(x)=0。也就是说
s
i
g
n
(
W
T
x
)
sign(W^Tx)
sign(WTx)=0。两个向量相乘为0说明w和x互相垂直。故找到w后就可以知道分割线的位置,从而对错误进行修正。
>> y n W t + 1 T x n ≥ y n W t T x n y_{n}W^{T}_{t+1}x_{n} \geq y_{n}W^{T}_{t}x_{n} ynWt+1Txn≥ynWtTxn ??
在 s i g n ( w t T x n ) ≠ y n sign(w_{t}^T x_{n}) \neq y_{n} sign(wtTxn)=yn, w t + 1 ← w t + y n x n w_{t+1} \leftarrow w_{t} + y_{n}x_{n} wt+1←wt+ynxn两条规则下,该等式一定成立。因为算法的修正一定会使修正后的结果更加接近目标值。如果 y n y_{n} yn是负的,而 W t T x n W^{T}_{t}x_{n} WtTxn是正的。如果成功修正为负,那么 y n W t + 1 T x n y_{n}W^{T}_{t+1}x_{n} ynWt+1Txn是正数肯定比原本的大。即使没有成功修正,修正也使他向负的靠齐, W t T x n W^{T}_{t}x_{n} WtTxn值变小,与 y n y_{n} yn也会比原来的乘积大。
4.PLA一定会结束吗
答案当然是不一定。训练数据可以分为两种,线性可分与线性不可分。假如数据是线性可分的,我们证明一下PLA是否一定能找到最优值。
假设我们找到了完美的
w
f
w_{f}
wf,此时所有的点都在对应的一边,任意一个点的
y
n
(
t
)
w
f
T
x
n
(
t
)
y_{n(t)}w^{T}_{f}x_{n(t)}
yn(t)wfTxn(t)都大于0。可以得到如下的公式:
y
n
(
t
)
w
f
T
x
n
(
t
)
≥
m
i
n
n
y
n
w
f
T
x
n
>
0
y_{n(t)}w^{T}_{f}x_{n(t)}\geq \underset{n}{min}\,y_{n}w^{T}_{f}x_{n} >0
yn(t)wfTxn(t)≥nminynwfTxn>0
两个向量的夹角越小,他们的内积就越大。我们计算
w
f
T
w
t
+
1
w_{f}^{T}w_{t+1}
wfTwt+1的内积
发现
w
w
w与理想值的内积越来越大,这很可能说明他们越来越接近。为什么说是很可能,因为还有可能是向量模变大了。下面证明他们确实是越来越接近的
数学无能,实在是不会推导,所以证明过程引用某同学的听课笔记
我们定义
R
2
=
m
a
x
n
∥
x
n
∥
2
R^{2}=\underset{n}{max}\left \| x_{n} \right \|^{2}
R2=nmax∥xn∥2,
ρ
=
m
i
n
n
y
n
w
f
T
∥
w
f
∥
x
n
\rho =\underset{n}{min}\,y_{n}\frac{w_{f}^{T}}{\left \|w_{f} \right \|}x_{n}
ρ=nminyn∥wf∥wfTxn
最多需要
R
2
ρ
2
\frac{R^{2}}{\rho^{2}}
ρ2R2轮,算法就可以停止。
5.PLA python实现
刚刚接触python,借助文首提到的博主github上的代码学习了一下。有些不懂的地方一看代码都明白了。她的代码用python2实现,所以稍微的修改了一下使其可以在python3运行,原po代码链接在此
关键代码如下
def PLA(trainingData):
#矩阵 转置
w = np.mat([1,2127,205]).transpose() # Step 1: 向量w赋初值
k = 0 # 第k轮计数
while True:
k += 1
(status, x, y) = noMistakePoint(trainingData, w)
draw(trainingData, w, k, x) # 画图
if status == 'YES': # Step 2: 切分正确,学习完成
return w
else:
w = w + y*x # Step 3: 修正w
sign = lambda x:1 if x > 0 else -1 if x < 0 else -1
def mSign(m):
'''判断某个矩阵的[0][0]元素正负.大于0返回1,否则返回-1'''
x = m.tolist()[0][0]
return 1 if x > 0 else -1 if x < 0 else -1
def noMistakePoint(training_data, w):
'''训练数据中是否有点被切分错误'''
status = 'YES'
for (x, y) in training_data:
if mSign(w.transpose() * x) != sign(y):
status = 'NO'
return (status, x, y)
return status, None, None
6.pocket 算法
如果我们知道训练的数据是线性可分的,那么我们可以用PLA算法进行训练。但是一般来说,我们并不知道我们拥有的数据集是否线性可分,也不知道需要多长时间才能成功训练。所以有了对PLA算法改进的pocket算法。
pocket算法中,分割线不需要将两类的数据完全分割开。它认为数据中可能存在一些错误的数据,称为噪声。分割数据时可以忽略噪声的存在。
算法值在PLA基础上增加了最优w的变量
- 随意选择一个初始向量 w 0 w_{0} w0,可以设置为0向量,初始化最优的权值 w ^ \hat{w} w^
- 随机找一 w t w_{t} wt向量中分错的点 ( x n ( t ) , y n ( t ) ) (x_{n(t)},y_{n(t)}) (xn(t),yn(t)) (t表示第t轮迭代 。即对于错误点 s i g n ( w t T x n ( t ) ) ≠ y n ( t ) sign(w_{t}^T x_{n(t)}) \neq y_{n(t)} sign(wtTxn(t))=yn(t)。
- 修正偏差 w t + 1 ← w t + y n ( t ) x n ( t ) w_{t+1} \leftarrow w_{t} + y_{n(t)}x_{n(t)} wt+1←wt+yn(t)xn(t)
- 如果 w t + 1 w_{t+1} wt+1错误比 w ^ \hat{w} w^少,则 w t + 1 w_{t+1} wt+1成为新的 w ^ \hat{w} w^
循环2-4步,最终
w
^
\hat{w}
w^代表的h(x)就是g。
使用pocket算法可以解决部分非线性可分的数据集,但会消耗更多的计算时间