当前位置: 首页 > news >正文

深度学习篇---VGGNet网络结构

在 PyTorch 中实现 VGGNet 非常直观,因为它的结构极其规整 —— 全是 3×3 卷积层和 2×2 池化层的组合,就像搭积木一样按固定模式堆叠。我们以最经典的 VGG-16 为例,一步步实现,保证零基础你能看懂每一行代码的作用。

一、先明确 VGG-16 的核心结构(复习)

VGG-16 的结构可以用一句话概括:5 个卷积块(每个块含多个 3×3 卷积层)+3 个全连接层,每个卷积块后都接 1 个 2×2 的最大池化层。具体来说:

输入(224×224彩色图) → 
卷积块1(2个3×3卷积) → 池化 → 
卷积块2(2个3×3卷积) → 池化 → 
卷积块3(3个3×3卷积) → 池化 → 
卷积块4(3个3×3卷积) → 池化 → 
卷积块5(3个3×3卷积) → 池化 → 
全连接层1(4096) → 全连接层2(4096) → 输出层(1000类)

二、PyTorch 实现 VGG-16 的步骤

步骤 1:导入必要的库

和之前实现 LeNet、AlexNet 一样,先准备好工具:

import torch  # 核心库
import torch.nn as nn  # 神经网络层
import torch.optim as optim  # 优化器
from torch.utils.data import DataLoader  # 数据加载器
from torchvision import datasets, transforms  # 图像数据处理

步骤 2:定义 VGG-16 网络结构

VGG 的精髓是 “用配置列表定义卷积块”,避免重复写代码。我们先定义每个卷积块的 “卷积层数量” 和 “输出通道数”,再用循环构建网络。

class VGG16(nn.Module):def __init__(self, num_classes=1000):super(VGG16, self).__init__()# 定义卷积块的配置:(卷积层数量, 输出通道数)# 5个卷积块对应VGG-16的结构config = [(2, 64),   # 卷积块1:2个卷积层,输出64通道(2, 128),  # 卷积块2:2个卷积层,输出128通道(3, 256),  # 卷积块3:3个卷积层,输出256通道(3, 512),  # 卷积块4:3个卷积层,输出512通道(3, 512)   # 卷积块5:3个卷积层,输出512通道]# 构建卷积部分layers = []in_channels = 3  # 输入是3通道彩色图for (num_convs, out_channels) in config:# 每个卷积块内堆叠num_convs个3×3卷积层for _ in range(num_convs):layers.append(nn.Conv2d(in_channels=in_channels,out_channels=out_channels,kernel_size=3,  # 固定3×3卷积核padding=1       # 边缘填充1像素,保证卷积后尺寸不变))layers.append(nn.ReLU(inplace=True))  # ReLU激活in_channels = out_channels  # 更新输入通道数为当前输出通道数# 每个卷积块后接1个2×2最大池化层(步长2,尺寸减半)layers.append(nn.MaxPool2d(kernel_size=2, stride=2))# 把卷积层组合成Sequentialself.features = nn.Sequential(*layers)# 构建全连接部分self.classifier = nn.Sequential(# 全连接层1:输入是7×7×512(池化后特征图),输出4096nn.Linear(512 * 7 * 7, 4096),nn.ReLU(inplace=True),nn.Dropout(p=0.5),  # Dropout防止过拟合# 全连接层2:输入4096,输出4096nn.Linear(4096, 4096),nn.ReLU(inplace=True),nn.Dropout(p=0.5),# 输出层:输入4096,输出类别数nn.Linear(4096, num_classes))# 定义数据流向def forward(self, x):x = self.features(x)  # 经过卷积部分x = x.view(x.size(0), 512 * 7 * 7)  # 拉平特征图(batch_size, 512×7×7)x = self.classifier(x)  # 经过全连接部分return x

关键解释

  • 配置列表 config:用元组(卷积层数量, 输出通道数)定义每个卷积块,让代码更简洁(改数字就能调整网络结构)。
  • 3×3 卷积 + padding=1:保证卷积后特征图尺寸不变(比如 224×224 的图经过 3×3 卷积 + padding=1 后还是 224×224)。
  • 池化层作用:每个卷积块后用 2×2 池化(步长 2),让特征图尺寸减半(224→112→56→28→14→7),最终得到 7×7×512 的特征图。

