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

三、总结

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

相关推荐
jerryinwuhan6 小时前
对图片进行解释的大语言模型
人工智能·语言模型·自然语言处理
golang学习记6 小时前
Anthropic 发布轻量级模型Claude Haiku 4.5:更快,更便宜,更聪明
人工智能
bin91537 小时前
当AI开始‘映射‘用户数据:初级Python开发者的创意‘高阶函数‘如何避免被‘化简‘?—— 老码农的函数式幽默
开发语言·人工智能·python·工具·ai工具
CoovallyAIHub7 小时前
Mamba-3震撼登场!Transformer最强挑战者再进化,已进入ICLR 2026盲审
深度学习·算法·计算机视觉
飞哥数智坊7 小时前
一文看懂 Claude Skills:让你的 AI 按规矩高效干活
人工智能·claude
JY190641068 小时前
从点云到模型,徕卡RTC360如何搞定铝单板测量?
深度学习
IT_陈寒8 小时前
5个Java 21新特性实战技巧,让你的代码性能飙升200%!
前端·人工智能·后端
dlraba8028 小时前
YOLOv3:目标检测领域的经典之作
人工智能·yolo·目标检测
科新数智8 小时前
破解商家客服困局:真人工AI回复如何成为转型核心
人工智能·#agent #智能体
szxinmai主板定制专家10 小时前
【NI测试方案】基于ARM+FPGA的整车仿真与电池标定
arm开发·人工智能·yolo·fpga开发