深度学习(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
相关推荐
weixin_750330232 小时前
AI获客工具选型:从技术架构看中小企业效率提升方案
大数据·人工智能·架构·ai获客
mpp0073 小时前
36氪《2026 中国 AI Agent 行业发展报告》:当 Agent 进入「交付」主战场
大数据·人工智能
吃饱了得干活5 小时前
Agent 的决策与规划:ReAct、Plan-and-Execute、Reflexion 与 Tree of Thoughts
人工智能·llm·agent
阿明65 小时前
小白入门机器学习基础【AI】
人工智能·机器学习
java资料站5 小时前
十一、评估测试
开发语言·人工智能·python
东方佑5 小时前
从《事件发生与智能》的框架看中国古代命理学
人工智能·深度学习·语言模型·自然语言处理·架构
白帽攻防录5 小时前
SRC 挖洞:Roundcube 预认证 SQL 注入深度复盘,CVE-2026-48842 preg_replace 转义绕过怎么打穿邮件系统
网络·数据库·sql·网络安全·sql注入
天远API5 小时前
零信任架构实战:基于天远运营商三要素简版V即时版查询构建自动化司乘安全绑定网关
人工智能·安全·架构·自动化
Henry-SAP6 小时前
SAP PP核心引擎计划策略业务解析
人工智能·云原生·sap·erp
DP DPharness6 小时前
拆开 dsh-knowledge 的检索链路,看 RRF 融合与锚点续读
人工智能·dpharness