深度L层神经网络 (Deep L-layer neural network)
要理解深度神经网络,我们可以想象它就像是建筑的多层楼房。越多的层就意味着这座楼房越高,同样地,神经网络里有越多的隐藏层就意味着它越“深”。上面的图片很好地展示了不同“楼层”数量的神经网络模型,从简单的地面楼(逻辑回归)到拥有多层的大厦。
你可能会问,为什么我们不直接说有5层或者6层呢?这是因为在神经网络的命名规则中,我们通常不把输入层算作一层。所以,当我们说2层神经网络的时候,它实际上有一个输入层和一个隐藏层,然后是输出层。这个命名规则其实是为了方便,因为当我们谈论网络的“深度”时,我们真正关心的是隐藏层的数量。
现在,让我们深入研究一下一个4层神经网络的结构。想象一下,这个网络就像是一个4层的楼房。 L L L 代表楼的总层数,这里 L = 4 L=4 L=4。我们的输入层是底楼,记为第0层,而最顶层,也就是输出层,是第L层。每一层楼有不同数量的房间,这些“房间”在神经网络中就是神经元。第l层有 n [ l ] n[l] n[l] 个神经元,这里 l l l 的范围是从0到L。所以在这个模型中, n [ 0 ] = n x = 3 n[0] = nx = 3 n[0]=nx=3 意味着我们有三个输入特征,这三个特征就像是我们楼房的大门。而 n [ 1 ] = 5 n[1]=5 n[1]=5, n [ 2 ] = 5 n[2]=5 n[2]=5, n [ 3 ] = 3 n[3]=3 n[3]=3 和 n [ 4 ] = 1 n[4]=1 n[4]=1 则是随着楼层递增的房间数量。
每个房间都有灯光,这个“灯光”可以暗或亮,代表神经元的激活函数输出,我们用 a [ l ] a[l] a[l] 来表示它。权重 W [ l ] W[l] W[l] 就像是楼层之间的电梯,它决定了我们从一层到另一层时“灯光”的变化程度。
这样,不管你是神经网络的初学者,还是有经验的专家,都能很容易地理解这个复杂的结构了。
深度网络中的正向传播 (Forward Propagation in a Deep Network)
深层神经网络的正向传播可以被想象成一个复杂的信息高速公路,信息在各个层之间高速流动。为了更容易理解,我们还是用上面的4层神经网络作为例子来说明。
首先,对于单个样本:
-
在第1层(也就是底楼):
z [ 1 ] = W [ 1 ] x + b [ 1 ] = W [ 1 ] a [ 0 ] + b [ 1 ] z^{[1]} = W^{[1]}x + b^{[1]} = W^{[1]}a^{[0]} + b^{[1]} z[1]=W[1]x+b[1]=W[1]a[0]+b[1]
这里, a [ 0 ] a^{[0]} a[0] 就是输入特征,而 g [ 1 ] ( z [ 1 ] ) g^{[1]}(z^{[1]}) g[1](z[1]) 则是激活函数输出的值,我们可以表示为 a [ 1 ] a^{[1]} a[1]。 -
在第2层(第一个隐藏层):
z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] z^{[2]} = W^{[2]}a^{[1]} + b^{[2]} z[2]=W[2]a[1]+b[2]
同样地, a [ 2 ] = g [ 2 ] ( z [ 2 ] ) a^{[2]} = g^{[2]}(z^{[2]}) a[2]=g[2](z[2])。 -
在第3层(第二个隐藏层):
z [ 3 ] = W [ 3 ] a [ 2 ] + b [ 3 ] z^{[3]} = W^{[3]}a^{[2]} + b^{[3]} z[3]=W[3]a[2]+b[3]
并且, a [ 3 ] = g [ 3 ] ( z [ 3 ] ) a^{[3]} = g^{[3]}(z^{[3]}) a[3]=g[3](z[3])。 -
最后,在第4层(输出层):
z [ 4 ] = W [ 4 ] a [ 3 ] + b [ 4 ] z^{[4]} = W^{[4]}a^{[3]} + b^{[4]} z[4]=W[4]a[3]+b[4]
输出 a [ 4 ] = g [ 4 ] ( z [ 4 ] ) a^{[4]} = g^{[4]}(z^{[4]}) a[4]=g[4](z[4]) 就是神经网络预测的结果。
现在,假设我们不仅有一个样本,而是有整整m个样本。这时候,我们可以使用矩阵来表示所有样本的正向传播:
-
在第1层:
Z [ 1 ] = W [ 1 ] X + b [ 1 ] = W [ 1 ] A [ 0 ] + b [ 1 ] Z^{[1]} = W^{[1]}X + b^{[1]} = W^{[1]}A^{[0]} + b^{[1]} Z[1]=W[1]X+b[1]=W[1]A[0]+b[1]
这里, A [ 1 ] = g [ 1 ] ( Z [ 1 ] ) A^{[1]} = g^{[1]}(Z^{[1]}) A[1]=g[1](Z[1])。 -
在第2层:
Z [ 2 ] = W [ 2 ] A [ 1 ] + b [ 2 ] Z^{[2]} = W^{[2]}A^{[1]} + b^{[2]} Z[2]=W[2]A[1]+b[2]
并且, A [ 2 ] = g [ 2 ] ( Z [ 2 ] ) A^{[2]} = g^{[2]}(Z^{[2]}) A[2]=g[2](Z[2])。 -
在第3层:
Z [ 3 ] = W [ 3 ] A [ 2 ] + b [ 3 ] Z^{[3]} = W^{[3]}A^{[2]} + b^{[3]} Z[3]=W[3]A[2]+b[3]
然后, A [ 3 ] = g [ 3 ] ( Z [ 3 ] ) A^{[3]} = g^{[3]}(Z^{[3]}) A[3]=g[3](Z[3])。 -
最后,在第4层:
Z [ 4 ] = W [ 4 ] A [ 3 ] + b [ 4 ] Z^{[4]} = W^{[4]}A^{[3]} + b^{[4]} Z[4]=W[4]A[3]+b[4]
输出 A [ 4 ] = g [ 4 ] ( Z [ 4 ] ) A^{[4]} = g^{[4]}(Z^{[4]}) A[4]=g[4](Z[4]) 就是神经网络基于所有m个样本的预测结果。
简而言之,无论是单个样本还是多个样本,第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])
其中,
l
l
l 取值范围是1到L。
确保矩阵维度正确 (Getting your matrix dimensions right)
在设计神经网络时,确保各种参数和变量的维度正确是至关重要的。否则,你的代码可能会因为维度不匹配而出错。为了帮助大家更好地理解,我们将通过以下内容逐步解析维度的规律。
首先,考虑单个训练样本的情况:
-
输入 x x x 的维度是 ( n [ 0 ] , 1 ) (n^{[0]}, 1) (n[0],1),其中 n [ 0 ] n^{[0]} n[0] 表示输入层的特征数目。
-
对于每一层 l l l 的参数 W [ l ] W^{[l]} W[l] 和 b [ l ] b^{[l]} b[l],它们的维度如下:
W [ l ] : ( n [ l ] , n [ l − 1 ] ) W^{[l]}: (n^{[l]}, n^{[l-1]}) W[l]:(n[l],n[l−1])
b [ l ] : ( n [ l ] , 1 ) b^{[l]}: (n^{[l]}, 1) b[l]:(n[l],1)
其中, n [ l ] n^{[l]} n[l] 和 n [ l − 1 ] n^{[l-1]} n[l−1] 分别代表第 l l l 层和 l − 1 l-1 l−1 层的神经元数目。
再来看看正向传播中的
z
[
l
]
z^{[l]}
z[l] 和
a
[
l
]
a^{[l]}
a[l],它们的维度如下:
z
[
l
]
:
(
n
[
l
]
,
1
)
z^{[l]}: (n^{[l]}, 1)
z[l]:(n[l],1)
a
[
l
]
:
(
n
[
l
]
,
1
)
a^{[l]}: (n^{[l]}, 1)
a[l]:(n[l],1)
它们的维度是一样的,这意味着 z [ l ] z^{[l]} z[l] 与 a [ l ] a^{[l]} a[l] 可以直接进行计算。
好的,现在我们来看反向传播的部分。你会发现
d
W
[
l
]
dW^{[l]}
dW[l] 和
d
b
[
l
]
db^{[l]}
db[l] 的维度与
W
[
l
]
W^{[l]}
W[l] 和
b
[
l
]
b^{[l]}
b[l] 的维度完全相同:
d
W
[
l
]
:
(
n
[
l
]
,
n
[
l
−
1
]
)
dW^{[l]}: (n^{[l]}, n^{[l-1]})
dW[l]:(n[l],n[l−1])
d
b
[
l
]
:
(
n
[
l
]
,
1
)
db^{[l]}: (n^{[l]}, 1)
db[l]:(n[l],1)
这其实很直观,因为我们在更新参数时需要确保 d W [ l ] dW^{[l]} dW[l] 和 W [ l ] W^{[l]} W[l] 有相同的维度, d b [ l ] db^{[l]} db[l] 和 b [ l ] b^{[l]} b[l] 也是如此。
现在,假设我们有 m m m 个训练样本。此时,输入矩阵 X X X 的维度就是 ( n [ 0 ] , m ) (n^{[0]}, m) (n[0],m)。但值得注意的是,不论样本数量是多少, W [ l ] W^{[l]} W[l] 和 b [ l ] b^{[l]} b[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] 时,因为 Python 的广播机制, b [ l ] b^{[l]} b[l] 会被看作 ( n [ l ] , m ) (n^{[l]}, m) (n[l],m) 维度的矩阵进行运算,且其每一列都相同。
最后,当我们有多个训练样本时,
Z
[
l
]
Z^{[l]}
Z[l] 和
A
[
l
]
A^{[l]}
A[l] 的维度都会变为:
Z
[
l
]
:
(
n
[
l
]
,
m
)
Z^{[l]}: (n^{[l]}, m)
Z[l]:(n[l],m)
A
[
l
]
:
(
n
[
l
]
,
m
)
A^{[l]}: (n^{[l]}, m)
A[l]:(n[l],m)
这些维度知识点非常重要,因为它们帮助我们在设计神经网络时确保所有的计算都能够正确进行。
4. 为什么选择深度表示? (Why deep representations?)
说到神经网络,我们经常听说它的强大功能,这其中很大一部分功劳归于它的"深度"结构。那么,为什么深层的神经网络会如此出色呢? 通过一些具体例子,我们来深入探讨一下。
想象一下,你正在看一张人脸图片。在第一层神经网络中,我们只是简单地识别出这张图片中的边缘和轮廓。往下一层看,神经网络开始识别出眼睛、鼻子和嘴巴等脸部的基本特征。再深入一些,我们可以看到神经网络已经能够识别出整张脸。也就是说,从简单的边缘,到局部特征,再到整体脸部,随着网络深度的增加,识别的特征越来越复杂。这正是深层网络的魔力所在:能够从简单特征构建出复杂特征。
类似地,在语音识别中,开始可能只是识别简单的音调,但随着网络深度的增加,我们可以识别到音素、单词,甚至整个短句。这个特点告诉我们,随着网络的加深,从简单到复杂的特征都可以被有效地学习和提取。
除了从功能角度看深层网络的优势,深度神经网络还有另一个明显的优点:效率。想象一下,我们有一个任务,用电路计算逻辑输出:
y
=
x
1
⊕
x
2
⊕
x
3
⊕
⋯
⊕
x
n
y = x_1 \oplus x_2 \oplus x_3 \oplus \cdots \oplus x_n
y=x1⊕x2⊕x3⊕⋯⊕xn
其中,
⊕
\oplus
⊕ 是异或操作。如果我们使用深层网络,每一层只进行前一层的两个输入的异或运算,最终的结果会是:
1
+
2
+
⋯
+
2
log
2
(
n
)
−
1
=
2
log
2
(
n
)
−
1
=
n
−
1
1+2+\cdots+2^{\log_2(n)-1} = 2^{\log_2(n)}-1 = n-1
1+2+⋯+2log2(n)−1=2log2(n)−1=n−1
这意味着,对于
n
n
n个输入,深层网络只需要
n
−
1
n-1
n−1个神经元。相比之下,浅层网络可能需要指数级的神经元数量来实现相同的功能。
不过,尽管深度学习非常有吸引力,还是建议在实际问题上,先尝试简单的模型。只有当简单模型不能满足需求时,再考虑使用更复杂、更深层的模型。
4. 为什么选择深度表示? (Why deep representations?)
说到神经网络,我们经常听说它的强大功能,这其中很大一部分功劳归于它的"深度"结构。那么,为什么深层的神经网络会如此出色呢? 通过一些具体例子,我们来深入探讨一下。
想象一下,你正在看一张人脸图片。在第一层神经网络中,我们只是简单地识别出这张图片中的边缘和轮廓。往下一层看,神经网络开始识别出眼睛、鼻子和嘴巴等脸部的基本特征。再深入一些,我们可以看到神经网络已经能够识别出整张脸。也就是说,从简单的边缘,到局部特征,再到整体脸部,随着网络深度的增加,识别的特征越来越复杂。这正是深层网络的魔力所在:能够从简单特征构建出复杂特征。
类似地,在语音识别中,开始可能只是识别简单的音调,但随着网络深度的增加,我们可以识别到音素、单词,甚至整个短句。这个特点告诉我们,随着网络的加深,从简单到复杂的特征都可以被有效地学习和提取。
除了从功能角度看深层网络的优势,深度神经网络还有另一个明显的优点:效率。想象一下,我们有一个任务,用电路计算逻辑输出:
y
=
x
1
⊕
x
2
⊕
x
3
⊕
⋯
⊕
x
n
y = x_1 \oplus x_2 \oplus x_3 \oplus \cdots \oplus x_n
y=x1⊕x2⊕x3⊕⋯⊕xn
其中,
⊕
\oplus
⊕ 是异或操作。如果我们使用深层网络,每一层只进行前一层的两个输入的异或运算,最终的结果会是:
1
+
2
+
⋯
+
2
log
2
(
n
)
−
1
=
2
log
2
(
n
)
−
1
=
n
−
1
1+2+\cdots+2^{\log_2(n)-1} = 2^{\log_2(n)}-1 = n-1
1+2+⋯+2log2(n)−1=2log2(n)−1=n−1
这意味着,对于
n
n
n个输入,深层网络只需要
n
−
1
n-1
n−1个神经元。相比之下,浅层网络可能需要指数级的神经元数量来实现相同的功能。
不过,尽管深度学习非常有吸引力,还是建议在实际问题上,先尝试简单的模型。只有当简单模型不能满足需求时,再考虑使用更复杂、更深层的模型。
5. 深度神经网络的构建块 (Building Blocks of Deep Neural Networks)
为了更清晰地理解深度学习,我们使用流程块图来描述神经网络中的正向传播和反向传播。想象一下,你正在建一座大楼,每一层楼都依赖于下面的楼层。这些楼层类似于神经网络中的层。
对于第 l l l层,正向传播是这样的:
- 输入: a [ l − 1 ] a^{[l-1]} a[l−1]
- 输出: a [ l ] a^{[l]} a[l]
- 参数: W [ l ] , b [ l ] W^{[l]}, b^{[l]} W[l],b[l]
- 缓存变量: z [ l ] z^{[l]} z[l]
反向传播则是:
- 输入: d a [ l ] da^{[l]} da[l]
- 输出: d a [ l − 1 ] , d W [ l ] , d b [ l ] da^{[l-1]}, dW^{[l]}, db^{[l]} da[l−1],dW[l],db[l]
- 参数: W [ l ] , b [ l ] W^{[l]}, b^{[l]} W[l],b[l]
这就像是一座大楼的蓝图。不同的层有不同的输入和输出,它们都彼此连接。
6. 正向和反向传播 (Forward and Backward Propagation)
让我们深入研究每层如何工作。正向传播就像是将石头从山顶滚下来,每一层都会给石头增加一些速度和方向。
正向传播的表达式为:
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])
对于
m
m
m个训练样本,我们可以将其向量化:
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])
接下来是反向传播,这就像是石头滚回山顶。每一层都会影响其速度和方向。
反向传播的表达式为:
d
z
[
l
]
=
d
a
[
l
]
∗
g
[
l
]
′
(
z
[
l
]
)
dz^{[l]} = da^{[l]} * g^{[l]\prime}(z^{[l]})
dz[l]=da[l]∗g[l]′(z[l])
d
W
[
l
]
=
d
z
[
l
]
⋅
a
[
l
−
1
]
dW^{[l]} = dz^{[l]} \cdot 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} \cdot dz^{[l]}
da[l−1]=W[l]T⋅dz[l]
其中最后一个关系表示了不同层之间的连接。
对于
m
m
m个训练样本,我们也可以将其向量化:
d
Z
[
l
]
=
d
A
[
l
]
∗
g
[
l
]
′
(
Z
[
l
]
)
dZ^{[l]} = dA^{[l]} * g^{[l]\prime}(Z^{[l]})
dZ[l]=dA[l]∗g[l]′(Z[l])
d
W
[
l
]
=
1
m
d
Z
[
l
]
⋅
A
[
l
−
1
]
T
dW^{[l]} = \frac{1}{m} dZ^{[l]} \cdot A^{[l-1]T}
dW[l]=m1dZ[l]⋅A[l−1]T
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]} = \frac{1}{m} np.sum(dZ^{[l]}, axis=1, keepdims=True)
db[l]=m1np.sum(dZ[l],axis=1,keepdims=True)
d
A
[
l
−
1
]
=
W
[
l
]
T
⋅
d
Z
[
l
]
dA^{[l-1]} = W^{[l]T} \cdot dZ^{[l]}
dA[l−1]=W[l]T⋅dZ[l]
7. 参数与超参数 (Parameters vs Hyperparameters)
在这部分,我们将探讨神经网络的两个关键组件:参数和超参数。想象一下,你正在建造一个房子。参数就像是你的砖块和木头,而超参数就像是你的蓝图。
神经网络中的参数是: W [ l ] W^{[l]} W[l] 和 b [ l ] b^{[l]} b[l],它们是神经网络学习的结果。而超参数包括:学习速率 α \alpha α、训练迭代次数 N N N、神经网络层数 L L L、每层的神经元数 n [ l ] n^{[l]} n[l] 和激活函数 g ( z ) g(z) g(z)。超参数决定了参数的形态和值。
选择最佳的超参数往往需要经验和实验。这个过程类似于建房子时选择最佳的蓝图。通常的方法是尝试不同的超参数组合,看看哪个效果最好。
8. 神经网络与大脑有什么关系? (What does this have to do with the brain?)
我们常常听说神经网络是受大脑启发的,但它们之间真的有多相似呢?神经网络,特别是深度神经网络,主要分为两个过程:正向传播和反向传播。每个神经元在神经网络中都通过一个激活函数来工作,这与感知机模型非常相似。这样的模型与我们大脑中的神经元有许多相似之处。它可以看作是对大脑神经元的简化表示。例如,大脑神经元由树突、细胞体和轴突组成。其中,树突接收信号(这与神经网络中的输入类似),细胞体处理这些信号(类似于神经网络中的激活函数),然后轴突将处理后的信号传递给下一个神经元(类似于神经网络中的输出)。
但是,我们必须记住,真实的大脑神经元比这种简化模型要复杂得多。而且,我们现在还不完全明白大脑是如何学习的。它是否也使用了类似于反向传播和梯度下降的机制?可能会更复杂。不过,这提供了一个有趣的方向,生物学家和神经科学家可以进一步研究。而我们作为人工智能研究者,也许可以从中找到新的灵感,为神经网络模型提供更强大的学习策略!
9. 总结 (Summary)
这一课我们详细探讨了深度神经网络,它基于我们在之前学习的浅层神经网络。首先,我们明确了构建神经网络时常用的标准符号。然后,通过流程图,我们详细推导了正向和反向传播的具体步骤。为什么深度神经网络比浅层神经网络更有优势?我们从特征提取的复杂性和计算效率的角度进行了探讨。此外,我们还讨论了超参数的重要性,并解释了它与常规参数之间的区别。最后,我们简要探讨了神经网络与人类大脑的相似之处,指出虽然它们之间有一些相似性,但神经网络只是一个简化版本。