感知机是二分类的线性分类模型,其输入是样本的特征向量,输出是样本的类别。感知机对应于输入空间中将样本划分为两个类别,属于判别模型。感知机学习旨在求出将训练数据进行线性划分的分离超平面,为此,导入基于误分类的损失函数,利用梯度下降法对损失函数进行极小化,求得感知机模型。
1、感知机模型
假设输入空间是
X
⊆
R
n
X\subseteq \mathbb{R}^{n}
X⊆Rn,输出空间是
Y
=
{
+
1
,
−
1
}
Y=\left \{ +1,-1 \right \}
Y={+1,−1}。输入
x
∈
X
x\in X
x∈X表示样本的特征向量,对应于输入空间的点,输出
y
∈
Y
y\in Y
y∈Y表示样本的类别。由输入空间到输出空间的函数如下:
称为感知机,其中权值
ω
\omega
ω和偏置b是感知机模型的参数。
感知机是一种线性分类模型,属于判别模型,感知机的假设空间定义在特征空间中所有线性分类模型。
2、多层感知机及其BP算法
Deep Learning 近年来在各个领域都取得了 state-of-the-art 的效果,对于原始未加工且单独不可解释的特征尤为有效,传统的方法依赖手工选取特征,而 神经网络可以进行学习,通过层次结构学习到更利于任务的特征。得益于近年来互联网充足的数据,计算机硬件的发展以及大规模并行化的普及。本文主要简单介绍 MLP ,也即为Full-connection Neural Network ,网络结构如下,分为输入,隐层与输出层,除了输入层外,其余的每层激活函数均采用 sigmod ,MLP 容易受到局部极小值与梯度弥散的困扰,如下图所示:
MLP 的 BP 算法基于经典的链式求导法则,首先看前向传导,对于输入层有
I
I
I 个单元, 对于输入样本 (x,z) ,隐层的输入为:
这里函数f为 非线性激活函数,常见的有sigmod 或者是 tanh,本文选取 sigmod 作为激活函数。计算完输入层向第一个隐层的传导后,剩下的隐层计算方式类似,用
h
l
h_{l}
hl 表示第
l
l
l层的单元数:
对于输出层,若采用二分类即 logistic regression ,则前向传导到输出层:
这里 y 即为 MLP 的输出类别为 1 的概率,输出类别为 0 的概率为 1−y,为了训练网络,当 z=1 时,y 越大越好,而当 z=0 时, 1−y越大越好 ,这样才能得到最优的参数 w ,采用 MLE 的方法,写到一起可以得到
y
z
(
1
−
y
)
1
−
z
y^{z}(1-y)^{1-z}
yz(1−y)1−z ,这便是单个样本的似然函数,对于所有样本可以列出 log 似然函数
O
=
∑
x
,
z
z
l
o
g
y
+
(
1
−
z
)
l
o
g
(
1
−
y
)
O=∑_{x,z}zlogy+(1−z)log(1−y)
O=∑x,zzlogy+(1−z)log(1−y) ,直接极大化该似然函数即可,等价于极小化以下的 −log 损失函数:
对于多分类问题,即输出层采用softmax,假设有K个类别,则输出层的第k个单元计算过程如下:
则得到类别 k 的概率可以写为$$ ,注意标签z中只有第k维为 1,其余为 0,所以现在只需极大化该似然函数即可:
同理等价于极小化以下损失:
以上便是softmax的损失函数,这里需要注意的是以上优化目标O均没带正则项,而且 logistic 与 softmax 最后得到的损失函数均可以称作交叉熵损失,注意和平方损失的区别。
反向传播过程
有了以上前向传导的过程,接下来看误差的反向传递,对于sigmod来说,最后一层的计算如下:
α
=
∑
h
ω
h
⋅
b
h
,
y
=
f
(
α
)
=
σ
(
α
)
\alpha=\sum_{h}\omega_{h}\cdot b_{h},y=f(\alpha)=\sigma (\alpha)
α=∑hωh⋅bh,y=f(α)=σ(α)这里
b
h
b_{h}
bh 为倒数第二层单元h的输出,σ为sigmod激活函数,且满足 σ′(a)=σ(a)(1−σ(a)),对于单个样本的损失 :
可得到如下的链式求导过程:
显而易见对于后半部分
∂
α
∂
ω
h
\frac{\partial \alpha}{\partial\omega _{h}}
∂ωh∂α为
b
h
b_{h}
bh,对于前半部分
∂
O
∂
α
\frac{\partial O}{\partial \alpha}
∂α∂O:
以上,便得到了logistic的残差,接下来残差反向传递即可,残差传递形式同softmax,所以先推导softmax的残差项,对于单个样本,softmax的log损失函数为:
其中:
根据以上分析,可得到
y
k
′
y_{k^{'}}
yk′关于
α
k
\alpha_{k}
αk的导数:
现在能得到损失函数O对于
α
k
\alpha_{k}
αk的导数:
这里有
∑
i
z
i
=
1
\sum_{i}z_{i}=1
∑izi=1,即只有一个类别,到这一步,softmax和sigmod的残差均计算完成,可用
σ
\sigma
σ来表示,对于单元j,其形式如下:
这里可以得到softmax层向倒数第二层的残差反向传递公式:
其中
a
k
=
∑
h
w
h
k
b
h
a_{k}=\sum_{h}w_{hk}b_{h}
ak=∑hwhkbh ,对于sigmod层,向倒数第二层的反向传递公式为:
以上公式的 δ 代表sigmod层唯一的残差,接下来就是残差从隐层向前传递的传递过程,一直传递到首个隐藏层即第二层(注意,残差不会传到输入层,因为不需要,对输入层到第二层的参数求导,其只依赖于第二层的残差,因为第二层是这些参数的放射函数):
整个过程可以看下图:
最终得到关于权值的计算公式:
至此完成了backwark pass 的过程,注意由于计算比较复杂,有必要进行梯度验证。对函数O关于参数
ω
i
j
\omega_{ij}
ωij 进行数值求导即可,求导之后与与上边的公式验证差异,小于给定的阈值即认为我们的运算是正确的。
# 多层感知机
from sklearn.datasets import make_moons
from sklearn.neural_network import MLPClassifier
import numpy as np
import matplotlib.pyplot as plt
# 生成数据
x, y = make_moons(n_samples=800, noise=0.15, random_state=42)
# 多层感知机模型
mlp = MLPClassifier(hidden_layer_sizes=(100, 100)).fit(x, y)
# 可视化分类边界
x_min, x_max = x[:, 0].min() - 1, x[:, 0].max() + 1
y_min, y_max = x[:, 1].min() - 1, x[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02))
z = mlp.predict(np.c_[xx.ravel(), yy.ravel()])
zz = z.reshape(xx.shape)
plt.contourf(xx, yy, zz)
plt.scatter(x[:, 0], x[:, 1], c=y)
plt.show()