基于 PyTorch 的模型测试与全局平均池化实践

一、模型测试:整体与类别准确率统计

模型训练完成后,我们需要在测试集上评估其性能,不仅要知道整体的准确率,有时还需要了解模型在各个类别上的表现。

首先来看整体准确率的计算代码:

复制代码
correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        images, labels = images.to(device), labels.to(device)
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

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

这里使用 torch.no_grad() 上下文管理器,因为测试阶段不需要计算梯度,这样可以节省内存并加快计算速度。通过遍历测试数据加载器 testloader,将图像和标签放到指定设备(CPU 或 GPU)上,模型 net 对图像进行前向传播得到输出 outputstorch.max(outputs.data, 1) 会返回每个样本输出中最大值的索引,也就是模型预测的类别。最后通过统计预测正确的样本数与总样本数的比例,得到整体准确率。

接下来是各类别准确率的统计代码:

复制代码
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data
        images, labels = images.to(device), labels.to(device)
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()
            class_total[label] += 1

for i in range(10):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i]))

我们初始化了两个列表 class_correctclass_total,分别用于记录每个类别预测正确的样本数和每个类别总的样本数。在遍历测试数据时,对于每个样本,判断预测是否正确,并根据标签更新对应类别的统计值。最后遍历每个类别,计算并打印出每个类别的准确率。这样可以帮助我们了解模型在哪些类别上表现较好,哪些类别上还有提升空间。

二、采用全局平均池化优化网络结构

全局平均池化(Global Average Pooling,GAP)是一种常用的网络结构优化手段,它可以替代全连接层的部分功能,减少模型参数数量,同时也有助于缓解过拟合问题。

下面是采用全局平均池化的网络结构定义代码:

复制代码
import torch.nn as nn
import torch.nn.functional as F

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 5)
        self.pool1 = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(16, 36, 5)
        self.pool2 = nn.MaxPool2d(2, 2)
        # 全局平均池化层
        self.aap = nn.AdaptiveAvgPool2d(1)
        self.fc3 = nn.Linear(36, 10)

    def forward(self, x):
        x = self.pool1(F.relu(self.conv1(x)))
        x = self.pool2(F.relu(self.conv2(x)))
        x = self.aap(x)
        x = x.view(x.shape[0], -1)
        x = self.fc3(x)
        return x

net = Net()
net = net.to(device)

print("net_gvp have {} parameters in total".format(sum(x.numel() for x in net.parameters())))

在这个网络结构中,首先通过卷积层 conv1conv2 提取图像特征,然后经过最大池化层 pool1pool2 缩小特征图尺寸。接着使用全局平均池化层 aap,它会将每个特征图平均成一个值,这样就将特征图转换为了固定长度的向量。最后通过一个全连接层 fc3 将特征映射到类别空间。

与使用全连接层直接处理卷积层输出相比,全局平均池化减少了大量的参数。我们可以通过 sum(x.numel() for x in net.parameters()) 统计模型的总参数数量,参数数量的减少有助于模型的部署和推理,同时也降低了过拟合的风险。

三、总结

通过模型测试,我们可以全面了解模型在测试集上的性能表现,包括整体准确率和各类别准确率。而采用全局平均池化则是一种有效的网络结构优化方法,能够在保证模型性能的前提下,减少参数数量,提升模型的泛化能力和推理效率。在实际的深度学习项目中,这些技术都是非常实用的工具,有助于我们开发出更高效、更准确的模型。

相关推荐
凳子(刘博浩)2 小时前
使用 PyTorch 实现 CIFAR-10 图像分类:从数据加载到模型训练全流程
人工智能·pytorch·分类
菜鸟‍2 小时前
【论文笔记】基于深度学习的图像分割研究综述 和 基于深度学习的二分图像分割综述
论文阅读·人工智能·深度学习
Juchecar2 小时前
软件开发属于哪种创新:从0到1,还是从1到n?
人工智能
星川皆无恙2 小时前
电商机器学习线性回归:基于 Python 电商数据爬虫可视化分析预测系统
大数据·人工智能·爬虫·python·机器学习·数据分析·线性回归
羽落·星辰2 小时前
NAFNet (Simple Baselines for Image Restoration) 阅读笔记
笔记·深度学习·机器学习
阿里云大数据AI技术3 小时前
阿里云AI搜索年度发布:开启Agent时代,重构搜索新范式
人工智能·搜索引擎
博睿谷IT99_3 小时前
语言大模型(LLM)与自然语言处理(NLP)
人工智能·自然语言处理
赴3353 小时前
LSTM自然语言处理情感分析项目(一)构建词汇表
人工智能·自然语言处理·lstm
ai_moe3 小时前
大白话讲UniVLA
人工智能·具身智能