深层神经网络技术总结
虽然之前说写博客记录下学习过程, 但写了一篇就停了, 过了一个多月还是重新开始吧
1 简介
单隐层的神经网络可以完成一些任务,但是有些函数或任务只有非常深的神经网络能学会,而更浅的模型则办不到。对于单隐层的神经网络,我们可以称其为浅层神经网络,如下图所示,X为输入层,中间的三个节点为隐藏层,后面的一个节点为输出层。
而浅层和深度神经网络的浅与深仅仅是指一种程度。下图则为深度神经网络,其隐藏层数分别为2层和5层。
那么深度神经网络究竟是在做什么?深度神经网络的这许多隐藏层中,较早的前几层能学习一些低层次的简单特征,等到后几层,就能把简单的特征结合起来,去探测更加复杂的东西。比如运行语音识别,首先识别音频当中的单词,单词再组合起来就能识别词组,再到完整的句子。在图像识别中,我们所计算的之前的几层,也就是相对简单的输入函数,比如图像单元的边缘什么的。到网络中的深层时,就可以探测各个部位,然后组合成为一个完整的图片。
2 技术原理
这里依旧使用基于逻辑回归的神经网络做介绍,为了完成猫图像识别的任务,首先在输入层和之前的单隐层逻辑回归一致,需要将图像的RGB像素强度值转为一维的矩阵,如下图:
不过在深度神经网络中,是通过多隐藏层的提取,然后迭代,提高准确度,最后输出预测值,根据预测结果y为1还是0,也就是预测图片中是否有猫。
2.1 流程
深度神经网络和单隐层神经网络的流程基本一致,主要还是为4个步骤:(1)提取图片特征值,作为输入,(2)在隐藏层计算线性回归,并通过非线性激活函数relu使得神经网络具有非线性拟合能力,(3)计算损失函数并通过梯度下降优化,(4)输出预测值。
2.1.1 前向传播
在L层神经网络中,我们将第一个隐藏层编号为1,依次到L。前向传播,输入 a [ l − 1 ] a^{[l-1]} a[l−1],输出的是 a [ l ] a^{[l]} a[l],缓存是 z [ l ] z^{[l]} z[l];代码实现时我们可以将 w [ l ] w^{[l]} w[l]和 b [ l ] b^{[l]} b[l]存入缓存中,这样可以更方便的在不同环节中调用函数。假设有个为L层的神经网络,
在第一个隐藏层,前向传播需要计算
z
[
1
]
=
w
[
1
]
x
+
b
[
1
]
,
a
[
1
]
=
g
[
1
]
(
z
[
1
]
)
z^{[1]}=w^{[1]}x+b^{[1]},a^{[1]}=g^{[1]}(z^{[1]})
z[1]=w[1]x+b[1],a[1]=g[1](z[1]):,其中
x
x
x可以看做为
a
[
0
]
a^{[0]}
a[0];
在第二个隐藏层,需要计算
z
[
2
]
=
w
[
2
]
x
+
b
[
2
]
,
a
[
2
]
=
g
[
2
]
(
z
[
2
]
)
z^{[2]}=w^{[2]}x+b^{[2]},a^{[2]}=g^{[2]}(z^{[2]})
z[2]=w[2]x+b[2],a[2]=g[2](z[2]);
…以此类推,前向传播可以归纳为多次迭代结果:
在第L层时,我们需要计算的是:
z
[
l
]
=
w
[
l
]
x
+
b
[
l
]
,
a
[
l
]
=
g
[
l
]
(
z
[
l
]
)
z^{[l]}=w^{[l]}x+b^{[l]},a^{[l]}=g^{[l]}(z^{[l]})
z[l]=w[l]x+b[l],a[l]=g[l](z[l]);
若以向量形式表达,前向传播的公式可以写为:
Z
[
l
]
=
W
[
l
]
A
[
l
−
1
]
+
b
[
l
]
Z^{[l]}=W^{[l]}A^{[l-1]}+b^{[l]}
Z[l]=W[l]A[l−1]+b[l]
A
[
l
]
=
g
[
l
]
(
Z
[
l
]
)
A^{[l]}=g^{[l]}(Z^{[l]})
A[l]=g[l](Z[l]);
前向传播需要输入层传入数据
A
[
0
]
A^{[0]}
A[0]也就是
X
X
X, 来初始化第一层的输入值;初始化的是第一层的输入值。
a
[
0
]
a^{[0]}
a[0]对应于一个训练样本的输入特征,而
A
[
0
]
A^{[0]}
A[0]对应于一整个训练样本的输入特征,所以这就是这条链的第一个前向函数的输入,重复这个步骤就可以从左到右计算前向传播。
2.1.2 激活函数
所谓激活函数就是对各个路径的输入求和之后进一步增强的函数。普遍使用的激活函数为以下几个:
其中sigmoid函数和tanh函数在输入值偏大或偏小的情况下,容易出现趋于饱和的情况,即梯度趋于0,这对于后续的梯度下降更新参数是十分不好的,所以在此选择的是Relu函数作为前L-1层的激活函数,而由于此神经网络的作用为预测图片是否是猫,在做一个二元分类,因此在最后的L层输出概率时,适合用sigmoid函数,因为其输出范围为[0,1]。
2.1.3 反向传播
根据逻辑回归的反向传播公式,结合前向传播公式,可以推导出L层神经网络的反向传播公式如下:
d
z
[
l
]
=
d
a
[
l
]
g
[
l
]
′
(
z
[
l
]
)
dz^{[l]}=da^{[l]}g^{[l]'}(z^{[l]})
dz[l]=da[l]g[l]′(z[l])
d
w
[
l
]
=
d
z
[
l
]
a
[
l
−
1
]
dw^{[l]}=dz^{[l]}a^{[l-1]}
dw[l]=dz[l]a[l−1]
d
b
[
l
]
=
d
z
[
l
]
db^{[l]}=dz^{[l]}
db[l]=dz[l]
d
a
[
l
−
1
]
=
w
[
l
]
T
d
z
[
l
]
da^{[l-1]}=w^{[l]T}dz^{[l]}
da[l−1]=w[l]Tdz[l]
将式子带入后可得,
d
z
[
l
+
1
]
=
d
w
[
l
]
T
d
z
[
l
+
1
]
g
[
l
]
′
(
z
[
l
]
)
dz^{[l+1]}=dw^{[l]T}dz^{[l+1]}g^{[l]'}(z^{[l]})
dz[l+1]=dw[l]Tdz[l+1]g[l]′(z[l])
则改成便于代码实现的向量形式为:
d
Z
[
l
]
=
d
A
[
l
]
g
[
l
]
′
(
Z
[
l
]
)
dZ^{[l]}=dA^{[l]}g^{[l]'}(Z^{[l]})
dZ[l]=dA[l]g[l]′(Z[l])
d
W
[
l
]
=
(
1
/
m
)
∗
d
Z
[
l
]
A
[
l
−
1
]
dW^{[l]}=(1/m)*dZ^{[l]}A^{[l-1]}
dW[l]=(1/m)∗dZ[l]A[l−1]
d
b
[
l
]
=
(
1
/
m
)
∗
n
p
.
s
u
m
(
d
Z
[
l
]
,
a
x
i
s
=
1
,
k
e
e
p
d
i
m
s
=
T
r
u
e
)
db^{[l]}=(1/m)*np.sum(dZ^{[l]},axis=1, keepdims=True)
db[l]=(1/m)∗np.sum(dZ[l],axis=1,keepdims=True)
d
A
[
l
−
1
]
=
W
[
l
]
T
d
Z
[
l
]
dA^{[l-1]}=W^{[l]T}dZ^{[l]}
dA[l−1]=W[l]TdZ[l]
2.1.4 损失函数和梯度下降
由于依旧是基于逻辑回归的神经网络,损失函数和之前总结的一样,为
L
(
y
^
,
y
)
L(\hat{y},y)
L(y^,y)
L
(
y
^
,
y
)
=
−
y
l
o
g
(
y
^
−
(
1
−
y
)
l
o
g
(
1
−
y
)
L(\hat{y},y)=-ylog(\hat{y}-(1-y)log(1-y)
L(y^,y)=−ylog(y^−(1−y)log(1−y)
对于梯度下降参数的更新,公式也为
w
[
l
]
=
w
[
l
]
−
α
d
w
[
l
]
w^{[l]}=w^{[l]}-{\alpha}dw^{[l]}
w[l]=w[l]−αdw[l],
b
[
l
]
=
b
[
l
]
−
α
d
b
[
l
]
.
b^{[l]}=b^{[l]}-{\alpha}db^{[l]}.
b[l]=b[l]−αdb[l].
其余内容便不再赘述。
3. 总结
(1)深度神经网络中,在反向传播时,要注意参数,有的是使用前一层的参数,通过归纳总结的话,可以得出适用的迭代公式;
(2)逻辑回归的深度神经网络,本质上和单层是一致的,前向和后项传播的公式需要多推导牢记;
(3)深层的网络隐藏单元数量相对较少,隐藏层数目较多,如果浅层的网络想要达到同样的计算结果则需要指数级增长的单元数量才能达到。
(4)反向传播时,由于最后一层激活函数和前L-1层不同,需要分开计算;
(5)在实现神经网络时,注意参数是否正确,这次实现时,有个地方参数写错了,排查了许久才找到错误。