PyTorch是深度学习领域最受欢迎的框架之一,它不仅易于使用,而且还灵活高效。本文将详细讲解如何在PyTorch中实现MNIST分类任务,让您更加深入地了解PyTorch的使用。
准备工作
在实现MNIST分类任务之前,我们需要以下库:
- PyTorch 用于构建神经网络模型
- torchvision 用于获取MNIST数据集
- matplotlib 用于可视化结果
需要确保电脑上已经安装好了以上三个库。可以使用以下命令来安装:
pip install torch
pip install torchvision
pip install matplotlib
获取数据集
在PyTorch中,可以很方便地获取MNIST数据集。代码如下:
import torch
import torchvision
import torchvision.transforms as transforms
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.MNIST(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
shuffle=True, num_workers=2)
testset = torchvision.datasets.MNIST(root='./data', train=False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
shuffle=False, num_workers=2)
我们首先定义了一个transform对象,用于将数据集转换为张量,并进行归一化处理。接着我们使用torchvision.datasets.MNIST()函数来获取训练集和测试集,其中包括了下载、转换等操作,并使用torch.utils.data.DataLoader()将数据集分成batch,方便模型训练时的批量处理。
构建神经网络
PyTorch中构建神经网络一般分为两个部分。首先需要定义一个继承自torch.nn.Module的类,该类提供了神经网络的整体结构。然后需要定义一个继承自torch.nn.Module的类,该类提供了神经网络的整体结构。
下面给出一个基本的MNIST分类模型例子,仅包含了一个全连接层:
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(28 * 28, 10)
def forward(self, x):
x = x.view(x.size(0), -1)
x = self.fc1(x)
return F.log_softmax(x, dim=1)
在__init__()函数中定义了一个全连接层,其中输入是28*28的像素矢量,输出是10个类别,即0~9。在forward()函数中,我们将数据展开成一维,然后使用全连接层,最后使用log_softmax()进行输出。
训练神经网络
将前面的数据集和神经网络结构传入下面的代码来训练模型:
import torch.optim as optim
net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.5)
for epoch in range(10):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 100 == 99:
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 100))
running_loss = 0.0
代码中,我们首先定义了一个网络对象net。然后定义了一个损失函数criterion和优化器optimizer,使用nn.CrossEntropyLoss()作为损失函数,使用optim.SGD()作为优化器。接着使用for循环来进行多次epoch的训练,每次训练时将数据分批处理,并通过.net(inputs)函数得到模型的输出,使用损失函数计算损失并进行反向传播和参数更新。
测试神经网络
我们可以使用以下代码来测试训练好的神经网络:
correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data
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))
该代码通过遍历测试集,并将结果与真实标签进行比较,得出神经网络的准确率。
示例说明
下面我们通过两条示例说明MNIST分类任务的实现:
示例一
在上一篇博客《PyTorch中的神经网络FashionMNIST分类任务》中,我们讲解了如何使用这个框架实现FashionMNIST分类任务。在这个示例中,我们将很快理解很多东西是如何使用的。我们将使用一个全连接层来定义网络结构。以下代码展示了如何定义模型。
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(28 * 28, 10)
def forward(self, x):
x = x.view(-1, 28 * 28)
x = self.fc1(x)
x = F.log_softmax(x, dim=1)
return x
我们接下来需要使用数据加载器来导入FashionMNIST数据集。使用以下代码。
import torch
import torchvision
import torchvision.transforms as transforms
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.FashionMNIST(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
shuffle=True, num_workers=2)
testset = torchvision.datasets.FashionMNIST(root='./data', train=False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
shuffle=False, num_workers=2)
classes = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
我们将使用SGD作为优化器和交叉熵损失函数。在PyTorch中,实现该任务非常容易。使用以下代码即可。
import torch.optim as optim
net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)
if __name__ == '__main__':
for epoch in range(10):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 200 == 199:
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 200))
running_loss = 0.0
使用以下代码来保存神经网络的模型参数:
PATH = './fashion_mnist_net.pth'
torch.save(net.state_dict(), PATH)
接下来,我们可以使用以下代码在测试集上测试训练好的神经网络:
correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data
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))
示例二
在这个例子中,我们将使用卷积神经网络(CNN)来解决MNIST分类问题。在以下代码中,我们定义了一个简单的卷积神经网络,其中包括两个卷积层和两个全连接层:
import torch
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.Dropout2d(0.25)
self.dropout2 = nn.Dropout2d(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
net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adadelta(net.parameters(), lr=1.0)
下面是训练代码:
if __name__ == '__main__':
for epoch in range(1, 15):
train_loss, correct, total = 0, 0, 0
net.train()
for batch_idx, (data, target) in enumerate(trainloader):
optimizer.zero_grad()
output = net(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
train_loss += loss.item()
_, predicted = torch.max(output.data, 1)
total += target.size(0)
correct += (predicted == target).sum().item()
if batch_idx % 100 == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)] Loss: {:.6f} Acc: {:.6f}'.format(
epoch, batch_idx * len(data), len(trainloader.dataset),
100. * batch_idx / len(trainloader), train_loss/(batch_idx+1), 100.*correct/total))
使用以下代码在测试集上测试训练好的神经网络:
correct, total = 0, 0
net.eval()
with torch.no_grad():
for batch_idx, (data, target) in enumerate(testloader):
output = net(data)
_, predicted = torch.max(output.data, 1)
total += target.size(0)
correct += (predicted == target).sum().item()
print('Test Acc: {:.6f}'.format(100.*correct/total))
这里我们使用Adadelta作为优化器,并在训练中使用了torch.no_grad()函数,以便在计算准确率时不会计算梯度。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:PyTorch中的神经网络 Mnist 分类任务 - Python技术站