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

1次阅读
没有评论

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

image.webp

为什么需要 CNN?

传统全连接神经网络在处理图像时会遇到两个致命问题:

  1. 参数爆炸 :假设处理 100×100 像素的 RGB 图片,输入层就需要 100×100×3=30,000 个权重参数,第一个隐藏层若包含 1000 个神经元,仅这一层就有 3000 万个参数!计算量公式为:

$$\text{参数量} = \text{输入维度} \times \text{输出维度} + \text{输出维度}$$

  1. 无视局部关联 :全连接网络把图像拆解为独立像素点处理,完全忽略了相邻像素之间的空间关系。

CNN 核心原理图解

卷积操作本质

想象用一个手电筒(卷积核)在图像上滑动扫描,每次照亮一个小区域做计算。数学表达为:

$$S(i,j) = (I * K)(i,j) = \sum_m \sum_n I(i+m,j+n)K(m,n)$$

其中 $I$ 是输入图像,$K$ 是卷积核,$S$ 是输出特征图。

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

为什么需要 ReLU?

使用激活函数 $\text{ReLU}(x)=\max(0,x)$ 有两个关键好处:

  • 解决梯度消失问题(相比 sigmoid)
  • 增加网络非线性表达能力

PyTorch 实战 MNIST 分类

模型定义

import torch
import torch.nn as nn

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

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

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

训练循环关键代码

optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

for epoch in range(10):
    for images, labels in train_loader:
        # 数据归一化到 [0,1]
        images = images / 255.0  

        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)

        # 核心三步曲
        loss.backward()  # 反向传播
        optimizer.step()  # 更新权重

        # 打印训练进度
        if (i+1) % 100 == 0:
            print(f'Epoch [{epoch+1}/10], Loss: {loss.item():.4f}')

调参实战技巧

学习率与 batch size 的协同

  • 大 batch size 需要更大的学习率
  • 推荐初始设置:
  • batch_size=64 → lr=0.001
  • batch_size=256 → lr=0.004

使用 torchsummary 诊断模型

from torchsummary import summary
summary(model, input_size=(1, 28, 28))  # MNIST 输入尺寸 

输出示例:

----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1           [-1, 32, 28, 28]             320
              ReLU-2           [-1, 32, 28, 28]               0
         MaxPool2d-3           [-1, 32, 14, 14]               0
            Conv2d-4           [-1, 64, 14, 14]          18,496
              ReLU-5           [-1, 64, 14, 14]               0
         MaxPool2d-6             [-1, 64, 7, 7]               0
           Flatten-7                 [-1, 3136]               0
            Linear-8                  [-1, 128]         401,536
              ReLU-9                  [-1, 128]               0
           Linear-10                   [-1, 10]           1,290
================================================================
Total params: 421,642

常见避坑指南

维度错误急救包

# 经典错误:忘记 unsqueeze 增加通道维度
tensor = torch.randn(28, 28)  # 错误!应该是 1×28×28
correct_tensor = tensor.unsqueeze(0)  # 变为 1×28×28

# 处理 NHWC 格式数据 (如 OpenCV 读取的图片)
image = cv2.imread('cat.jpg')  # H×W×C 格式
pytorch_tensor = torch.from_numpy(image).permute(2,0,1)  # 转为 C×H×W

显存不足解决方案

  1. 减小 batch size(如从 256 降到 64)
  2. 使用混合精度训练:
    scaler = torch.cuda.amp.GradScaler()
    with torch.cuda.amp.autocast():
        outputs = model(inputs)
        loss = criterion(outputs, labels)
    scaler.scale(loss).backward()
    scaler.step(optimizer)
    scaler.update()

延伸思考

当处理 4 通道 DICOM 医学影像时,只需修改第一层卷积的 in_channels 参数:

# 原版:适用于灰度图像
nn.Conv2d(1, 32, kernel_size=3) 

# 修改版:适配 4 通道输入
nn.Conv2d(4, 32, kernel_size=3)

关键是要保证卷积核的输入通道数与实际数据通道数一致。其他网络结构无需改动,这就是 CNN 参数共享优势的体现!

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