构建ResNet-18模型在CIFAR-10数据集上实现分类(pytorch版)

文章目录

  • [1. 构建ResNet模型](#1. 构建ResNet模型)
    • [1.1 前置条件](#1.1 前置条件)
    • [1.2 构建Residual Block](#1.2 构建Residual Block)
    • [1.3 构建ResNet-18](#1.3 构建ResNet-18)
    • [1.4 模型测试](#1.4 模型测试)
  • [2. 训练与评估](#2. 训练与评估)
    • [2.1 数据预处理与加载](#2.1 数据预处理与加载)
    • [2.2 模型训练](#2.2 模型训练)
    • [2.3 模型评估](#2.3 模型评估)
  • 参考文献

1. 构建ResNet模型

我们将使用PyTorch框架来实现一个简化版的ResNet-18模型。我们的目标是构建一个可以在CIFAR-10数据集上进行分类任务的模型。

1.1 前置条件

python 复制代码
pip install torch torchvision

1.2 构建Residual Block

首先,让我们实现一个残差块。这是前面章节已经介绍过的内容。

python 复制代码
import torch
import torch.nn as nn

class ResidualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        super(ResidualBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1)
        self.bn2 = nn.BatchNorm2d(out_channels)
        
        self.shortcut = nn.Sequential()
        if stride != 1 or in_channels != out_channels:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride),
                nn.BatchNorm2d(out_channels)
            )

1.3 构建ResNet-18

接下来,我们使用残差块来构建完整的ResNet-18模型。

python 复制代码
class ResNet18(nn.Module):
    def __init__(self, num_classes=10):
        super(ResNet18, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.layer1 = self._make_layer(64, 64, 2)
        self.layer2 = self._make_layer(64, 128, 2, stride=2)
        self.layer3 = self._make_layer(128, 256, 2, stride=2)
        self.layer4 = self._make_layer(256, 512, 2, stride=2)
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(512, num_classes)

    def _make_layer(self, in_channels, out_channels, blocks, stride=1):
        layers = []
        layers.append(ResidualBlock(in_channels, out_channels, stride))
        for _ in range(1, blocks):
            layers.append(ResidualBlock(out_channels, out_channels))
        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.fc(x)
        return x

以上代码定义了一个用于CIFAR-10分类任务的ResNet-18模型。在这个模型中,我们使用了前面定义的ResidualBlock类,并通过_make_layer函数来堆叠多个残差块。

1.4 模型测试

接下来,我们可以测试这个模型以确保其结构是正确的。

python 复制代码
# 创建一个模拟输入
x = torch.randn(64, 3, 32, 32)

# 实例化模型
model = ResNet18(num_classes=10)

# 前向传播
output = model(x)

# 输出形状应为(64, 10),因为我们有64个样本和10个类别
print(output.shape)  # 输出:torch.Size([64, 10])

2. 训练与评估

在成功构建了ResNet-18模型之后,下一步就是进行模型的训练和评估。在这一部分,我们将介绍如何在CIFAR-10数据集上完成这两个步骤。

2.1 数据预处理与加载

首先,我们需要准备数据。使用PyTorch的torchvision库,我们可以非常方便地下载和预处理CIFAR-10数据集。

python 复制代码
import torch
import torchvision
import torchvision.transforms as transforms

# 数据预处理
transform = transforms.Compose([
    transforms.RandomCrop(32, padding=4),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
])

# 加载数据集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True)

testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=128, shuffle=False)

2.2 模型训练

训练模型通常需要指定损失函数和优化器,并反复进行前向传播、计算损失、反向传播和参数更新。

python 复制代码
import torch.optim as optim

# 实例化模型并移至GPU
model = ResNet18(num_classes=10).cuda()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)

# 训练模型
for epoch in range(10):  # 运行10个周期
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data
        inputs, labels = inputs.cuda(), labels.cuda()

        # 清零梯度缓存
        optimizer.zero_grad()

        # 前向传播,计算损失,反向传播
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()

        # 更新参数
        optimizer.step()

2.3 模型评估

训练完成后,我们需要评估模型的性能。这通常通过在测试集上计算模型的准确率来完成。

python 复制代码
# 切换模型为评估模式
model.eval()

correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        images, labels = images.cuda(), labels.cuda()
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print(f'Accuracy of the network on the 10000 test images: {100 * correct / total}%')

参考文献

理论内容:https://blog.csdn.net/magicyangjay111/article/details/132553872

相关推荐
一点媛艺2 小时前
Kotlin函数由易到难
开发语言·python·kotlin
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
_.Switch3 小时前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
测开小菜鸟4 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
数据猎手小k5 小时前
AIDOVECL数据集:包含超过15000张AI生成的车辆图像数据集,目的解决旨在解决眼水平分类和定位问题。
人工智能·分类·数据挖掘
萧鼎6 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
学地理的小胖砸6 小时前
【一些关于Python的信息和帮助】
开发语言·python
疯一样的码农6 小时前
Python 继承、多态、封装、抽象
开发语言·python
Python大数据分析@6 小时前
python操作CSV和excel,如何来做?
开发语言·python·excel
黑叶白树6 小时前
简单的签到程序 python笔记
笔记·python