Avatar
DEEP LEARNING

深度学习实践:CNN 经典架构复现

从零手写 LeNet → AlexNet → VGG-16 → GoogLeNet → ResNet18 五个经典 CNN 架构(含 3 个 ResNet 变体与 3 个 GoogLeNet 变体),统一在 FashionMNIST 上训练对比;进阶至 C3D 三维卷积,分别在暴力行为检测与 Flask Web 推理系统上实践从算法到部署的完整闭环。全程采用 PyTorch + torchvision 生态,训练脚本支持 GPU/CPU 自适应、最佳模型保存、tensorboardX 可视化。

PyTorch CNN C3D Flask
8
经典架构
60+
Python 文件
2
视频应用
C3D
3D 卷积模型

架构演进之路

所有模型统一在 FashionMNIST(10 类服饰)上训练,训练集/验证集按 8:2 随机切分。全项目采用同一套训练框架:Adam 优化器(lr=0.001)+ CrossEntropyLoss + batch_size=32,自动检测 CUDA GPU 加速。每个 epoch 记录训练/验证的 loss 与 accuracy,保存验证集准确率最高的模型权重(best_model.pth)。

L
1998

LeNet

一切开始的地方。7 层结构:Conv(1→6,5x5) → Sigmoid → AvgPool(2x2) → Conv(6→16,5x5) → AvgPool → Flatten → FC(400→120) → FC(120→84) → FC(84→10)。输入 28×28 灰度图,Sigmoid 激活 + 平均池化的经典组合。

Sigmoid AvgPool 5×5 Conv
A
2012

AlexNet

深度与宽度的飞跃。输入 227×227(适配 11×11 大卷积核),ReLU 替代 Sigmoid 解决梯度消失,Dropout 防止过拟合,MaxPool 替代 AvgPool 保留强特征。双全连接层 4096 维。

ReLU Dropout MaxPool 11×11 Conv
V
2014

VGG-16

极致的规整设计。全程仅用 3×3 卷积 + BatchNorm + ReLU,通过堆叠深度(16 层)而非大卷积核提升性能。每两个 3×3 conv 的感受野等价于一个 5×5,参数却更少。约 138M 参数的巨型网络。

3×3 卷积 BatchNorm 138M 参数
G
2014

GoogLeNet

不再"堆深度"而是"铺宽度"。核心 Inception 模块在同一层并行 1×1、3×3、5×5 卷积分支后沿通道拼接。1×1 卷积降维大幅减少计算量,辅助分类器(auxiliary loss)缓解深层梯度消失。实现了三个变体逐步优化。

Inception 1×1 Conv Aux Loss 3 Variants
R
2015

ResNet18

跳跃连接的革命。核心创新 残差块 F(x) + x:将输入直接加到卷积输出上,解决了深层网络的退化问题。本项目实现了 三个变体:标准 ResNet18(BasicBlock,2 层残差)/SE-ResNet18(嵌入 Squeeze-and-Excitation 通道注意力,让网络自动学习各通道重要性)/ 集成版本。BatchNorm 替代了早期架构的 Dropout 做正则化。

Skip Connection SE Module BatchNorm 3 Variants

从图像到视频:C3D 实战

将 2D 卷积的认知迁移到 3D:Conv3d(kernel=(3,3,3)) 在时间维度上同时滑动,单次推理捕捉 16 帧的时空特征。基于 Sports-1M 预训练模型(ucf101-caffe.pth)微调,大幅降低从头训练成本。

warning

暴力行为检测

将 Sports-1M 预训练的 101 类 C3D 微调为 2 分类器(Fight / NoFight)。自定义 VideoDataset 从帧序列读取:128×171 缩放 → 112×112 随机裁剪 → 均值减除 [90,98,102] → ToTensor。使用 SGD(momentum=0.9, weight_decay=5e-4) + StepLR(step=10, gamma=0.1) 训练 29 epoch,TensorBoard 记录训练曲线与 tqdm 进度条可视化。

推理阶段:OpenCV 读取视频 → center_crop → 滑动窗口 16 帧 → 模型输出 Softmax 概率 → 逐帧标注类别 + 置信度到视频画面上。

Conv3d Slide Window OpenCV Sports-1M
play_circle

视频识别 Web 应用

Flask 3.0 + CORS 构建的完整后端服务。核心 API POST /api/recognize:接收 MP4/AVI/MOV/MKV 视频 → UUID 安全存储 → 逐帧抽提 + C3D 推理 → 返回帧级分类结果 JSON(frame/class/confidence)。单文件上限 100MB,处理完自动清理。

前端:HTML5 原生实现,渐变色 UI,拖拽上传 + 进度动画 + 结果置信度条形图可视化。无需任何前端框架,纯 vanilla JS + CSS。

Flask 3.0 REST API 拖拽上传 置信度分析
architecture

训练工程化细节

数据加载

VideoDataset 自定义 Dataset 类:从磁盘帧图片加载 → 随机时间/空间裁剪(数据增强)→ 归一化。DataLoader batch 并行加载,num_workers 多进程加速。

训练策略

C3D 训练采用 SGD + momentum + weight_decay 组合,StepLR 每 10 epoch 将学习率衰减为 1/10。tensorboardX 记录 loss/accuracy 曲线。tqdm 实时显示 batch 进度。

推理优化

滑动窗口:每 16 帧送入一次 C3D,窗口步进 1 帧(clip.pop(0)),实现逐帧分类。上传视频处理完自动删除临时文件,防止磁盘堆积。

