CNN卷积神经网络入门:从数学原理到PyTorch实战

1次阅读
没有评论

共计 2059 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

为什么需要 CNN?

传统全连接网络处理图像时,参数量会随分辨率暴增。对于一个 28×28 的 MNIST 图像:

  • 全连接层输入维度:28×28=784
  • 假设隐藏层 500 节点,仅第一层参数就达 784×500=392,000 个

而同样情况下,使用 3×3 卷积核、32 个滤波器的 CNN 层参数仅 32×(3×3+1)=320 个(+ 1 为偏置项)。这种局部连接和权值共享特性,使 CNN 特别适合处理高维空间数据。

卷积操作的本质

  1. 数学表达:离散卷积运算可表示为
    $$(I * K)(i,j) = \sum_{m}\sum_{n} I(i+m,j+n)K(m,n)$$
    其中 $I$ 是输入矩阵,$K$ 是卷积核

  2. 可视化理解:

  3. 想象一个滑动窗口在图像上逐像素移动
  4. 每次窗口内进行元素乘加运算
  5. 最终得到特征响应图(feature map)

  6. 关键参数:

  7. Padding:在边缘补零控制输出尺寸
  8. Stride:滑动步长影响下采样率

CNN 卷积神经网络入门:从数学原理到 PyTorch 实战

PyTorch 实战 MNIST 分类

模型定义

import torch
import torch.nn as nn

model = nn.Sequential(
    # 卷积层 1:输入 1 通道,输出 32 通道,3x3 卷积核
    nn.Conv2d(1, 32, 3, padding=1),  
    nn.ReLU(),
    nn.MaxPool2d(2),  # 2x2 最大池化

    # 卷积层 2:32→64 通道
    nn.Conv2d(32, 64, 3, padding=1),
    nn.ReLU(),
    nn.MaxPool2d(2),

    # 展平后接全连接层
    nn.Flatten(),
    nn.Linear(64*7*7, 128),  # MNIST 经过两次池化后尺寸 7x7
    nn.ReLU(),
    nn.Linear(128, 10)
)

训练流程

from torchvision import datasets, transforms

# 数据预处理
transform = transforms.Compose([transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))  # MNIST 均值和标准差
])

train_data = datasets.MNIST('../data', train=True, download=True, transform=transform)

# 关键步骤:创建 DataLoader 时设置 pin_memory=True 可加速 GPU 传输
train_loader = torch.utils.data.DataLoader(train_data, batch_size=64, shuffle=True)

# 训练循环
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

for epoch in range(10):
    for batch_idx, (data, target) in enumerate(train_loader):
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()  # 反向传播
        optimizer.step()  # 参数更新

调参技巧

  • 学习率与 batch size:
  • 大 batch size 可配合更大学习率(建议比例:lr∝√batch_size)
  • 使用学习率预热 (warmup) 避免初期震荡

  • 网络结构分析:

    from torchsummary import summary
    summary(model, input_size=(1, 28, 28))  # 输出各层参数统计

  • 早停法实现:

    best_loss = float('inf')
    patience = 3
    counter = 0
    
    for epoch in range(100):
        val_loss = validate(model, val_loader)
    
        if val_loss < best_loss:
            best_loss = val_loss
            counter = 0
            torch.save(model.state_dict(), 'best_model.pt')
        else:
            counter += 1
            if counter >= patience:
                print('Early stopping!')
                break

常见问题解决方案

  1. 维度错误:
  2. PyTorch 默认 NCHW 格式(批次数×通道数×高×宽)
  3. 遇到 NHWC 数据时需 permute(0,3,1,2)

  4. 显存不足:

  5. 减小 batch size
  6. 使用混合精度训练(torch.cuda.amp)
  7. 梯度累积:多次 forward 后统一 backward

  8. 卷积核设计:

  9. 小尺寸(3×3)卷积堆叠效果优于大卷积核
  10. 最后一层特征图尺寸不宜小于 7×7

延伸思考

当处理 4 通道 DICOM 医学影像时:
– 修改第一层 Conv2d 的 in_channels 参数为 4
– 注意预处理时对每个通道单独归一化
– 可能需要增加初始卷积核数量捕捉多通道特征

通过这个实战流程,我们实现了从理论到实践的完整闭环。建议读者尝试调整网络深度、卷积核数量等参数,观察对模型性能的影响。

正文完
 0
评论(没有评论)