在介绍神经网络之前,首先介绍一下神经元模型。
神经元模型可以描述为这样的一张图:
对于一个模型而言,我们首先要把握住四个部分:输入、输出、参数以及对应的运算关系。(这一点很重要)
在上图所示的神经元模型中:
输入为
X
X
X,输出为
Y
Y
Y,参数为权重
W
W
W和偏置
b
b
b。
其运算关系为:
Z
=
x
1
w
1
+
x
2
w
2
+
.
.
.
+
x
n
w
n
+
b
Z = x_1w_1+x_2w_2+...+x_nw_n+b
Z=x1w1+x2w2+...+xnwn+b
Y
=
σ
(
Z
)
=
σ
(
W
T
X
+
b
)
Y = σ(Z) = σ(W^TX+b)
Y=σ(Z)=σ(WTX+b)
其中,
σ
σ
σ被称为激活函数,一般为连续的非线性函数,以增强网络的表示能力。
常见的激活函数有Sigmoid函数、Relu函数、Tanh函数等等,在这里不一一赘述,有兴趣的朋友们可以自行百度。
人工神经网络就是由神经元模型组成的,具有并行分布式结构的神经网络模型。
【一】DNN
DNN,前馈神经网络,网络中神经元分属于不同的层,整个网络中无反馈,信号从输入层向输出层单向传播,可用一个有向无环图表示 。
从图中可以看出,网络的输入与神经元模型相同,是一个
N
N
N维向量
X
X
X,网络的输出是一个
M
M
M维向量
Y
Y
Y。因此,模型中的运算关系可以看作
f
:
R
n
→
R
m
f:R^n \to R^m
f:Rn→Rm。
此外,模型中的参数包括每层所对应的权重
W
i
W^i
Wi和偏置
b
i
b^i
bi。
这样,整个模型可以描述为:
Y
=
f
(
X
,
θ
)
θ
=
{
W
1
,
b
1
,
W
2
,
b
2
,
.
.
.
,
W
L
,
b
L
}
Y = f(X, θ) \quad θ = \{W^1,b^1,W^2,b^2,...,W^L,b^L\}
Y=f(X,θ)θ={W1,b1,W2,b2,...,WL,bL}
y
=
f
(
x
)
=
σ
(
W
L
.
.
.
σ
(
W
2
σ
(
W
1
x
+
b
1
)
+
b
2
)
.
.
.
+
b
L
)
y = f(x) = σ(W^L...σ(W^2σ(W^1x+b^1)+b^2)...+b^L)
y=f(x)=σ(WL...σ(W2σ(W1x+b1)+b2)...+bL)
其中,对于每一层而言:
Z
L
=
W
L
a
L
−
1
+
b
L
,
a
L
=
σ
(
Z
L
)
Z^L = W^La^{L-1}+b^L, \quad\quad a^L = σ(Z^L)
ZL=WLaL−1+bL,aL=σ(ZL)
即:
X
=
a
0
→
Z
1
→
a
1
→
Z
2
→
.
.
.
→
a
L
−
1
→
Z
L
→
a
L
=
Y
X = a^0 \to Z^1 \to a^1 \to Z^2 \to...\to a^{L-1} \to Z^L \to a^L = Y
X=a0→Z1→a1→Z2→...→aL−1→ZL→aL=Y
在上述模型中,需要经过计算得到的,就是模型中的参数值(
W
W
W,
b
b
b),对于有监督训练来讲(在这里,为了简化问题,我们仅考虑有监督训练问题),如何求得权重
W
W
W和偏置
b
b
b呢?
【二】梯度下降法
在有监督训练中,我们有给定的实例
(
x
i
,
y
i
′
)
(x^i, {y^i}')
(xi,yi′),那么很自然地,我们会想到列方程来求解参数,但是当参数个数很多时,给定的实例个数可能会小于参数个数,这样,方程法将无法求解参数。
所以,我们通过另一种方式来进行参数求解——迭代调参:通过调整参数,让模型输出递归性地逼近标准输出。
在神经网络中,我们往往用迭代调参的方法进行参数求解。
很明显,在调参的过程中会有三个最基本的问题:
1.参数的初始值是什么?
2.怎么调参数?
3.要把参数调到什么程度才算结束?
对于第一个问题,方法很简答:随便设置参数初值。
因为参数值在迭代过程中是可调的,所以初始值并不重要(实际上还是会对模型效果有些影响的,在后面的多极值点函数问题中会提到),因此,可以随意设置。
对于后两个问题,一般来说,迭代调参方式分为两个步骤:
1.定义目标函数(损失函数):将问题转化为极值问题。
2.优化目标函数:用调参的方式求目标函数的极值,以此来确定参数。
这样,我们既解决了如何调整参数的问题,也确定了调参什么时间结束。
为了反应模型输出对真实结果的拟合程度,很自然地会想到利用模型输出结果
y
i
y^i
yi与真实结果
y
i
′
{y^i}'
yi′之间的误差定义目标函数。
损失函数,也就是我们所说的目标函数,常记作
C
(
θ
)
C(θ)
C(θ)或
L
(
θ
)
L(θ)
L(θ),我们的问题也就定义成了:求解
m
i
n
C
(
θ
)
minC(θ)
minC(θ),使得模型输出与真实结果之间的误差最小。
损失函数有很多,交叉熵函数是较为常用的一种,对损失函数感兴趣的朋友可以自行百度了解~
现在,目标函数定义好了,索性将其表示为
L
(
θ
)
L(θ)
L(θ),我们的问题和目标都已经很清晰了:
已知
L
(
θ
)
L(θ)
L(θ),求
m
i
n
L
(
θ
)
minL(θ)
minL(θ)
我们将其描述为“优化目标函数”过程,也就是上面所说的步骤二:利用迭代调参的方式逼近我们的目标。
这种迭代调参的方法就是大名鼎鼎的梯度下降法。
梯度下降法背后的数学原理是泰勒公式:
假如函数
h
(
x
)
h(x)
h(x)在
x
=
x
0
x = x_0
x=x0附近无限可微,那么利用泰勒展开可以写为:
h
(
x
)
=
∑
k
=
0
∞
h
(
k
)
(
x
0
)
k
!
(
x
−
x
0
)
k
h(x) = \sum_{k=0}^∞\frac{h^{(k)}(x_0)}{k!}(x-x_0)^k
h(x)=k=0∑∞k!h(k)(x0)(x−x0)k
=
h
(
x
0
)
+
h
′
(
x
0
)
(
x
−
x
0
)
+
h
′
′
(
x
0
)
2
!
(
x
−
x
0
)
2
+
.
.
.
=h(x_0)+h'(x_0)(x-x_0)+\frac{h''(x_0)}{2!}(x-x_0)^2+...
=h(x0)+h′(x0)(x−x0)+2!h′′(x0)(x−x0)2+...
那么,当
x
x
x与
x
0
x_0
x0无限接近时,上式可以写为:
h
(
x
)
≈
h
(
x
0
)
+
h
′
(
x
0
)
(
x
−
x
0
)
h(x)≈h(x_0)+h'(x_0)(x-x_0)
h(x)≈h(x0)+h′(x0)(x−x0)
不失一般性:
h
(
x
1
)
=
h
(
x
0
)
+
h
′
(
x
0
)
(
x
1
−
x
0
)
h(x_1)=h(x_0)+h'(x_0)(x_1-x_0)
h(x1)=h(x0)+h′(x0)(x1−x0)
由于我们的目标是求解函数
h
(
x
)
h(x)
h(x)的极小值(在这里我们将
h
(
x
)
h(x)
h(x)看作目标函数),那么每次选取的
h
(
x
i
)
h(x_i)
h(xi)的值要比上一次的
h
(
x
i
−
1
)
h(x_{i-1})
h(xi−1)更小,即:
h
(
x
i
)
<
h
(
x
i
−
1
)
h(x_i)<h(x_{i-1})
h(xi)<h(xi−1)
带入泰勒展开式:
h
(
x
i
)
=
h
(
x
i
−
1
)
+
h
′
(
x
i
−
1
)
(
x
i
−
x
i
−
1
)
h(x_i) = h(x_{i-1})+h'(x_{i-1})(x_i-x_{i-1})
h(xi)=h(xi−1)+h′(xi−1)(xi−xi−1)
可以得出:
h
′
(
x
i
−
1
)
(
x
i
−
x
i
−
1
)
<
0
h'(x_{i-1})(x_i-x_{i-1})<0
h′(xi−1)(xi−xi−1)<0
值得注意的是, x i x_i xi和 x i − 1 x_{i-1} xi−1的大小犹未可知。或者说,无所谓 x i x_i xi和 x i − 1 x_{i-1} xi−1的大小关系如何,梯度下降法都可以很好地达到我们预期的目标,对此有疑问的朋友们可以自己画图验证一下~
到这里,我们就得到了迭代调参的方法——梯度下降法:
X
i
+
1
←
X
i
−
η
h
′
(
X
i
)
X_{i+1} \leftarrow X_{i}- ηh'(X_i)
Xi+1←Xi−ηh′(Xi)
其中,
η
η
η被称为学习率,
h
′
(
X
i
)
h'(X_i)
h′(Xi)被称为梯度,整个迭代过程到梯度为0(即
h
′
(
X
i
)
h'(X_i)
h′(Xi)=0)时停止。
可以看出,梯度下降法面临着这样一个很明显的问题:
加入函数是一个具有多极值点的函数,那么如何确定梯度下降之后的结果是最优解呢?
(图片来自百度)
上图中,很明显,函数在
x
1
x_1
x1处达到最小值。然而,如果梯度下降法找到了
x
4
x_4
x4或者
x
6
x_6
x6之后,是不会再继续寻找极值点的,因为此刻的梯度已经为零,迭代结束。
对于这个问题,解决方法比较佛系:设置随机的参数初值。
这个方法不能保证一定能解决这个问题,但是至少做出了一定的,成本可接受的努力。
此外,学习率
η
η
η的设置也是需要考虑的。
很明显,学习率过大会导致无法到达最优解,学习率过小将会导致迭代次数过多。
对于如何设置学习率,本人在另外一篇博客中有简单提及:机器学习如何进行调参
在这里要注意一点,此“调参”非彼“调参”,本文中所说的调参是调节模型训练的参数 W W W、 b b b,而在引用博客中所说的调参是调节超参数。超参数在模型训练之前预先设置,并在模型训练过程中保持不变。
最后,梯度下降法根据调节参数利用的样本个数分为:梯度下降法(一次利用所有样本)、随机梯度下降法(一次利用随机选取的一个样本)、mini-batch梯度下降法(一次利用一个batch的样本),对其感兴趣的朋友可以自行百度了解,在这里就不再赘述。
【三】反向传播算法
在梯度下降法提出过后,人们发现,调节参数仍然是一项巨大的工程,这直接导致了神经网络无法做得过深,直到反向传播(BP)算法诞生。
BP算法的核心思想很简单:将输出误差以某种形式反传给各层所有的单元,各层按本层误差修正各单元连接权值。
这样,神经网络真正地成为了深度学习,迎来了自己的春天。
你一定还记得,在DNN中有这样一组式子:
对于每一层而言:
Z
L
=
W
L
a
L
−
1
+
b
L
(
1
)
Z^L = W^La^{L-1}+b^L \quad(1)
ZL=WLaL−1+bL(1)
a
L
=
σ
(
Z
L
)
(
2
)
a^L = σ(Z^L) \quad(2)
aL=σ(ZL)(2)
以及:
X
=
a
0
→
Z
1
→
a
1
→
Z
2
→
.
.
.
→
a
L
−
1
→
Z
L
→
a
L
=
Y
X = a^0 \to Z^1 \to a^1 \to Z^2 \to...\to a^{L-1} \to Z^L \to a^L = Y
X=a0→Z1→a1→Z2→...→aL−1→ZL→aL=Y
那么,按照对网络递推关系的理解,我们可以很容易在此基础上得到下面的一组式子:
Δ
W
1
→
Δ
Z
1
→
Δ
a
1
→
Δ
Z
2
→
.
.
.
→
Δ
Z
L
→
Δ
a
L
→
Δ
Y
→
Δ
C
(
θ
)
ΔW^1\toΔZ^1\toΔa^1\toΔZ^2\to...\toΔZ^L\toΔa^L\toΔY\toΔC(θ)
ΔW1→ΔZ1→Δa1→ΔZ2→...→ΔZL→ΔaL→ΔY→ΔC(θ)
Δ
W
2
→
Δ
Z
2
→
.
.
.
→
Δ
Z
L
→
Δ
a
L
→
Δ
Y
→
Δ
C
(
θ
)
\quad\quadΔW^2\toΔZ^2\to...\toΔZ^L\toΔa^L\toΔY\toΔC(θ)
ΔW2→ΔZ2→...→ΔZL→ΔaL→ΔY→ΔC(θ)
.
.
.
.
.
.
......
......
Δ
W
L
→
Δ
Z
L
→
Δ
a
L
→
Δ
Y
→
Δ
C
(
θ
)
\quad\quad\quadΔW^L\toΔZ^L\toΔa^L\toΔY\toΔC(θ)
ΔWL→ΔZL→ΔaL→ΔY→ΔC(θ)
很容易理解,这意味着,某层的
W
W
W改变影响了之后所有层的结果。
利用梯度下降法,可以得到:
[
W
I
]
1
←
[
W
I
]
0
−
η
∂
C
(
θ
)
∂
W
I
[W^I]^1\leftarrow[W^I]^0-η\frac{\partial{C(θ)}}{\partial{W^I}}
[WI]1←[WI]0−η∂WI∂C(θ)
在这个式子中,我们关心的只有梯度
∂
C
(
θ
)
∂
W
I
\frac{\partial{C(θ)}}{\partial{W^I}}
∂WI∂C(θ),根据导数的链式法则,有:
∂
C
(
θ
)
∂
W
I
=
∂
C
(
θ
)
∂
Z
I
∂
Z
I
∂
W
I
\frac{\partial{C(θ)}}{\partial{W^I}}=\frac{\partial{C(θ)}}{\partial{Z^I}}\frac{\partial{Z^I}}{\partial{W^I}}
∂WI∂C(θ)=∂ZI∂C(θ)∂WI∂ZI
其中,对于后一项
∂
Z
I
∂
W
I
\frac{\partial{Z^I}}{\partial{W^I}}
∂WI∂ZI我们可以利用式(1)简单求得,结果为
a
I
−
1
a^{I-1}
aI−1。
那么问题的关键就转化为了求解前一项:
∂
C
(
θ
)
∂
Z
I
\frac{\partial{C(θ)}}{\partial{Z^I}}
∂ZI∂C(θ),不妨设该误差项为
δ
I
δ^I
δI。
由于误差是从最后一层反向传播,所以先对最后一层计算
δ
L
δ^L
δL,这也很简单:
δ
L
=
∂
C
(
θ
)
∂
Z
L
=
∂
C
(
θ
)
∂
Y
∂
Y
∂
Z
L
δ^L=\frac{\partial{C(θ)}}{\partial{Z^L}}=\frac{\partial{C(θ)}}{\partial{Y}}\frac{\partial{Y}}{\partial{Z^L}}
δL=∂ZL∂C(θ)=∂Y∂C(θ)∂ZL∂Y
后一项可以由式(2)求得,结果为:
σ
′
(
Z
L
)
σ'(Z^L)
σ′(ZL)。
(对最后一层而言,
Y
Y
Y与
a
L
a^L
aL相同)
而在前一项
∂
C
(
θ
)
∂
Y
\frac{\partial{C(θ)}}{\partial{Y}}
∂Y∂C(θ)中,很明显,误差函数
C
(
θ
)
C(θ)
C(θ)是输出
Y
Y
Y的函数,因此也可通过简单的求导得到,在这里记为
∇
C
r
(
y
r
)
\nabla{C^r(y^r)}
∇Cr(yr)。
于是,我们可以得到
δ
L
=
σ
′
(
Z
L
)
∇
C
r
(
y
r
)
δ^L=σ'(Z^L)\nabla{C^r(y^r)}
δL=σ′(ZL)∇Cr(yr)
现在,我们有了最后一层的
δ
L
δ^L
δL,最关键的部分就是求
δ
I
δ^I
δI和
δ
I
+
1
δ^{I+1}
δI+1之间的关系了,有了这个关系,误差就可以从最后一层反向传播至所有层。
定义第I层的第i个神经元的误差为
δ
i
I
δ^{I}_i
δiI,下图为神经网络状态:
根据网络的递推关系,我们可以得到:
δ
i
I
=
∂
C
r
∂
z
i
I
δ^{I}_i=\frac{\partial{C^r}}{\partial{z^I_i}}
δiI=∂ziI∂Cr
由于
Δ
C
r
ΔC^r
ΔCr和
Δ
z
i
I
Δz^I_i
ΔziI之间的关系是这样的:
所以,根据导数的链式法则,有:
δ
i
I
=
∂
C
r
∂
z
i
I
=
∂
a
i
I
∂
z
i
I
∑
k
∂
z
k
I
+
1
∂
a
i
I
∂
C
r
∂
z
k
I
+
1
δ^{I}_i=\frac{\partial{C^r}}{\partial{z^I_i}}=\frac{\partial{a^I_i}}{\partial{z^I_i}}\sum_k\frac{\partial{z^{I+1}_k}}{\partial{a^I_i}}\frac{\partial{C^r}}{\partial{z^{I+1}_k}}
δiI=∂ziI∂Cr=∂ziI∂aiIk∑∂aiI∂zkI+1∂zkI+1∂Cr
在这个式子中,我们可以发现,所有的偏导均可求,求解结果如下:
δ
i
I
=
σ
′
(
z
i
I
)
∑
k
w
k
i
I
+
1
δ
k
I
+
1
δ^{I}_i=σ'(z^I_i)\sum_kw_{ki}^{I+1}δ^{I+1}_k
δiI=σ′(ziI)k∑wkiI+1δkI+1
把上式中的
w
w
w项写成矩阵形式:
δ
I
=
σ
′
(
z
I
)
⋅
(
W
I
+
1
)
T
δ
I
+
1
δ^{I}=σ'(z^I)·(W^{I+1})^Tδ^{I+1}
δI=σ′(zI)⋅(WI+1)TδI+1
其中,‘·’表示矩阵的点乘,
σ
′
(
z
I
)
=
[
σ
′
(
z
1
I
)
,
σ
′
(
z
2
I
)
,
.
.
.
,
σ
′
(
z
i
I
)
,
.
.
.
]
T
σ'(z^I)=[σ'(z^I_1),σ'(z^I_2),...,σ'(z^I_i),...]^T
σ′(zI)=[σ′(z1I),σ′(z2I),...,σ′(ziI),...]T。
至此,反向传播算法的全部要素都已经求得,在推导BP算法的过程中,导数的链式法则是基础,对链式法则不熟悉的朋友可以自行百度了解~
此外,最重要的一点是把握住每层之间的递推关系(这一点真的很重要),如果还有哪个地方不理解,闲暇之余自己手推一遍是比较好的一种加深理解的方法~
在反向传播的过程中,我们发现,在每一层都要乘激活函数的导数,即
σ
′
(
z
I
)
σ'(z^I)
σ′(zI)。当激活函数为sigmoid函数或者tanh函数时,由于激活函数的导数小于1,会导致误差经过每一层网络时都会衰减。当网络层数很深时误差接近于0,这就是梯度消失问题。
这个问题可以将激活函数改为Relu函数加以解决。
【四】CNN
CNN,卷积神经网络,在图像相关问题中得到广泛使用。
为什么呢?
在上文中所提到的DNN中,我们可以做这样一个假设:
如果第
i
i
i层有
n
i
n^i
ni 个神经元,第
i
−
1
i-1
i−1层有
n
i
−
1
n^{i-1}
ni−1 个神经元,那么,连接边有
n
i
n
i
−
1
n^in^{i-1}
nini−1个,也就是说,权重矩阵有
n
i
n
i
−
1
n^in^{i-1}
nini−1个参数。
如果有一张图像是
m
∗
n
m*n
m∗n的,当
m
m
m、
n
n
n很大时,权重矩阵的参数非常多,训练的效率会非常低。
假设
m
=
n
=
10
m=n=10
m=n=10,第一个隐藏层有1024个神经元,那么权重矩阵的参数就有102400个。
CNN就是为了解决参数过多的问题而提出的。
卷积神经网络(Convolutional Neural Networks,CNN)是一种前馈神经网络,是受生物学上感受野(Receptive Field)的机制启发而提出的。所谓感受野,就是神经元的特定区域,只有在这个区域内的刺激才可以激活该神经元。
(对于感受野的概念,这里介绍得比较笼统,有兴趣的朋友们可以自行百度~)
在网络结构上,CNN是由卷积层、池化层(也叫子采样、降采样层)和全连接层交叉堆叠而成。
在卷积层,利用卷积核(filter)对图片进行卷积运算,得到的结果称为特征图(feature map)。
假设我们的图片是这样的:
卷积核是这样的:
那么我们得到的结果(特征图),是这样的:
至于具体是怎么操作的,涉及到填充(padding)、步长(stride)等等概念的组合以及卷积运算的基本概念,在这里不一一赘述,有兴趣的朋友可以自行百度或者参看本人的另外一篇博客:机器学习中的一些基本概念。
看到这里,大家会发现一件事:我们把一张
6
∗
6
6*6
6∗6的图片处理成了
4
∗
4
4*4
4∗4的图片,这从一方面减少了参数的数量。
现在,我们再来做一笔计算:
还是一个10*10的图像,第一层的神经元个数还是1024个。
如果这1024个神经元是用16个
3
∗
3
3*3
3∗3的filter卷积得到(
1024
=
16
∗
(
(
10
−
3
)
/
1
+
1
)
2
1024 = 16*((10-3)/1+1)^2
1024=16∗((10−3)/1+1)2)(假设步长为1,无填充),那么参数的个数是
16
∗
3
∗
3
=
144
16*3*3 = 144
16∗3∗3=144个(16个filter,每个filter都是
3
∗
3
3*3
3∗3)。
很明显,与DNN相比,CNN在参数个数方面的优越性很强。
此外,卷积连接有这样的两个特点:局部连接、权重共享。
即,对于一张feature map来说,所用的filter是同一个,而且一个filter每次只对原图像中的一部分进行卷积操作,重复多次,得到结果。
在池化层,池化操作(pooling)的本质是采样,用于减少模型参数并保留有效信息避免过拟合,提高训练速度。
以刚刚得到的feature map为例,进行
2
∗
2
2*2
2∗2的max pooling:
可以得到如下结果:
可以看出,在每个
2
∗
2
2*2
2∗2的方格中,选取方格内最大的值,组成新的结果:
上面的描述中,pooling即为池化。
在网络训练中,卷积层和池化层作为一个整体进行训练。而且,卷积层和池化层可以进行多层堆叠。
此外,池化的方法有很多,在这里不一一介绍,有兴趣的朋友可以参看:机器学习中的一些基本概念
在全连接层,首先将最后的池化层的单元进行“平化”,组成全连接输入网:
此后,就像传统DNN结构相同啦~
CNN具有三个结构上的特性:
1.局部连接
2.权重共享
3.时间或空间上的降采样
这些特性使得卷积神经网络具有一定程度上的平移、缩放和扭曲不变性。
【五】RNN
在神经网络中,有两个RNN:Recurrent Neural Network 循环神经网络、Recursive Neural Network 递归神经网络,本节所提到的RNN均指循环神经网络。
在了解了DNN和CNN过后,我们会意识到一个问题,CNN和DNN只能处理输入、输出定长的问题,而处理变长问题效率不高,而在自然语言处理(NLP)等领域,输入、输出(语句)的长度往往不固定。
(我们将在NLP章节介绍另一种RNN:递归神经网络)
除此之外,对于时序相关问题,DNN和CNN也无法解决。因此,提出循环神经网络的概念。
循环神经网络的核心思想十分简单:将问题在时序上分解为一系列相同的“单元”,单元的神经网络可以在时序上展开,并且能将上一时刻的结果传递给下一时刻,整个网络按时间轴展开,即可处理变长和时序问题。
RNN的单元结构如下:
对于一个模型而言,最重要的是什么?
四个部分:输入、输出、参数、对应运算关系。
在RNN单元中:
输入:X,以及来自前一时刻隐藏层的结果
输出:Y,以及传递给下一时刻隐藏层的结果
参数:
W
i
W_i
Wi、
W
o
W_o
Wo、
W
h
W_h
Wh、
b
b
b
对应运算关系(信息传播):
h
(
t
)
=
σ
(
W
i
X
+
W
h
h
(
t
−
1
)
+
b
)
h(t)=σ(W_iX+W_hh(t-1)+b)
h(t)=σ(WiX+Whh(t−1)+b)
Y
=
s
o
f
t
m
a
x
(
W
o
h
(
t
)
)
Y=softmax(W_oh(t))
Y=softmax(Woh(t))
其中,
s
o
f
t
m
a
x
softmax
softmax函数是一种特殊的函数,使得输出为一个对应的概率值,对
s
o
f
t
m
a
x
softmax
softmax函数感兴趣的朋友们可以自行百度进行了解~
有了这个RNN基本单元,整个RNN网络也就呼之欲出了:
这张图中告诉了我们极为关键的一点:每个RNN基本单元的对应参数值都是相同的(这一点十分重要)。
此外,对应不同的问题,RNN的输入输出结构可以不同:
同样,利用梯度下降法进行参数学习。
但是反向传播过程与DNN有所不同:
传统BP算法无法保证在参数调整的过程中对应参数相同,而RNN网络各个单元中的对应参数要求相同,这就需要对传统BP算法进行改进,这种改进后的BP算法叫做基于时间的反向传播算法(BPTT):
为了保证RNN单元对应参数相同,BPTT提出了两点要求:
1.要求所有RNN单元结构的对应参数置相同初值。
2.在参数调整的过程中,要求同时调整参数。
即:
这两点要求都很好理解,而且都很好实现,只需使得RNN单元结构中的对应参数共享同一块内存即可。
在实际应用的过程中,人们发现RNN有一个问题,这个问题也很好理解,那就是:
距离当前节点越远的节点对当前节点处理影响越小。
这也就导致了,RNN虽然可以处理变长或者时序问题,但是无法建模长时间的依赖。
为了解决这个问题,提出了RNN的变种:LSTM和GRU,GRU是对LSTM的简化。
LSTM通过引入“门”结构,实现保留信息和选择信息功能。
在此基础上,进一步提出了双向LSTM(Bi-LSTM)和双向深度LSTM(Deep Bi-LSTM),可以建模双向依赖。
这在NLP领域是十分重要的,因为这意味着可以对上下文信息同时加以利用,而不仅仅只能利用上文信息。
在这里,不对LSTM和GRU进行详细地阐述,只需要知道LSTM和GRU可以建模长时间的依赖就可以啦,有兴趣的朋友们可以自行百度~
【六】RvNN
RNN适合处理能够在时序上展开的输入序列,然而对于结构展开的非线性关系表示能力差。
在NLP领域中,语句内部的句法关系通常是非线性的。
例如,NLP中常常用到的句法分析树(也称为短语结构树):
因此,引入递归神经网络RvNN。
RvNN的基本思想很简单:将处理问题在结构上分解为一系列相同的“单元”,单元的神经网络可以在结构上展开,且能沿展开方向传递信息。
与RNN的思想类似,只不过将“时序”转换成了“结构”。
RvNN的单元结构和信息传递方式是这样的:
其中底层是输入、顶层是输出。
由此构成的RvNN网络是这样的:
就句法分析树而言,RvNN的输出有两个:生成此种句法分析树的分数score,以及该种句法分析树的句嵌入(embedding)。
举个例子:“新桌子和椅子”
很明显,不同的句法结构所对应的句嵌入不同,分数也不同。
RvNN的学习过程与一般的神经网络差别不大,在这里不再赘述,有兴趣的朋友们可以自行查阅相关资料~
RvNN的参数训练过程与RNN类似,需要对每个单元结构的参数
W
,
U
W,U
W,U 同时进行调整。值得注意的是,RvNN的误差由打分部分误差和句嵌入(信息部分)误差共同构成。
其他方面与RNN类似,这里也不再赘述。
本文主要介绍了几种基本的神经网络:DNN、CNN、RNN、RvNN,以及网络训练过程中的基本方法:梯度下降法和反向传播算法(BP、BPTT)。
由于细节内容太过繁琐,所以有很多扩展内容无法全部进行介绍,比如LSTM模型、GRU模型、以及在RNN基础上大名鼎鼎的encoder-decoder架构。
对于encoder-decoder架构,将会在NLP部分进行介绍。
对这些内容感兴趣的朋友可以自行百度进行了解,同时欢迎私信进行沟通,共同进步~
如果文中有某些概念理解有误,欢迎各位大神批评指正。
谢谢!