在深度学习项目实践中,全面了解项目流程并掌握有效的模型优化技术至关重要。最近参与的会议既回顾了深度学习项目全流程,也深入讲解了全局平均池化这一优化手段,结合相关代码,我有不少收获,在此分享。

一、深度学习项目全流程回顾

(一)数据处理与模型训练流程

  • 数据加载与转换:数据集以 NumPy 数组形式存储,加载后要将其转换为 Tensor。这样做一是能利用 GPU 实现高效运算,二是便于进行反归一化处理,让数据处于 0 - 1 的显示范围,更符合模型处理需求。
  • 数据展示:当展示大量图像时,为避免过多占用内存,在信息展示完毕后,要及时关闭或释放相关内存资源,保障系统的内存使用效率。

(二)网络结构与后处理

  • 网络结构:我们的模型由 CNN(卷积神经网络)和全连接层组成,包含 18 层卷积层以及 2 个全连接层,这样的结构能提取图像的特征并进行分类决策。
  • 结果解读:模型输出的是各类别对应的置信度分数,分类时会选取置信度最高的分数及其对应的索引号,以此确定最终的预测类别。

(三)模型测试与评估

  • 测试过程:使用测试集数据对模型进行推理和评估。过程中要进行 GPU/CPU 资源选择,之后通过正向传播得到各类别的置信度,再依据索引获取最终的预测类别。
  • 准确性计算:通过检查预测类别与真实标签是否匹配,对总样本数进行累加,从而计算出分类准确率。从代码来看,首先初始化correcttotal为 0,然后在torch.no_grad()上下文管理器下,遍历测试集数据加载器testloader。将图像和标签移到指定设备(GPU 或 CPU)后,把图像输入模型得到输出outputs,通过torch.max获取预测类别predictedtotal累加标签的数量,correct累加预测与标签匹配的数量,最后计算并打印出整体准确率,如下所示:

python

运行

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))

同时,还可以计算每个类别的准确率,初始化class_correctclass_total为长度为 10 的列表,遍历测试集时,对每个样本的预测与标签进行比较,更新对应类别的正确数和总数,最后打印每个类别的准确率:

python

运行

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]))

(四)项目复盘

项目各环节,包括数据预处理、模型训练、测试等,逻辑是完整的。但测试集上的总体准确率仅为 66%,明显偏低,这表明模型还有很大的优化空间。

(五)技术核心认知

深度学习底层依赖矩阵运算,其理论基础可追溯到传统的数据处理与线性代数知识。对于不同类型的数据,有通用的模型选择建议:像序列这类有序数据,可考虑使用循环神经网络等模型;而对于图像这类无序但具有空间位置的数据,则适合用卷积神经网络。

二、全局平均池化:优化模型的利器

(一)全局平均池化介绍

全局平均池化是一种特殊的池化操作,它的池化核大小与输入图像大小完全一致。当输入尺寸为H×W且通道数为C时,全局平均池化会输出一个C维的向量。和标准池化相比,它能极大压缩参数数量,还能将高维特征图压缩为一维向量。

(二)全局平均池化在网络中的作用

它可以替代全连接层,实现特征的聚合与整合。能同时完成 “参数压缩” 和 “特征整合” 的双重功能,比传统先展平再连接的方法更加简洁高效。不过,它不宜放置在网络开头,应该在深层特征(包含中、高阶特征)提取之后使用,不然容易丢失重要信息。

从代码实现来看,我们定义了采用全局平均池化的Net类,在__init__方法中,设置了卷积层、池化层,并用AdaptiveAvgPool2d(1)实现全局平均池化,之后接全连接层fc3。前向传播过程中,经过卷积、池化、全局平均池化等操作,最后通过全连接层得到输出:

python

运行

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.fc1 = nn.Linear(10 * 5 * 5, 120)
        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)

同时,还可以计算模型的总参数量:

python

运行

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

(三)卷积层概念澄清

当输入是彩色图像(如 RGB 图像,有 3 个通道)时,卷积核默认维度为(高度 × 宽度 × 通道数),即一个卷积核默认为(h×w×3)。如果设置N个卷积核,就相当于执行N次独立的卷积操作,每次使用一个独立的卷积核进行运算,最后将结果累加,输出N个新的特征通道。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