深度学习(21)使用块的网络VGG

1. VGG网络

经测试后,发现3*3的效果比5*5的效果要好

2. 总结

1. VGG网络(使用自定义)

一、VGG块(核心思想)

python 复制代码
def vgg_block(num_convs, in_channels, out_channels):

👉 一个 VGG block = 多个卷积层 + 1个池化层

结构:

python 复制代码
(Conv + ReLU) × num_convs → MaxPool

代码解析:

python 复制代码
layers = []
for _ in range(num_convs):
    layers.append(nn.Conv2d(in_channels,out_channels,kernel_size=3,padding=1))
    layers.append(nn.ReLU())
    in_channels = out_channels
  • kernel_size=3, padding=1
    👉 保证卷积前后 高宽不变

  • 每一层卷积后:
    👉 通道数变成 out_channels

    layers.append(nn.MaxPool2d(kernel_size=2,stride=2))

👉 池化层作用:

  • 高宽减半(224 → 112 → 56 → ...

    return nn.Sequential(*layers)

👉 把列表展开成一个顺序模型


二、VGG整体结构

复制代码
conv_arch = ((1,64),(1,128),(2,256),(2,512),(2,512))

👉 表示 5 个 block:

block 卷积层数 输出通道
1 1 64
2 1 128
3 2 256
4 2 512
5 2 512

构建网络

复制代码
def vgg(conv_arch):

卷积部分:

复制代码
for (num_convs, out_channels) in conv_arch:
    conv_blks.append(vgg_block(num_convs,in_channels,out_channels))

👉 每个 block:

  • 通道数逐渐增加
  • 空间尺寸逐渐减小

全连接部分:

复制代码
nn.Flatten(),
nn.Linear(out_channels * 7 * 7, 4096)

👉 为什么是 7×7

因为输入是 224×224:

复制代码
224 → 112 → 56 → 28 → 14 → 7

(5次池化)


后面结构:

复制代码
ReLU → Dropout → Linear → ReLU → Dropout → Linear

👉 经典 VGG 全连接设计:

  • 两个 4096 层
  • Dropout 防止过拟合

三、输出尺寸变化(重点)

复制代码
X = torch.randn(size=(1,1,224,224))

👉 输入:1张灰度图

循环打印:

复制代码
for blk in net:

你会看到类似:

复制代码
Sequential output shape: (1, 64, 112, 112)
Sequential output shape: (1, 128, 56, 56)
Sequential output shape: (1, 256, 28, 28)
Sequential output shape: (1, 512, 14, 14)
Sequential output shape: (1, 512, 7, 7)

👉 总结规律:

  • 高宽:不断减半
  • 通道:不断增加

四、为什么要缩小模型(关键优化)

复制代码
ratio = 4
small_conv_arch = [(pair[0], pair[1]//ratio) for pair in conv_arch]

👉 原始 VGG 太大:

  • 参数太多
  • 训练慢
  • 显存占用高

👉 所以:

复制代码
64 → 16
128 → 32
256 → 64
...

👉 这样:

  • 计算量 ↓↓↓
  • 更适合普通GPU/CPU

五、数据加载

复制代码
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,resize=224)

👉 关键点:

  • Fashion-MNIST 原本是 28×28
  • resize 到 224×224

👉 原因:

  • VGG 是为 ImageNet 设计的(224×224)

六、训练过程

复制代码
d2l.train_ch6(net,train_iter,test_iter,num_epochs,lr,d2l.try_gpu())

👉 做了几件事:

  1. 前向传播
  2. 计算损失
  3. 反向传播
  4. 更新参数
  5. 在 GPU 上训练(如果有)

七、整体流程总结

复制代码
输入图像 (1×224×224)
    ↓
5个VGG块(卷积+池化)
    ↓
特征图 (512×7×7)
    ↓
Flatten
    ↓
全连接层
    ↓
输出10类

八、核心思想总结(非常重要🔥)

1️⃣ 小卷积核(3×3)

  • 提取局部特征
  • 堆叠增强表达能力

2️⃣ 深层结构

  • 多层卷积比大卷积更有效

3️⃣ 通道数逐步增加

  • 表示更复杂特征

4️⃣ 池化逐步降维

  • 减少计算量
python 复制代码
import torch
from torch import nn
from d2l import torch as d2l

#构造一个VGG块
def vgg_block(num_convs,in_channels,out_channels): # 卷积层个数、输入通道数、输出通道数
    layers = []
    for _ in range(num_convs):
        layers.append(nn.Conv2d(in_channels,out_channels,kernel_size=3,padding=1))      
        layers.append(nn.ReLU())
        in_channels = out_channels
    layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
    return nn.Sequential(*layers) # *layers表示把列表里面的元素按顺序作为参数输入函数     

conv_arch = ((1,64),(1,128),(2,256),(2,512),(2,512)) # 第一个参数为几层卷积,第二个参数为输出通道数

def vgg(conv_arch):
    conv_blks = []
    in_channels = 1
    for (num_convs, out_channels) in conv_arch:
        conv_blks.append(vgg_block(num_convs,in_channels,out_channels))
        in_channels = out_channels

    return nn.Sequential(*conv_blks, nn.Flatten(),
                         nn.Linear(out_channels * 7 * 7, 4096),nn.ReLU(),
                         nn.Dropout(0.5), nn.Linear(4096,4096),nn.ReLU(),
                         nn.Dropout(0.5), nn.Linear(4096,10))

net = vgg(conv_arch)

# 观察每个层输出的形状
X = torch.randn(size=(1,1,224,224))
for blk in net:
    X = blk(X)
    print(blk.__class__.__name__,'output shape:\t', X.shape) # VGG使得高宽减半,通道数加倍
复制代码
Sequential output shape:	 torch.Size([1, 64, 112, 112])
Sequential output shape:	 torch.Size([1, 128, 56, 56])
Sequential output shape:	 torch.Size([1, 256, 28, 28])
Sequential output shape:	 torch.Size([1, 512, 14, 14])
Sequential output shape:	 torch.Size([1, 512, 7, 7])
Flatten output shape:	 torch.Size([1, 25088])
Linear output shape:	 torch.Size([1, 4096])
ReLU output shape:	 torch.Size([1, 4096])
Dropout output shape:	 torch.Size([1, 4096])
Linear output shape:	 torch.Size([1, 4096])
ReLU output shape:	 torch.Size([1, 4096])
Dropout output shape:	 torch.Size([1, 4096])
Linear output shape:	 torch.Size([1, 10])
python 复制代码
# 由于VGG-11比AlexNet计算量更大,因此构建了一个通道数较少的网络
ratio = 4
small_conv_arch = [(pair[0], pair[1]//ratio) for pair in conv_arch] # 所有输出通道除以4
net = vgg(small_conv_arch)

lr, num_epochs, batch_size = 0.05, 10, 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,resize=224)    
d2l.train_ch6(net,train_iter,test_iter,num_epochs,lr,d2l.try_gpu())
复制代码
loss 0.179, train acc 0.934, test acc 0.915
593.8 examples/sec on cuda:0
相关推荐
Raink老师2 小时前
【AI面试临阵磨枪-79】实时数据 RAG:订单、商家、物流、天气、动态库存
人工智能·面试·职场和发展
脑极体2 小时前
点亮星河AI+鸿蒙,一座艺术场馆的日神觉醒
人工智能·华为·harmonyos
Cosolar2 小时前
Chroma向量库面试学习指南
数据库·人工智能·面试·职场和发展·数据库架构
BUG指挥官2 小时前
Claude Code的自动化编程
人工智能
2301_809051142 小时前
Linux 网络编程 学习笔记
linux·网络·学习
意图共鸣2 小时前
意图共鸣科技《认知智能白皮书》——感知与执行分离:认知架构(CA)如何重塑大模型底层结构
人工智能·架构
等一个人的@2 小时前
让数据自己开口:数睿通智库新增智能问数模块
人工智能·自然语言处理
ZGi.ai2 小时前
人工审查节点:让自动化工作流多一步人工把关
运维·人工智能·自动化·人机协同·智能体工作流·人工审查
王莎莎-MinerU3 小时前
MinerU 深度技术解析:从架构原理到生产部署的全面指南
css·人工智能·自然语言处理·架构·ocr·个人开发
盘古信息IMS3 小时前
盘古信息IMS V6 8.0重磅发布:以薪火AI数智平台点燃离散制造数智化引擎
大数据·人工智能·制造