深度前馈网络(deep feedforward network),也叫做前馈神经网络(feedforward neural network)或者多层感知机(multilayer perceptron, MLP),是典型的深度学习模型。前馈网络的目标是近似某个函数
f
∗
f^*
f∗。例如,对于分类器,
y
=
f
∗
(
x
)
y=f^*(x)
y=f∗(x)将输入
x
x
x映射到一个类别
y
y
y。前馈网络定义了一个映射
y
=
f
(
x
;
θ
)
y=f(x;\theta)
y=f(x;θ),并且学习参数
θ
\theta
θ的值,使它能够得到最佳的函数近似。
为了扩展线性模型来表示
x
x
x的非线性函数,不把线性模型用于
x
x
x本身,而是用在一个变换后的输入
ϕ
(
x
)
\phi(x)
ϕ(x),
ϕ
\phi
ϕ是一个非线性变换。
如何选择
ϕ
\phi
ϕ:
- 选择通用的 ϕ \phi ϕ。
- 手动的设计 ϕ \phi ϕ。
- 深度学习的策略是去学习 ϕ \phi ϕ。
6.1实例:学习XOR
XOR函数(“异或”逻辑)是两个二进制值
x
1
x_1
x1和
x
2
x_2
x2的运算。
原始x空间没办法通过一条线区分0和1。解决这个问题的其中一种方法是使用一个模型来学习一个不同的特征空间,在这个空间上线性模型能够表示这个解。
可以把上述神经网络看成这样两个函数
h
=
f
(
1
)
(
x
,
W
,
c
)
h=f^{(1)}(x,W,c)
h=f(1)(x,W,c)和
y
=
f
(
2
)
(
h
;
w
,
b
)
y=f^{(2)}(h;w,b)
y=f(2)(h;w,b),完整的模型是
f
(
x
;
W
,
c
,
w
,
b
)
=
f
(
2
)
(
f
(
2
)
(
x
)
)
f(x;W,c,w,b)=f^{(2)}(f^{(2)}(x))
f(x;W,c,w,b)=f(2)(f(2)(x))。
如果
f
(
1
)
f^{(1)}
f(1)是线性的,则整体对于输入仍然是线性的,多层次结构表示无意义。
利用非线性函数来描述这些特征。大多数神经网络通过放射变化之后紧跟着一个被称为激活函数的固定非线性函数来实现这个目标,其中仿射变换由学得的参数控制。定义
h
=
g
(
W
T
x
+
c
)
h=g(W^Tx+c)
h=g(WTx+c),其中
W
W
W是线性变换的权重矩阵,c是偏置。
激活函数g通常选择对每个元素分别起作用的函数,有
h
+
i
=
g
(
x
T
W
:
,
i
+
c
i
)
h+i=g(x^TW_{:,i}+c_i)
h+i=g(xTW:,i+ci)。在现代神经网络中,推荐使用
g
(
x
)
=
m
a
x
{
0
,
z
}
g(x)=max\{0,z\}
g(x)=max{0,z}定义的整流线性单元(rectified linear unit),或者成为ReLU(Jarrett et al., 2009b; Nair and Hinton, 2010a; Clorot et al., 2011a)。
整个网络为:
f
(
x
;
W
,
c
,
w
,
b
)
=
w
T
m
a
x
{
0
,
W
T
x
+
c
}
+
b
f(x;W,c,w,b)=w^Tmax\{0,W^Tx+c\}+b
f(x;W,c,w,b)=wTmax{0,WTx+c}+b
令
W
=
[
1
1
1
1
]
W= \begin{bmatrix} 1 & 1 \\ 1 & 1 \\ \end{bmatrix}
W=[1111]
c
=
[
0
1
]
c= \begin{bmatrix} 0 \\ 1 \\ \end{bmatrix}
c=[01]
w
=
[
1
−
2
]
w= \begin{bmatrix} 1\\ -2 \\ \end{bmatrix}
w=[1−2]以及
b
=
0
b=0
b=0。
令X表示设计矩阵,包含二进制输入控件中的全部四个点。
X
=
[
0
0
0
1
1
0
1
1
]
X=\begin{bmatrix} 0 & 0\\0 & 1\\1 & 0\\1 & 1\\ \end{bmatrix}
X=⎣⎢⎢⎡00110101⎦⎥⎥⎤
X
W
=
[
0
0
1
1
1
1
2
2
]
XW=\begin{bmatrix} 0 & 0\\1 & 1\\1 & 1\\2 & 2\\ \end{bmatrix}
XW=⎣⎢⎢⎡01120112⎦⎥⎥⎤加上偏置向量c(广播操作),得到:
[
0
−
1
1
0
1
0
2
1
]
\begin{bmatrix} 0 & -1\\1 & 0\\1 & 0\\2 & 1\\ \end{bmatrix}
⎣⎢⎢⎡0112−1001⎦⎥⎥⎤使用整流线性变化:
[
0
0
1
0
1
0
2
1
]
\begin{bmatrix} 0 & 0\\1 & 0\\1 & 0\\2 & 1\\ \end{bmatrix}
⎣⎢⎢⎡01120001⎦⎥⎥⎤最后乘以一个权重向量w:
[
0
1
1
0
]
\begin{bmatrix} 0\\1 \\1 \\0 \\ \end{bmatrix}
⎣⎢⎢⎡0110⎦⎥⎥⎤
6.2 基于梯度的学习
线性模型和神经网络的最大区别,在于神经网络的非线性导致大多数感兴趣的代价函数变成非凸。
训练算法几乎总是基于使用梯度来使得代价函数下降的各种方法。一些特别的算法是对梯度下降思想的改进和提纯。
6.2.1 代价函数
深度神经网络设计中的一个重要方面是代价函数的选择。
大多数现代的神经网络使用最大似然来训练。这意味着代价函数就是负的对数似然,它与训练数据和模型分布间的交叉熵等价。
随用最大似然来导出代价函数的方法优势在于:它减轻了为每个模型设计代价函数的负担。明确一个模型
p
(
y
∣
x
)
p(y\ |\ x)
p(y ∣ x)则自动地确定了一个代价函数
l
o
g
p
(
y
∣
x
)
\mathtt {log}\ p(y\ |\ x)
log p(y ∣ x)。
贯穿神经网络设计的重要主题是代价函数的梯度必须足够大并且具有足够的预测性,来为学习算法提供一个好的指引。饱和(斜率接近0)的函数破坏了这一目标(比如sigmoid),因为它们把梯度变得非常小。这种情况很容易缠身,因为用于产生隐藏单元或输出单元的输出的激活函数会变得饱和。负对数似然能够使模型避免这个问题。输出单元一般都会包含一个指数函数,这在它的变量取绝对值非常大的负值会造成饱和。负对数似然函数可以消除某些输出单元的指数效果。
对函数求解优化问题需要用到变分法(calculus of variations)。
6.2.2 输出单元
代价函数的选择与输出单元的选择密切相关。大多数,使用数据分布和模型分布间的交叉熵。选择如何表示输出决定了交叉熵的形式。
用于高斯输出分布的线性单元
一种简单的输出单元是基于仿射变换的输出单元,仿射变化不具有非线性。这些单元往往被称为线性单元。
给定特征
h
h
h,线性输出单元层产生一个向量
y
^
=
W
T
x
+
b
\hat y=W^Tx+b
y^=WTx+b。
线性输出层经常被用来产生条件高斯分布的均值:
p
(
y
∣
x
)
=
N
(
y
;
y
^
,
I
)
p(y\ |\ x)=N(y;\hat y,I)
p(y ∣ x)=N(y;y^,I)最大化其对数似然此时等价于最小化均方误差。
基于Bernoulli输出分布的sigmoid单元
许多任务需要预测二值型变量y的值。二分类问题可以归为这种形式。
此时最大似然的方法是定义y在x条件下的Bernoulli分布。
Bernoulli分布仅需单个参数来定义。神经网络只需要预测
P
(
y
=
1
∣
x
)
P(y=1\ |\ x)
P(y=1 ∣ x)即可。为了使这个数是有效的概率,必须处在区间[0,1]中。
如果使用线性单元(ReLU),并通过阈值来限定它成为一个有效的概率。但无法使用梯度下降来高效训练。当
w
T
+
b
w^T+b
wT+b处于区间外,模型的输出对其参数的梯度都将为0。梯度为0通常为飞涨场情况,因为学习算法对于如何改善相应参数不再具有指导意义。
相反,最好是使用一种新的方法来保证无论何时模型给出了错误的答案时,总能有一个较大的梯度。这时候,可以使用基于sigmoid输出单元结合最大似然来实现。
基于Multinoulli输出分布的softmax单元
表示任意一个具有n个可能取值的离散型随机变量的分布时,都可以使用softmax函数。可以看做sigmoid函数的扩展,其中sigmoid函数用来表示二值型变量的分布。
其他的输出类型
异方差(heteroscedastic)模型。在多维变量的情况下,最常见的是使用一个对角精度矩阵:
d
i
a
g
(
β
)
diag\ (\beta)
diag (β)。
6.3 隐藏单元
ReLU是隐藏单元极好的默认选择。
6.3.1 整流线性单元及扩展
整流线性单元的缺陷是不能通过基于梯度的方法学习那些使它们激活为零的样本。整流线性单元的各种扩展保证了能在各个位置都接受到梯度。
整流线性单元的3个扩展基于当
z
i
<
0
z_i<0
zi<0时使用一个非零的斜率
α
i
:
h
i
=
g
(
z
,
α
)
i
=
m
a
x
(
0
,
d
)
+
α
i
m
i
n
(
0
,
z
i
)
\alpha _i :\ h_i=g(z,\alpha)_i=\mathtt{max}(0,d)+\alpha_i\mathtt{min}(0,z_i)
αi: hi=g(z,α)i=max(0,d)+αimin(0,zi)
- 绝对值整流( absolute value rectification)固定 α i = − 1 \alpha_i=-1 αi=−1来得到 g ( z ) = ∣ z ∣ g(z)=|z| g(z)=∣z∣。用于图像中的对象识别,其中寻找在输入照明极性反转下不变的特征是有意义的。
- 渗透整流线性单元(Leaky ReLU)将 α i \alpha_i αi固定成类似0.01的小值。
- 参数化整流线性单元(parametric ReLU)或者PReLU将 α i \alpha_i αi作为学习的参数。
6.3.2 logistic sigmoid与双曲正切函数
在引入整流线性单元之前,大多数神经网络使用logistic sigmoid激活函数
g
(
z
)
=
σ
(
z
)
g(z)=\sigma(z)
g(z)=σ(z)或者是双曲正切激活函数
g
(
z
)
=
t
a
n
h
(
z
)
g(z)=\mathtt{tanh}(z)
g(z)=tanh(z)。
两个函数的关系:
t
a
n
h
(
z
)
=
2
σ
(
2
z
)
−
1
\mathtt{tanh}(z)=2\sigma(2z)-1
tanh(z)=2σ(2z)−1。
当必须要使用sigmoid激活函数时,双曲正切激活函数通常要比logistic sigmoid函数表现更好。在
t
a
n
h
(
0
)
=
0
\mathtt{tanh}(0)=0
tanh(0)=0而
σ
(
0
)
=
1
2
\sigma(0)=\frac{1}{2}
σ(0)=21的意义上,它更像是单位函数。因为tanh在0附近与单位函数类似,训练深层神经网络
y
^
=
w
T
t
a
n
h
(
U
T
t
a
n
h
(
V
T
x
)
)
\hat y=w^T\mathtt{tanh}(U^T\mathtt{tanh}(V^Tx))
y^=wTtanh(UTtanh(VTx))类似于训练一个线性模型
y
^
=
w
T
U
T
V
T
x
\hat y=w^TU^TV^Tx
y^=wTUTVTx,只要网络的激活能够被保持地很小。这使得训练tanh网络更容易。
sigmoid激活函数在除了前馈网络以外的情境中更为常见。循环网络、许多概率模型以及一些自编码器有一些额外的要求使得它们不能使用分段线性激活函数,并且使得sigmoid单元更有效,尽管它存在饱和性的问题。
6.3.3 其他隐藏单元
其他一些常见的隐藏单元类型:
- 径向基函数(radial basis function,RBF): h i = e − 1 σ i 2 ∥ W : , i − x ∥ w h_i=e^{-\frac{1}{\sigma_i^2}\parallel W_{:,i}-x\parallel^w} hi=e−σi21∥W:,i−x∥w。这个函数在x接近模板 W : , i W_{:,i} W:,i时更加活跃。因为对大部分x都饱和到0,因此很难优化。
- softplus函数: g ( a ) = ζ ( a ) = l o g ( 1 + e a ) g(a)=\zeta(a)=\mathtt{log}(1+e^a) g(a)=ζ(a)=log(1+ea)。这是整流线性单元的平滑版本。softplus表明隐藏单元类型的性能可能是非常反直觉——因为它处处可导或因为它不完全饱和。
- 硬双曲正切函数(hard tanh)。形状和tanh以及整流线性单元类似,但是有界, g ( a ) = m a x ( − 1 , m i n ( a , a ) ) g(a)=\mathtt{max}(-1,min(a,a)) g(a)=max(−1,min(a,a))。
6.4 架构设计
架构(architecture)是指网络的整体结构:它应该具有多少单元,以及这些单元应该如何连接。
6.4.1 万能近似性质和深度
线性模型,通过矩阵乘法将特征映射到输出,仅能表示线性函数。具有易于训练的有点,当使用线性模型,许多损失函数会导出优化问题。
万能近似定理(universal approximation theorem)表明,一个前馈神经网络如果具有线性输出层和至少一层具有任何一种“挤压”性质的激活函数(例如logistic sigmoid激活函数)的隐藏层,只要给予网络足够数量的隐藏单元,它可以以任意的精度来近似任何从一个有限维空间的奥另一个有限维空间的Borel可测函数。
万能近似定理意味着无论试图学习什么函数,一个大的MLP一定能够表示这个函数。然而,不能保证训练算法能够学得这个算法。即使MLP能够表示该函数,学习也可能因两个不同的原因而失败。
- 首先,用于训练的优化算法可能找不到用于期望函数的参数值。
- 其次,训练算法可能由于过拟合而选择了错误的函数。
6.4.2 其他架构上的考虑
到目前为止,都将神经网络描述成层的简单链式结构,主要的考虑因素是网路ode深度和每层的宽度。在实践中,神经网络显示出相当的多样性。
6.5 反向传播和其他的微分算法
当使用前馈神经网络接受输入x并产生输出
y
^
\hat y
y^时,信息通过网络向前流动。输入x提供初始信息,然后传播到每一层的隐藏单元,最终产生输出
y
^
\hat y
y^。这种为前向传播(forward propagation)。在训练过程中,前向传播可以持续向前直到它产生一个标量代价函数
J
(
θ
)
J(\theta)
J(θ)。
反向传播(back propagation),允许来自代价函数的信息通过网络向后流动,以便计算梯度。
反向传播仅指用于计算梯度的方法。而另一种算法,例如随机梯度下降,使用该梯度来进行学习。
此外,反向传播经常被误解为仅适用于多层神经网络。但原则上它可以计算任何函数的函数(对于一些函数,正确说法是报告函数的导数是未定义的)。
6.5.1 计算图
为了更精确第描述反向传播算法,使用更精确的计算图(computational graph)有更大的优势。
6.5.2 微积分的链式法则
微积分中的链式法则用于计算复合函数的导数。
∂
z
∂
w
=
∂
z
∂
y
∂
y
∂
x
∂
x
∂
w
=
f
′
(
y
)
f
′
(
x
)
f
′
(
w
)
=
f
′
(
f
(
f
(
w
)
)
)
f
′
(
f
(
w
)
)
f
′
(
w
)
\frac{\partial z}{\partial w}\quad\quad\quad\quad\quad\quad\quad\quad \\=\frac{\partial z}{\partial y} \frac{\partial y}{\partial x}\frac {\partial x}{\partial w}\quad\quad\quad\quad\quad\quad\quad\\=f'(y)f'(x)f'(w)\quad\quad\quad\quad\ \\=f'(f(f(w)))f'(f(w))f'(w)
∂w∂z=∂y∂z∂x∂y∂w∂x=f′(y)f′(x)f′(w) =f′(f(f(w)))f′(f(w))f′(w)
6.5.3 递归地使用链式法则来实现反向传播
6.5.4 全连接MLP中的反向传播计算
6.5.5 符号到符号的导数
6.5.6 一般化的反向传播
6.5.7 实例:用于MLP训练的反向传播
6.5.8 复杂化
提及的反向传播比实践中的更为简单。
- 需要考虑如何控制反向传播的内存消耗。反向传播设计张量的运算。在朴素方法中,将分别计算这些张量中的每一个,然后在第二步中对所有这些张量求和。朴素方法具有过高的存储瓶颈,可以通过保持一个缓冲器,并且在计算时每个值加到该缓冲器中来避免。
- 还需要考虑各种数据类型的处理,比如32位浮点数、64位浮点数和整型。
- 其他技术特性的实现。
6.5.9 深度学习界以外的微分
自动微分(automatic differentiation)领域关心如何以算法方式计算导数。反向传播算法只是自动微分的一种方法,它是一种称为反向模式相加(reverse mode accumulation)的更广泛类型的技术的特殊情况。
一般来说,确定一种计算的顺序是的计算开销最小的问题比较困难。找到计算梯度的最优操作序列是NP完全问题(Naumann,2008)。
假设有变量
p
1
,
p
2
,
…
,
p
n
p_1,p_2,\dots,p_n
p1,p2,…,pn表示概率,以及变量
z
1
,
z
2
,
…
,
z
n
z_1,z_2,\dots,z_n
z1,z2,…,zn表示未归一化的对数概率。假设定义:
q
i
=
e
(
z
i
)
∑
i
e
(
z
i
)
q_i=\frac{e^{(z_i)}}{\sum_ie^{(z_i)}}
qi=∑ie(zi)e(zi)通过指数化、求和与除法运算构建softmax函数,并构造交叉熵损失函数
J
=
−
∑
i
p
i
l
o
g
q
i
J=-\sum_ip_i\ log\ q_i
J=−∑ipi log qi。
Theano(Bergstra et al. 2010b; Bastien et al. 2012b)能够执行某些种类的袋鼠替换来改进由纯反向传播算法提出的图。
6.5.10 高阶微分
在深度学习软件框架中,至少包括Theano和TensorFlow。这些库使用一种数据结构来描述要被微分的原始函数,使用相同类型的数据结构来描述这个函数的导数表达式。
如果有函数
f
:
R
n
→
R
f :\mathbb R^n\ \rightarrow\ \mathbb R
f:Rn → R,那么Hessian矩阵的大小是
n
×
n
n\times n
n×n。在典型的深度学习应用中,n将是模型的参数数量,可能很容易达到数十亿数量级。因此,完整的Hessian矩阵无法进行表示。
典型的深度学习方法是使用Krylov方法,而不是显式地计算Hessian矩阵。Krylov方法是用于执行各种操作的一组迭代技术,操作方法使用,如近似求解矩阵的逆或近似矩阵的特征值/特征向量等,而非使用矩阵-向量乘法以外的任何操作。
为了在Hessian矩阵上使用Krylov方法,需要能够计算Hessian矩阵
H
\mathtt H
H和任意向量
v
v
v间的乘积即可。实现这一目标的一种直观方法是:
H
v
=
∇
x
[
(
∇
x
f
(
x
)
)
T
v
]
Hv=\nabla_x[(\nabla_xf(x))^Tv]
Hv=∇x[(∇xf(x))Tv]该表达式中两个梯度的计算都可以由机器自动完成。(外部梯度表达式是内部梯度表达式的函数的梯度——双层梯度)
如果
v
v
v本身是由计算图产生的一个向量,那么自动微分过程不应该对产生
v
v
v的图进行微分。
虽然计算Hessian通常是不可取的,但是可以使用Hessian向量积。对所有的
i
=
1
,
…
,
n
i=1,\dots,n
i=1,…,n简单地计算
H
e
(
i
)
He^{(i)}
He(i),其中
e
(
i
)
e^{(i)}
e(i)是
e
(
i
)
=
1
e^{(i)}=1
e(i)=1并且其他元素都为0的one-hot向量。
6.6 历史小记
前馈网络被视为高效的非线性函数近似器