深度学习模型优化:从全流程复盘到全局平均池化应用
在深度学习项目实践中,全面了解项目流程并掌握有效的模型优化技术至关重要。最近参与的会议既回顾了深度学习项目全流程,也深入讲解了全局平均池化这一优化手段,结合相关代码,我有不少收获,在此分享。
一、深度学习项目全流程回顾
(一)数据处理与模型训练流程
- 数据加载与转换:数据集以 NumPy 数组形式存储,加载后要将其转换为 Tensor。这样做一是能利用 GPU 实现高效运算,二是便于进行反归一化处理,让数据处于 0 - 1 的显示范围,更符合模型处理需求。
- 数据展示:当展示大量图像时,为避免过多占用内存,在信息展示完毕后,要及时关闭或释放相关内存资源,保障系统的内存使用效率。
(二)网络结构与后处理
- 网络结构:我们的模型由 CNN(卷积神经网络)和全连接层组成,包含 18 层卷积层以及 2 个全连接层,这样的结构能提取图像的特征并进行分类决策。
- 结果解读:模型输出的是各类别对应的置信度分数,分类时会选取置信度最高的分数及其对应的索引号,以此确定最终的预测类别。
(三)模型测试与评估
- 测试过程:使用测试集数据对模型进行推理和评估。过程中要进行 GPU/CPU 资源选择,之后通过正向传播得到各类别的置信度,再依据索引获取最终的预测类别。
- 准确性计算:通过检查预测类别与真实标签是否匹配,对总样本数进行累加,从而计算出分类准确率。从代码来看,首先初始化
correct和total为 0,然后在torch.no_grad()上下文管理器下,遍历测试集数据加载器testloader。将图像和标签移到指定设备(GPU 或 CPU)后,把图像输入模型得到输出outputs,通过torch.max获取预测类别predicted。total累加标签的数量,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_correct和class_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个新的特征通道。
更多推荐


所有评论(0)