深度学习复现:CIFAR-10 数据集任务的实现
一、数据预处理
数据是机器学习的基石,对数据进行恰当的预处理至关重要。在本次实验中,我们使用了 PyTorch 提供的 torchvision.datasets.CIFAR10
来加载数据集。CIFAR-10 数据集包含 60,000 张 32×32 的彩色图像,分为 10 个类别,每个类别有 6,000 张图像。其中,训练集包含 50,000 张图像,测试集包含 10,000 张图像。
为了提高模型的泛化能力,我们对数据进行了标准化处理。具体来说,我们使用了 torchvision.transforms
模块中的 Compose
函数,将图像转换为张量(ToTensor
),并对其进行了标准化(Normalize
)。标准化的均值和标准差分别为 (0.5, 0.5, 0.5)
,这有助于将像素值归一化到 [-1, 1] 的范围内,从而加速模型的收敛。
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
通过 DataLoader
,我们可以方便地加载和迭代数据集,设置批量大小为 4,并在训练时对数据进行随机打乱,以增加模型的鲁棒性。
二、模型构建
接下来,我们构建了一个简单的卷积神经网络(CNN)。CNN 在图像处理任务中表现出色,因为它能够自动提取图像的局部特征。我们的网络结构如下:
第一层:包含 16 个卷积核,卷积核大小为 5×5,步长为 1,之后接一个最大池化层,池化窗口大小为 2×2。
第二层:包含 36 个卷积核,卷积核大小为 3×3,步长为 1,之后接一个最大池化层,池化窗口大小为 2×2。
全连接层:将卷积层的输出展平后,先经过一个包含 128 个神经元的全连接层,再经过一个包含 10 个神经元的全连接层,输出类别概率。
class CNNNet(nn.Module):def __init__(self):super(CNNNet, self).__init__()self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=5, stride=1)self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)self.conv2 = nn.Conv2d(in_channels=16, out_channels=36, kernel_size=3, stride=1)self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)self.fc1 = nn.Linear(1296, 128)self.fc2 = nn.Linear(128, 10)def forward(self, x):x = self.pool1(F.relu(self.conv1(x)))x = self.pool2(F.relu(self.conv2(x)))x = x.view(-1, 36 * 6 * 6)x = F.relu(self.fc2(F.relu(self.fc1(x))))return x
三、训练过程
在训练过程中,我们使用了交叉熵损失函数(CrossEntropyLoss
)和随机梯度下降优化器(SGD)。学习率设置为 0.001,并引入了动量(momentum=0.9)来加速收敛并减少震荡。
训练过程持续了 10 个 epoch,每个 epoch 包含约 12,500 个 mini-batch。在每个 mini-batch 中,我们计算损失值并进行反向传播,更新模型的权重。通过打印每 2,000 个 mini-batch 的损失值,我们可以观察到模型在训练过程中的收敛情况。
for epoch in range(10):running_loss = 0.0for i, data in enumerate(trainloader, 0):inputs, labels = datainputs, labels = inputs.to(device), labels.to(device)optimizer.zero_grad()outputs = net(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()if i % 2000 == 1999:print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000))running_loss = 0.0
从输出的损失值来看,模型的损失在逐渐降低,这表明模型正在学习数据中的模式。
四、测试与评估
训练完成后,我们使用测试集对模型的性能进行了评估。测试集包含了模型未曾见过的数据,因此可以很好地衡量模型的泛化能力。
我们定义了一个函数 imshow
来显示图像,并打印出图像的真实标签。通过观察模型的预测结果与真实标签的对比,我们可以直观地了解模型的分类效果。
def imshow(img):img = img / 2 + 0.5npimg = img.numpy()plt.imshow(np.transpose(npimg, (1, 2, 0)))plt.show()datatier = iter(testloader)
images, labels = next(datatier)
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
此外,我们还可以计算模型在测试集上的准确率,以更全面地评估模型的性能。
五、总结
我们可以尝试以下几种方法来进一步优化模型性能:
数据增强:通过对训练数据进行旋转、裁剪、翻转等操作,增加数据的多样性,提高模型的泛化能力。
模型优化:尝试更复杂的网络结构,如更深的网络、添加批量归一化(Batch Normalization)等。
超参数调整:调整学习率、优化器、批量大小等超参数,寻找更优的训练配置。
正则化技术:引入 Dropout、L2 正则化等技术,防止模型过拟合。