配音

Course 1:深层神经网络

课程简介

从浅层到深层网络,理解激活函数选择、参数初始化、正则化等工程实践。

🎬 本课程视频:Deep Learning Specialization — 深度学习专项课程


一、深层神经网络概述

深层神经网络(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

这段代码展示了深层网络的完整实现。在实际项目中我们会使用深度学习框架,但理解底层计算对调试和优化至关重要。

延伸阅读