配音

Course 2:高级学习算法

课程简介

Adam 优化器、Batch Norm、Dropout、数据增强等实践。

🎬 本课程视频:Machine Learning Specialization (2022) — 新版机器学习


一、Adam 优化器

Adam(Adaptive Moment Estimation)是目前深度学习中最流行的优化器。它结合了 Momentum 和 RMSprop 的优点,既能平滑梯度方向,又能为每个参数自适应调整学习率。

1.1 算法原理

Adam 维护两个指数加权移动平均:一阶矩(梯度均值)和二阶矩(梯度平方均值)。

$$v_t = \beta_1 v_{t-1} + (1 - \beta_1) g_t$$
$$s_t = \beta_2 s_{t-1} + (1 - \beta_2) g_t^2$$

其中 g_t 是当前时间步的梯度,β₁ 通常取 0.9,β₂ 通常取 0.999。

由于 v₀ 和 s₀ 初始化为 0,早期估计会偏小,需要进行偏差修正:

$$\hat{v}_t = \frac{v_t}{1 - \beta_1^t}, \quad \hat{s}_t = \frac{s_t}{1 - \beta_2^t}$$

参数更新:

$$\theta_t = \theta_{t-1} - \alpha \frac{\hat{v}_t}{\sqrt{\hat{s}_t} + \epsilon}$$

其中 α 是学习率(默认 0.001),ε = 1e-8 防止除以零。

1.2 Adam 的优势

1.3 使用建议

import tensorflow as tf

# 基本用法
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')

# 自定义学习率
model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
    loss='categorical_crossentropy'
)

# 学习率衰减
lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate=0.001,
    decay_steps=10000,
    decay_rate=0.9
)
optimizer = tf.keras.optimizers.Adam(learning_rate=lr_schedule)

二、Batch Normalization

2.1 解决的问题

深度网络训练中,每层输入的分布会随着前层参数更新而变化——这称为内部协变量偏移(Internal Covariate Shift)。这种分布变化迫使每层不断适应新的输入分布,拖慢训练速度。

2.2 Batch Normalization 算法

给定 mini-batch B = {z₁, ..., zₘ},BN 的计算步骤:

  1. 计算 mini-batch 均值:μ_B = (1/m) Σ z_i
  2. 计算 mini-batch 方差:σ²_B = (1/m) Σ (z_i - μ_B)²
  3. 标准化:ẑ_i = (z_i - μ_B) / √(σ²_B + ε)
  4. 缩放和平移:z̃_i = γ ẑ_i + β

其中 γ(缩放参数)和 β(偏移参数)是可学习的,它们让网络能够决定标准化后的最佳分布。

2.3 BN 的位置

BN 通常放在线性变换之后、激活函数之前:
Z = WX + b
Z_norm = BatchNorm(Z)
A = ReLU(Z_norm)

2.4 训练与测试的差异

训练时:每个 mini-batch 独立计算均值和方差。
测试时:使用训练过程中所有 mini-batch 的均值和方差的移动平均。

model = tf.keras.Sequential([
    layers.Dense(256),
    layers.BatchNormalization(),  # 批归一化
    layers.ReLU(),
    layers.Dropout(0.3),
    layers.Dense(128),
    layers.BatchNormalization(),
    layers.ReLU(),
    layers.Dense(10, activation='softmax')
])

2.5 BN 的好处

三、Dropout 正则化

3.1 原理

Dropout 在每次训练迭代中随机丢弃(置零)一部分神经元。丢弃比例由 keep_prob 参数控制。

# Dropout 的 NumPy 实现
def dropout_forward(A, keep_prob=0.8):
    D = np.random.rand(*A.shape) < keep_prob
    A = A * D            # 丢弃神经元
    A = A / keep_prob    # 反向 Dropout 缩放
    return A, D

反向 Dropout 在训练时缩放激活值,使得测试时不需要任何特殊处理。

3.2 Dropout 为什么有效

3.3 使用建议

四、数据增强

4.1 为什么需要数据增强

深度网络需要大量标注数据。数据增强通过对现有数据进行变换生成新的训练样本,有效扩充数据集规模。

4.2 图像数据增强

# Keras 中的数据增强
data_augmentation = tf.keras.Sequential([
    layers.RandomFlip("horizontal"),                 # 水平翻转
    layers.RandomRotation(0.1),                      # 随机旋转 ±10%
    layers.RandomZoom(0.1),                         # 随机缩放
    layers.RandomContrast(0.1),                     # 随机对比度
])

# 在模型中使用
model = tf.keras.Sequential([
    layers.Input(shape=(224, 224, 3)),
    data_augmentation,                              # 训练时自动增强
    layers.Rescaling(1./255),
    # ... 主干网络 ...
])

4.3 常见增强方法

几何变换:翻转、旋转、裁剪、缩放、平移
颜色变换:亮度调整、对比度调整、饱和度调整、色相偏移
噪声注入:高斯噪声、椒盐噪声
混合方法:MixUp、CutMix、CutOut

数据增强是几乎所有计算机视觉项目的标准配置。它不仅增加数据量,还提高模型对光照、角度、遮挡等变化的鲁棒性。

延伸阅读