Course 2:高级学习算法
课程简介
Adam 优化器、Batch Norm、Dropout、数据增强等实践。
一、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 的计算步骤:
- 计算 mini-batch 均值:μ_B = (1/m) Σ z_i
- 计算 mini-batch 方差:σ²_B = (1/m) Σ (z_i - μ_B)²
- 标准化:ẑ_i = (z_i - μ_B) / √(σ²_B + ε)
- 缩放和平移: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 的好处
- 允许使用更大的学习率,加速训练
- 减少对精心初始化的依赖
- 有轻微的正则化效果(每个 batch 的随机统计量引入噪声)
- 改善梯度流,有助于训练深层网络
三、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 为什么有效
- 防止特征共适应:神经元不能过度依赖其他特定神经元的输出
- 隐式模型集成:每次训练不同的子网络,测试时取所有子网络的平均
- 正则化效果:相当于在权重上施加了 L2 正则化
3.3 使用建议
- 输入层 keep_prob 接近 1(0.8-1.0)
- 隐藏层 keep_prob 取 0.5-0.8
- 输出层通常不使用 Dropout
- 验证集性能下降时增加 Dropout;欠拟合时减少或去掉 Dropout
四、数据增强
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
数据增强是几乎所有计算机视觉项目的标准配置。它不仅增加数据量,还提高模型对光照、角度、遮挡等变化的鲁棒性。
延伸阅读
- 📺 B 站播放列表:Machine Learning Specialization (2022) — 新版机器学习
- 📚 更多学习资源,请访问 deeplearning.ai 官网