步骤 3:准备数据(用 CIFAR-10 演示)

VGG 原本用于 ImageNet(1000 类),我们用小型的 CIFAR-10(10 类)演示,预处理流程类似:

# 数据预处理:缩放+裁剪+翻转+标准化
transform = transforms.Compose([transforms.Resize(256),  # 缩放为256×256transforms.RandomCrop(224),  # 随机裁剪成224×224(VGG输入尺寸)transforms.RandomHorizontalFlip(),  # 随机水平翻转(数据增强)transforms.ToTensor(),  # 转为Tensor# 标准化(用ImageNet的均值和标准差,通用做法)transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])# 加载CIFAR-10数据集
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform
)
test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform
)# 批量加载数据(VGG参数量大,batch_size设小一点,这里用64)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True, num_workers=4)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False, num_workers=4)

步骤 4:初始化模型、损失函数和优化器

  • 模型:我们定义的 VGG16(CIFAR-10 是 10 类,输出层设为 10)。
  • 损失函数:交叉熵损失(分类任务标配)。
  • 优化器:SGD + 动量(VGG 原文推荐的优化器)。
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')  # 用GPU加速(必须!否则太慢)
model = VGG16(num_classes=10).to(device)  # 初始化模型,输出10类criterion = nn.CrossEntropyLoss()  # 交叉熵损失
# 优化器:学习率0.001,动量0.9,权重衰减5e-4(防止过拟合)
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9, weight_decay=5e-4)

注意:VGG-16 参数量达 1.38 亿,必须用 GPU 训练,否则单轮训练可能要几小时甚至几天。

步骤 5:训练模型

训练逻辑和 AlexNet 类似,但 VGG 更深,需要更多轮次才能收敛(这里示例训练 20 轮):

def train(model, train_loader, criterion, optimizer, epoch):model.train()  # 训练模式for batch_idx, (data, target) in enumerate(train_loader):data, target = data.to(device), target.to(device)  # 数据放GPUoptimizer.zero_grad()  # 清空梯度output = model(data)   # 模型预测loss = criterion(output, target)  # 计算损失loss.backward()        # 反向传播optimizer.step()       # 更新参数# 打印进度(每200个batch打印一次)if batch_idx % 200 == 0:print(f'Epoch {epoch}, Batch {batch_idx}, Loss: {loss.item():.6f}')

步骤 6:测试模型效果

用测试集评估准确率:

def test(model, test_loader):model.eval()  # 评估模式(关闭Dropout)correct = 0total = 0with torch.no_grad():  # 不计算梯度,节省内存for data, target in test_loader:data, target = data.to(device), target.to(device)output = model(data)_, predicted = torch.max(output.data, 1)  # 取概率最大的类别total += target.size(0)correct += (predicted == target).sum().item()print(f'Test Accuracy: {100 * correct / total:.2f}%')

步骤 7:开始训练和测试

# 训练20轮(实际需要更多轮次,比如50-100轮才能达到较高准确率)
for epoch in range(1, 21):train(model, train_loader, criterion, optimizer, epoch)test(model, test_loader)

训练过程中,你会看到损失逐渐下降,准确率逐渐上升。在 CIFAR-10 上,VGG-16 训练充分后准确率通常能达到 90% 左右。