训练工程化

所有 CNN 模型共享同一套训练框架,这不是代码重复,而是刻意设计——每个架构都有自己独立的数据预处理参数(输入尺寸从 28→227→224 随架构不同而变),但训练循环逻辑保持高度一致以方便横向对比。

CNN 训练管道

数据加载:FashionMNIST → transforms.Compose(Resize → ToTensor) → DataLoader(batch=32, shuffle=True, num_workers=2)。训练集 8:2 随机分割出验证集,使用 random_split 保证无数据泄露。

训练循环:双层循环——外层 epoch 遍历,内层 batch 遍历。每个 batch 执行 zero_grad → forward → loss → backward → optimizer.step() 标准五步。每个 epoch 结束后计算整个训练集和验证集的平均 loss 和 accuracy。

设备管理:torch.device("cuda" if torch.cuda.is_available() else "cpu") 自动检测 GPU。模型和输入数据都通过 .to(device) 迁移,确保 CPU/GPU 无缝切换。

模型保存:copy.deepcopy(model.state_dict()) 深拷贝保存验证集准确率最高的模型权重,避免后续 epoch 过拟合覆盖最优解。

C3D 训练差异

自定义 Dataset:VideoDataset(Dataset) 类从磁盘帧目录读取,覆盖 __len__、__getitem__、load_frames、crop、normalize、to_tensor 六个方法,实现完整的自定义数据管道。

数据增强:np.random.randint 在时空维度分别生成随机裁剪起点,每次训练同一个视频看到不同的片段——这是视频理解的标准增强手段。

优化策略:SGD 替代 Adam(C3D 参数量大,SGD+momentum 更稳定),StepLR 阶梯式学习率衰减(step=10, gamma=0.1),weight_decay=5e-4 做 L2 正则化。

迁移学习:加载 Sports-1M 预训练权重 ucf101-caffe.pth,冻结底层 3D 卷积核,仅微调分类头——pretrain + finetune 范式。

核心收获

lightbulb

Sigmoid → ReLU:激活函数的代际跃迁

LeNet 的 Sigmoid 在深层网络中会导致梯度消失(饱和区导数→0)。AlexNet 引入 ReLU(f(x)=max(0,x)) 是该领域最具影响力的单行代码改进。训练中直观感受到两者收敛速度的巨大差异:ReLU 网络的 loss 下降曲线明显更陡,训练时间大幅缩短。

account_tree

残差连接:不是魔法,是恒等映射

ResNet 论文最精巧的设计:残差连接不是新运算,只是恒等映射。F(x)=H(x)-x 的数学洞察——让网络学习残差而非目标——解决了 VGG 纯堆叠到 20+ 层反而退化的问题。SE-ResNet 在此基础上做了通道注意力:全局平均池化→FC→Sigmoid→逐通道加权,计算开销极小但精度提升显著。三个变体的横向对比让"为什么加这个模块有效"不再是纸上谈兵。

view_in_ar

2D→3D 卷积的思维跃迁

Conv2d(kernel=3×3) → Conv3d(kernel=3×3×3),本质是在 kernel 张量上加了一维。但真正卡住理解的是数据流形状:2D 输入 (B,C,H,W),3D 变成 (B,C,D,H,W)。需要在 DataLoader 里手动 transpose 把帧堆叠从 (D,H,W,C)→(C,D,H,W)。这个维度顺序是实际调试最容易出错的地方——整个项目在这个 bug 上卡了大半天。

deployed_code

从 Notebook 到生产部署

训练完模型只是第一步。把 C3D 封装进 Flask + CORS Web 服务,处理文件上传安全(UUID 重命名、扩展名白名单、自动清理),设计 JSON API 返回帧级结果,写 HTML5 前端做拖拽上传和置信度可视化——这才是从"会训练"跨越到"能交付"的关键。尤其 torch.no_grad() 推理时必须加,否则 PyTorch 为每个 tensor 保留计算图导致显存溢出——实际部署踩过的坑。

技术栈

code

Python 3.8+

全部训练/推理逻辑

memory

PyTorch 2.0+

torch.nn + torch.optim

visibility

torchvision 0.15+

FashionMNIST + transforms

dns

Flask 3.0

Web 推理服务 + REST API

bar_chart

tensorboardX

训练 loss/acc 曲线

monitoring

tqdm

实时训练进度条

movie

OpenCV 4.10

视频帧抽提与处理

hub

torchsummary

模型参数量分析

项目结构

CNN 分类模型(8 个)

LeNet / AlexNet / VGG-16 / GoogLeNet×3 / ResNet18×3 — 每架构标配 model.py(定义)/ model_train.py(训练循环 + Adam + 早停保存)/ model_test.py(测试推理)/ plot.py(FashionMNIST 批次可视化)

C3D 视频分析(2 个)

Fight-detection:C3D_model.py(145 行,8 Conv3d + 2 FC)+ train.py(SGD + StepLR + tensorboardX)+ inference.py(OpenCV 实时标注);video-recognition:src/backend/app.py(Flask 服务)+ src/model/(C3D 模型组)

工程配套

requirements.txt(15 个依赖包,含豆瓣/清华镜像源);start.bat(Windows 一键安装启动);VideoDataset 自定义数据加载器(随机时空裁剪 + 均值归一化 + ToTensor);best_model.pth 预训练权重

stars

FROM THEORY TO PRACTICE

每个架构都是手写实现,每个模型都能独立运行。这就是深度学习的正确打开方式。