Course 1:深层神经网络
课程简介
从浅层到深层网络,理解激活函数选择、参数初始化、正则化等工程实践。
一、深层神经网络概述
深层神经网络(DNN)是指包含多个隐藏层的神经网络。与浅层网络相比,深层网络能够学习到更抽象和复杂的特征表示。
1.1 为什么需要深层网络
以人脸识别为例,网络的分层处理过程是:
- 第一层:检测边缘和纹理(水平边缘、垂直边缘)
- 第二层:组合边缘检测更复杂的形状(眼睛、鼻子)
- 第三层:组合局部特征检测完整的面部特征
- 更深层:检测完整的人脸
这种层次化特征学习是深层网络的核心优势。每一层都在前一层的基础上构建更高级的表示。
理论上,单隐藏层神经网络可以逼近任意连续函数(万能逼近定理),但实践中深层结构更有效——它用更少的参数达到更好的泛化性能。
1.2 深层网络的前向传播
对于 L 层网络,前向传播通用公式:
$$Z^{[l]} = W^{[l]} A^{[l-1]} + b^{[l]}$$
$$A^{[l]} = g^{[l]}(Z^{[l]})$$
其中 $l=1,...,L$,$A^{[0]}=X$。实现时需要缓存每层的 $Z^{[l]}$、$A^{[l]}$、$W^{[l]}$、$b^{[l]}$。
1.3 反向传播通用公式
对于第 l 层:
$$dZ^{[l]} = dA^{[l]} \odot g^{[l]'}(Z^{[l]})$$
$$dW^{[l]} = \frac{1}{m} dZ^{[l]} A^{[l-1]T}$$
$$db^{[l]} = \frac{1}{m} \sum dZ^{[l]}$$
$$dA^{[l-1]} = W^{[l]T} dZ^{[l]}$$
这些公式是反向传播最核心的四个公式。误差从输出层逐层反向传播。
1.4 矩阵维度检查
第 l 层的维度:
- $W^{[l]}$: $(n^{[l]}, n^{[l-1]})$ —— 当前层神经元数 × 上一层神经元数
- $b^{[l]}$: $(n^{[l]}, 1)$
- $Z^{[l]}, A^{[l]}$: $(n^{[l]}, m)$
- $dW^{[l]}$: 与 $W^{[l]}$ 同维度
- $db^{[l]}$: 与 $b^{[l]}$ 同维度
1.5 激活函数
Sigmoid:输出(0,1),适合二分类输出层。缺点:饱和区梯度几乎为零,不以零为中心。
Tanh:输出(-1,1),均值为零,收敛通常快于Sigmoid。同样有梯度消失问题。
ReLU:$\max(0,z)$,正区间梯度恒为1,缓解梯度消失。计算简单。缺点:负区间梯度为0,可能导致神经元"死亡"。
Leaky ReLU:$\max(0.01z, z)$,负区间有微小梯度。
1.6 参数初始化
零初始化:所有神经元学到的特征永远相同(对称性问题)
随机初始化:$W = \text{np.random.randn}(n_h, n_x) \times 0.01$
He初始化(针对ReLU):$W = \text{np.random.randn}(n^{[l]}, n^{[l-1]}) \times \sqrt{2/n^{[l-1]}}$
Xavier初始化(针对Tanh):$W = \text{np.random.randn}(n^{[l]}, n^{[l-1]}) \times \sqrt{1/n^{[l-1]}}$
1.7 梯度消失与梯度爆炸
梯度消失:浅层梯度趋近于0,参数几乎不更新。原因:激活函数饱和区梯度<1,连乘后指数衰减。
梯度爆炸:浅层梯度极大,训练不稳定。原因:权重初始化过大。
考虑一个简化线性网络:$y = W^{[L]}W^{[L-1]}\cdots W^{[1]}x$。权重都>1则爆炸,都<1则消失。
1.8 完整实现
def initialize_parameters_deep(layer_dims):
parameters = {}
L = len(layer_dims)
for l in range(1, L):
parameters['W'+str(l)] = np.random.randn(
layer_dims[l], layer_dims[l-1]) * np.sqrt(2.0/layer_dims[l-1])
parameters['b'+str(l)] = np.zeros((layer_dims[l], 1))
return parameters
def L_model_forward(X, parameters):
caches = []
A = X
L = len(parameters) // 2
for l in range(1, L):
A_prev = A
Z = np.dot(parameters['W'+str(l)], A_prev) + parameters['b'+str(l)]
A = np.maximum(0, Z)
caches.append((Z, A_prev, parameters['W'+str(l)], parameters['b'+str(l)]))
# 输出层用Sigmoid
W, b = parameters['W'+str(L)], parameters['b'+str(L)]
Z = np.dot(W, A) + b
AL = 1/(1+np.exp(-Z))
caches.append((Z, A, W, b))
return AL, caches
def L_model_backward(AL, Y, caches):
grads = {}
L = len(caches)
m = AL.shape[1]
Y = Y.reshape(AL.shape)
# 输出层
dZ = AL - Y
grads['dW'+str(L)] = 1/m * np.dot(dZ, caches[L-1][1].T)
grads['db'+str(L)] = 1/m * np.sum(dZ, axis=1, keepdims=True)
# 隐藏层
for l in reversed(range(L-1)):
Z, A_prev, W, _ = caches[l]
dA = np.dot(caches[l+1][2].T, dZ)
dZ = np.array(dA, copy=True)
dZ[Z <= 0] = 0
grads['dW'+str(l+1)] = 1/m * np.dot(dZ, A_prev.T)
grads['db'+str(l+1)] = 1/m * np.sum(dZ, axis=1, keepdims=True)
return grads
这段代码展示了深层网络的完整实现。在实际项目中我们会使用深度学习框架,但理解底层计算对调试和优化至关重要。
延伸阅读
- 📺 B 站播放列表:Deep Learning Specialization — 深度学习专项课程
- 📚 更多学习资源,请访问 deeplearning.ai 官网