深度学习(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
相关推荐
TomEval3 分钟前
【测AI】第17篇:大模型评测方法论 —— LLM 怎么测?
人工智能·python·aigc·测试用例
2601_965619694 分钟前
新闻数据可视化视频:AI自动生成图表动画的完整流程
人工智能·信息可视化·音视频
志尊宝7 分钟前
AI原生前端开发(018):端侧AI性能优化:模型加载、推理加速
人工智能·性能优化·ai-native
renhongxia18 分钟前
RAG检索增强生成:打通大模型与外部知识的通道
大数据·人工智能·算法
jarvisuni11 分钟前
【无标题】
人工智能·ai编程
沈阳光域纪元科技有限公司16 分钟前
GEO 效果归因的技术难点:从曝光到引用的链式度量
人工智能·创业创新
QYR-分析17 分钟前
2.80 亿增至 4.12 亿美元,CAGR5.6%:肌电诱发电位仪稳健扩容,神经电生理检测设备加速走向便携与数字化
大数据·网络·人工智能
宇哥(mf️取5r)17 分钟前
环评验收屡次卡壳,模块化危废间该如何匹配新标准?
大数据·人工智能·制造
醒醒该学习了!19 分钟前
Prompt 设计之带深度思考模型的提示方法和提示词优化
人工智能·prompt
m0_敲代码的彭于晏16823 分钟前
OpenCode 2.0 智能编程效果全景展示
人工智能·python·语言模型