基于 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()) 统计模型的总参数数量,参数数量的减少有助于模型的部署和推理,同时也降低了过拟合的风险。

三、总结

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

相关推荐
知识分享小能手14 小时前
深度学习学习教程,从入门到精通,数值计算 — 知识点详解(4)
人工智能·深度学习·学习
三声三视14 小时前
审计清单函数名写成 def?tri-checklist 的 diff 解析在 Python 改名场景下悄悄翻车
人工智能·ai·skillhub·tri-checklist·tri-skills
嘟嘟嘟952714 小时前
Kubernetes 引入 KYAML:更安全的 YAML 子集
人工智能·架构·开源
智购科技自动售货机厂家14 小时前
2026自动售货机设备清洁效果自动验证:从图像比对到评分算法的工程实践~YH
人工智能·算法·计算机视觉
财迅通Ai14 小时前
光智科技全景透视:一家被“光学元件”标签遮蔽的稀散金属材料平台
大数据·人工智能·科技·光智科技
AI技术新视界14 小时前
失控的认知外包:大语言模型如何像病毒般入侵人类思维与社会生态
人工智能·llm·认知科学
后端小肥肠14 小时前
还在找PPT 生成工具?我集成了 GitHub 高星 Skill,自动匹配最优方案
人工智能·aigc·agent
打破砂锅问到底00714 小时前
115 行把 Qwen3-8B 跑进浏览器:WebLLM 本地推理实战
人工智能·ai·llm
二川bro14 小时前
幻觉≠提示词注入!拆解GPT‑6 Astra三层防御架构的致命短板
人工智能
雪庭14 小时前
pmb 面向 AI 编码智能体的本地记忆系统
人工智能