📚 课程目录

第12课:数据增强

📖 本课概述

数据是深度学习的燃料,数据增强是免费的燃料增长器。本课深入各种增强策略,从基础几何变换到高级混合方法。

🔄 一、为什么需要数据增强

更多数据 → 更好泛化 → 更少过拟合

数据增强:从现有数据生成"新"样本,增加数据多样性

📐 二、基础增强方法

2.1 几何变换

方法参数效果
随机翻转p=0.5水平/垂直镜像
随机旋转degrees=15角度变化
随机裁剪size=224位置变化
仿射变换shear=10形状变化

2.2 颜色变换

方法参数效果
颜色抖动brightness=0.2亮度变化
对比度contrast=0.2明暗对比
饱和度saturation=0.2颜色丰富度

2.3 高级增强:MixUp与CutMix

MixUp: x̃ = λxᵢ + (1-λ)xⱼ, ỹ = λyᵢ + (1-λ)yⱼ

CutMix: 将一张图的部分区域替换为另一张图

λ ~ Beta(α, α),通常α=1.0

2.4 PyTorch实现


import torch
import torchvision.transforms as T
import numpy as np

# 数据增强效果演示
print("=== 数据增强方法 ===")

# 模拟图像张量
img = torch.randn(3, 32, 32)
print(f"原始图像: shape={img.shape}, mean={img.mean():.4f}, std={img.std():.4f}")

# 基本变换
transforms_list = {
    "随机水平翻转": T.RandomHorizontalFlip(p=1.0),
    "随机垂直翻转": T.RandomVerticalFlip(p=1.0),
    "随机旋转10°": T.RandomRotation(10),
    "随机裁剪": T.RandomCrop(28),
    "颜色抖动": T.ColorJitter(brightness=0.5, contrast=0.5),
    "高斯模糊": T.GaussianBlur(3),
    "随机擦除": T.RandomErasing(p=1.0),
}

for name, transform in transforms_list.items():
    try:
        augmented = transform(img)
        diff = (augmented - img).abs().mean().item()
        print(f"  {name}: shape={list(augmented.shape)}, 与原图差异={diff:.4f}")
    except Exception as e:
        print(f"  {name}: 需要PIL图像输入 ({str(e)[:50]})")

# MixUp实现
def mixup_data(x, y, alpha=1.0):
    lam = np.random.beta(alpha, alpha) if alpha > 0 else 1
    batch_size = x.size(0)
    index = torch.randperm(batch_size)
    mixed_x = lam * x + (1 - lam) * x[index]
    y_a, y_b = y, y[index]
    return mixed_x, y_a, y_b, lam

# MixUp实验
X = torch.randn(32, 3, 32, 32)
y = torch.randint(0, 10, (32,))

mixed_X, y_a, y_b, lam = mixup_data(X, y, alpha=1.0)
print(f"\nMixUp: λ={lam:.4f}")
print(f"  原图与混合图差异: {(mixed_X - X).abs().mean():.4f}")

# CutMix实现
def cutmix_data(x, y, beta=1.0):
    lam = np.random.beta(beta, beta)
    rand_index = torch.randperm(x.size(0))
    bbx1, bby1, bbx2, bby2 = rand_bbox(x.size(), lam)
    x_cut = x.clone()
    x_cut[:, :, bbx1:bbx2, bby1:bby2] = x[rand_index, :, bbx1:bbx2, bby1:bby2]
    lam = 1 - ((bbx2 - bbx1) * (bby2 - bby1) / (x.size(-1) * x.size(-2)))
    return x_cut, y, y[rand_index], lam