三、完整代码总结

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms# 1. 定义VGG-16网络结构
class VGG16(nn.Module):def __init__(self, num_classes=1000):super(VGG16, self).__init__()# 卷积块配置:(卷积层数量, 输出通道数)config = [(2, 64),   # 卷积块1(2, 128),  # 卷积块2(3, 256),  # 卷积块3(3, 512),  # 卷积块4(3, 512)   # 卷积块5]# 构建卷积部分layers = []in_channels = 3  # 输入为3通道彩色图for (num_convs, out_channels) in config:# 堆叠num_convs个3×3卷积层for _ in range(num_convs):layers.append(nn.Conv2d(in_channels=in_channels,out_channels=out_channels,kernel_size=3,padding=1))layers.append(nn.ReLU(inplace=True))in_channels = out_channels# 每个卷积块后接池化层layers.append(nn.MaxPool2d(kernel_size=2, stride=2))self.features = nn.Sequential(*layers)# 构建全连接部分self.classifier = nn.Sequential(nn.Linear(512 * 7 * 7, 4096),nn.ReLU(inplace=True),nn.Dropout(p=0.5),nn.Linear(4096, 4096),nn.ReLU(inplace=True),nn.Dropout(p=0.5),nn.Linear(4096, num_classes))def forward(self, x):x = self.features(x)x = x.view(x.size(0), 512 * 7 * 7)  # 拉平特征图x = self.classifier(x)return x# 2. 准备CIFAR-10数据
transform = transforms.Compose([transforms.Resize(256),transforms.RandomCrop(224),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform
)
test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform
)train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True, num_workers=4)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False, num_workers=4)# 3. 初始化模型、损失函数和优化器
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = VGG16(num_classes=10).to(device)  # CIFAR-10是10类
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9, weight_decay=5e-4)# 4. 训练函数
def train(model, train_loader, criterion, optimizer, epoch):model.train()for batch_idx, (data, target) in enumerate(train_loader):data, target = data.to(device), target.to(device)optimizer.zero_grad()output = model(data)loss = criterion(output, target)loss.backward()optimizer.step()if batch_idx % 200 == 0:print(f'Epoch {epoch}, Batch {batch_idx}, Loss: {loss.item():.6f}')# 5. 测试函数
def test(model, test_loader):model.eval()correct = 0total = 0with torch.no_grad():for data, target in test_loader:data, target = data.to(device), target.to(device)output = model(data)_, predicted = torch.max(output.data, 1)total += target.size(0)correct += (predicted == target).sum().item()print(f'Test Accuracy: {100 * correct / total:.2f}%')# 6. 开始训练和测试
for epoch in range(1, 21):train(model, train_loader, criterion, optimizer, epoch)test(model, test_loader)

四、关键知识点回顾

  1. 结构设计:用配置列表config定义卷积块,通过循环堆叠 3×3 卷积层,结构极其规整,修改config即可得到 VGG-11、VGG-19 等其他版本。
  2. 核心技巧:3×3 卷积 + padding=1 保证尺寸不变,2×2 池化实现尺寸减半,Dropout 防止过拟合。
  3. 实现注意:VGG 参数量极大(1.38 亿),必须用 GPU 训练;全连接层输入维度是512×7×7(最后一次池化后的特征图尺寸),别算错。

运行这段代码,你就能亲手实现这个 “结构标准化典范” 模型,感受 “小卷积核 + 深网络” 的强大特征提取能力!

http://www.dtcms.com/a/355141.html

相关文章:

  • 阿里云轻量服务器的系统镜像和应用镜像的区别在哪?
  • 从零开始的python学习——浅谈python
  • 深度学习网络结构搭建
  • 【算法--链表题4】23.合并K个升序链表
  • Scikit-learn Python机器学习 - 什么是机器学习
  • 【lucene】advanceShallow (int target) 与advance(int target)
  • Vulhub靶场通关教程详解
  • Vibe Coding 概念提出者 AndrejKarpathy 谈强化学习。
  • Flink CDC如何保障数据的一致性
  • 设计模式相关面试题
  • 一个基于物理信息神经网络(Physics-Informed Neural Network, PINN)的多变量时间序列预测模型MATLAB代码
  • 消息队列核心问题解决方案:从丢失到重复消费的全方位保障
  • 力扣(LeetCode) ——965. 单值二叉树(C语言)
  • 化肥行业磷石膏粉尘专项环保解决方案​——从污染治理到资源循环的全流程突破
  • static 作用一:修饰全局变量
  • [高并发系统设计] - 搭建高并发高可用的系统 - 学习与探究
  • 美图设计室-AI帮你做设计
  • Windows系统安装stata软件教程
  • 【高等数学】第十章 重积分——第三节 三重积分
  • 如何在API高并发中玩转资源隔离与限流策略?
  • 为什么选择 TDengine?
  • nginx的诞生背景、核心优势、与 Apache 的对比
  • 测试设备:高效维修问题的思维模式与日常提升指南
  • STM32——PWR
  • GitHub宕机处理
  • 向宋江学管理
  • Node.js的特性
  • 【动态规划】简单多状态 dp 问题
  • Day16_【机器学习概述】
  • Windows 7-11通用,这工具让电脑提速300%