共计 2926 个字符,预计需要花费 8 分钟才能阅读完成。
提醒:本文最后更新于 2023-10-07 17:37,文中所关联的信息可能已发生改变,请知悉!
数据集
MNIST 是一个大型数据库,其中包含手写数字。它通常被用作图像处理机器学习的基准测试。该数据库包含 60,000 个训练图像和 10,000 个测试图像。每个图像都是 28×28 的灰度图像,表示 0 到 9 之间的数字。
数据预处理
首先,我们需要将图像数据转换为可以被神经网络接受的格式。我们可以使用 torchvision
库中的 transforms
模块来进行数据预处理。我们将图像转换为张量,并将其归一化以使其具有零均值和单位方差。
import torch
from torchvision import datasets, transforms
# 数据预处理
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))])
# 加载数据集
trainset = datasets.MNIST('./data', download=True, train=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
testset = datasets.MNIST('./data', download=True, train=False, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=True)
定义神经网络模型
我们可以使用 PyTorch 中的 nn
模块来定义神经网络模型。在这里,我们将使用一个简单的卷积神经网络(CNN)来处理 MNIST 数据集。该模型包含两个卷积层、两个池化层和两个全连接层。
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.dropout1 = nn.Dropout(0.25)
self.dropout2 = nn.Dropout(0.5)
self.fc1 = nn.Linear(9216, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = F.max_pool2d(x, 2)
x = self.dropout1(x)
x = torch.flatten(x, 1)
x = self.fc1(x)
x = F.relu(x)
x = self.dropout2(x)
x = self.fc2(x)
output = F.log_softmax(x, dim=1)
return output
训练模型
训练模型的关键步骤如下:
import torch.optim as optim
# 定义优化器和损失函数
model = Net()
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()
# 训练模型
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
num_epochs = 10
for epoch in range(num_epochs):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch + 1}, Loss: {running_loss / len(trainloader)}")
print("Finished Training")
在这个代码片段中,我们使用 Adam 优化器来更新模型的权重和偏差,以最小化交叉熵损失。我们迭代训练数据集多个周期(这里选择了 10 个周期),在每个周期内对所有的批次进行训练。在每个批次中,我们计算损失、执行反向传播和权重更新,最后计算并输出每个周期的平均损失。
评估模型
评估模型的代码已经在之前提到的代码片段中给出,但是为了更全面,这里再次列出:
test_loss = 0
correct = 0
with torch.no_grad(): # 禁止梯度计算
for data, target in testloader:
images, labels = data.to(device), target.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
test_loss += criterion(outputs, labels).item()
correct += (predicted == labels).sum().item()
test_loss /= len(testloader.dataset)
print('Test Loss: {:.4f}'.format(test_loss))
print('Test Accuracy: {}/{} ({:.2f}%)\n'.format(correct, len(testloader.dataset),
100 * correct / len(testloader.dataset)))
在这段代码中,我们遍历测试数据集,计算模型在每个图像上的损失和预测标签。然后,我们汇总这些信息来计算平均损失和准确率,以评估模型的性能。最后,我们输出测试集上的损失和准确率。这些指标可以帮助我们判断模型是否有效地泛化到新数据。
运行结果
Epoch 1, Loss: 0.23964141234844874
Epoch 2, Loss: 0.09505011013218526
Epoch 3, Loss: 0.07344594778967643
Epoch 4, Loss: 0.05976587735257471
Epoch 5, Loss: 0.05009076422531414
Epoch 6, Loss: 0.044607697039664385
Epoch 7, Loss: 0.040750773838482426
Epoch 8, Loss: 0.03625520611176456
Epoch 9, Loss: 0.033343519127966445
Epoch 10, Loss: 0.03101113824747073
Finished Training
Test Loss: 0.0009
Test Accuracy: 9838/10000 (98.38%)
正文完