def rand_bbox(size, lam):
    W = size[2]
    H = size[3]
    cut_rat = np.sqrt(1. - lam)
    cut_w = int(W * cut_rat)
    cut_h = int(H * cut_rat)
    cx = np.random.randint(W)
    cy = np.random.randint(H)
    bbx1 = np.clip(cx - cut_w // 2, 0, W)
    bby1 = np.clip(cy - cut_h // 2, 0, H)
    bbx2 = np.clip(cx + cut_w // 2, 0, W)
    bby2 = np.clip(cy + cut_h // 2, 0, H)
    return bbx1, bby1, bbx2, bby2

cut_X, y_a2, y_b2, lam2 = cutmix_data(X, y, beta=1.0)
print(f"CutMix: λ={lam2:.4f}")
print(f"  原图与CutMix图差异: {(cut_X - X).abs().mean():.4f}")

# 数据增强对训练的影响
print("\n=== 增强对训练的影响 ===")
torch.manual_seed(42)
X_train = torch.randn(200, 10)
y_train = (X_train[:, 0] + X_train[:, 1] > 0).long()

model = nn.Sequential(nn.Linear(10, 64), nn.ReLU(), nn.Linear(64, 2))
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
loss_fn = nn.CrossEntropyLoss()

for epoch in range(100):
    # 在线增强:给输入加噪声
    X_aug = X_train + torch.randn_like(X_train) * 0.1
    optimizer.zero_grad()
    loss = loss_fn(model(X_aug), y_train)
    loss.backward()
    optimizer.step()

acc = (model(X_train).argmax(1) == y_train).float().mean()
print(f"加噪声增强训练: acc={acc.item():.2%}")
🟢 运行结果 ✅验证通过 === Data Augmentation Demo === Original: shape=torch.Size([3, 32, 32]), mean=0.0089 MixUp: lambda=0.5084, diff=0.5195 CutMix: lambda=0.3398, diff=0.6973 Noise augmentation: acc=96.00%

🔬 深入拓展

核心要点回顾

本课的核心知识点构成了CNN学习的重要一环。让我们从更高维度审视这些知识之间的关系:

常见陷阱与最佳实践

⚠️ 初学者常犯的错误:

💡 最佳实践:

与前后课程的联系

深度学习是一个整体——每一课的知识都不是孤立的:

📖 延伸阅读

💡 继续深入的学习路径:

📝 练习

练习1:AutoAugment

实现自动增强策略搜索(简化版)。

练习2:增强强度实验

逐渐增加增强强度,观察对训练和验证精度的影响。

练习3:Test Time Augmentation

实现TTA,在测试时多次增强取平均,观察精度提升。

💡 数据增强策略

增强流水线设计

常见错误与解决方案

⚠️ 需要避免的典型错误:

  1. 不了解模型假设就盲目使用
  2. 没有建立基线就追求复杂方法
  3. 忽视数据质量和预处理
  4. 过度调参而不理解原理
  5. 只看训练指标忽略验证指标

性能优化建议

💡 提升模型性能的系统方法:

  1. 确保数据管道正确且高效
  2. 建立简单但正确的基线模型
  3. 分析基线的错误类型
  4. 针对性地改进(数据/模型/训练)
  5. 持续迭代,每步验证

🔬 深度拓展:从理论到实践

核心概念网络

理解本课内容需要将其置于更大的知识网络中。每个核心概念都不是孤立的,它们相互关联、相互支撑:

关键洞察与直觉

建立正确的直觉比记住公式更重要:

1. 维度直觉:高维空间中,数据分布与低维直觉截然不同(维度诅咒)

2. 信息瓶颈:神经网络逐层压缩信息,保留任务相关的、丢弃无关的

3. 流形假设:高维数据实际分布在低维流形上,学习即发现流形结构

4. 偏差-方差权衡:简单模型欠拟合(高偏差),复杂模型过拟合(高方差)

与其他课程的关联

本课作为CNN阶段的核心内容,与前后课程紧密关联:

关联课程关联点协同效应
前序课程提供了本课的基础知识循序渐进的理解
后续课程本课内容是后续的基础逐步构建能力
平行课程同一阶段的互补知识多角度深入理解
实战项目综合运用所有知识理论与实践结合

面试常见问题

💡 准备面试时,确保能回答以下问题:

  1. 用简单语言解释本课核心概念
  2. 画出关键算法/结构的流程图
  3. 比较不同方法的优缺点
  4. 举出实际应用场景
  5. 讨论常见误解和注意事项

进阶学习路径

掌握本课内容后,可以通过以下方式继续深入:

🔄

成就解锁:数据炼金师

数据增强是免费的提升——你已经掌握了这门手艺!