📜  PyTorch中的图像识别的MNIST数据集(1)

📅  最后修改于: 2023-12-03 14:46:48.618000             🧑  作者: Mango

PyTorch中的图像识别的MNIST数据集

在计算机视觉中,图像识别任务是非常重要的。PyTorch是一种基于Python的开源机器学习框架,它非常适合用于图像识别任务的处理。在PyTorch中,可以使用MNIST数据集来进行图像识别任务。

MNIST数据集

MNIST是一组手写数字图像数据集,包含了60000个训练样本和10000个测试样本。它是计算机视觉领域中的一个经典数据集,也被广泛用于训练各种图像识别模型。

MNIST数据集的图片都是由28x28个像素组成的,并且每张图片都有一个相应的数字标签,表示这张图片上的手写数字是什么。

PyTorch中的MNIST图像识别

为了在PyTorch中进行MNIST图像识别任务,首先需要导入相应的库。以下是一个简单的代码片段,用于导入PyTorch和MNIST数据集。

import torch
import torchvision.datasets as dsets
import torchvision.transforms as transforms

train_dataset = dsets.MNIST(root='./data', 
                            train=True, 
                            transform=transforms.ToTensor(),  
                            download=True)
test_dataset = dsets.MNIST(root='./data', 
                           train=False, 
                           transform=transforms.ToTensor())

在此代码片段中,首先导入了PyTorch库,然后导入了torchvision.datasetstorchvision.transforms模块。torchvision.datasets模块包含了许多常用的数据集,包括MNIST数据集。torchvision.transforms模块包含了许多常用的图像变换方法,如ToTensor()方法,用于将图像转换为PyTorch中的Tensor类型。

接下来,利用dsets.MNIST方法,可以获取MNIST数据集中的训练数据和测试数据。在获取训练数据时,需要指定train=True,同时指定数据集的根目录root,以及图像变换方法transformdownload=True表示如果数据集不存在,会自动下载数据集。获取测试数据时,需要将train=False

接下来,可以使用PyTorch中的DataLoader方法,将MNIST数据集中的图像和标签加载进来,并进行相应的参数配置。

batch_size = 100

train_loader = torch.utils.data.DataLoader(dataset=train_dataset, 
                                           batch_size=batch_size, 
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset, 
                                          batch_size=batch_size, 
                                          shuffle=False)

这里使用了batch_size参数,可以控制每次载入的数据量。然后利用torch.utils.data.DataLoader方法,分别将训练数据和测试数据加载进来,并指定相应的参数,如batch_sizeshuffle等。

我们可以定义一个卷积神经网络(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, kernel_size=5, padding=2)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=5, padding=2)
        self.fc1 = nn.Linear(7*7*64, 1024)
        self.fc2 = nn.Linear(1024, 10)
        
    def forward(self, x):
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2(x), 2))
        x = x.view(-1, 7*7*64)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

这里我们定义了一个名为Net的模型。该模型包含了两个卷积层、两个全连接层和相关的ReLU和max-pooling等层。在模型中,我们还定义了相应的前向传播函数forward,将输入数据x作为模型的输入,通过定义的各种层进行前向传播计算,并返回最终的输出结果。

接下来,可以定义模型的一些超参数,如学习率等。

learning_rate = 0.001
num_epochs = 10

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

这里定义了一个学习率learning_rate和迭代次数num_epochs,以及GPU/CPU设备device

我们可以定义训练过程中的损失函数和优化器,并对每一轮迭代进行训练,同时记录一下训练和测试的准确率。

net = Net().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=learning_rate)

train_accs = []
test_accs = []

for epoch in range(num_epochs):
    train_acc = 0
    test_acc = 0
    
    for i, (images, labels) in enumerate(train_loader):
        images = images.to(device)
        labels = labels.to(device)

        optimizer.zero_grad()
        outputs = net(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        _, train_predicted = torch.max(outputs.data, 1)
        train_acc += torch.sum(train_predicted == labels).item()
        
        if (i+1) % 100 == 0:
            print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' 
                  .format(epoch+1, num_epochs, i+1, len(train_dataset)//batch_size, loss.item()))
    
    train_accs.append(train_acc/len(train_dataset))
    
    with torch.no_grad():
        for images, labels in test_loader:
            images = images.to(device)
            labels = labels.to(device)

            outputs = net(images)
            _, test_predicted = torch.max(outputs.data, 1)
            test_acc += torch.sum(test_predicted == labels).item()

    test_accs.append(test_acc/len(test_dataset))
    print('Epoch [{}/{}], Train Accuracy: {:.2f}%, Test Accuracy: {:.2f}%' 
          .format(epoch+1, num_epochs, train_accs[-1]*100, test_accs[-1]*100))

首先,我们定义了一个Net的实例net,并将该实例移动到GPU设备上。接下来,定义了损失函数criterion和优化器optimizer,用于模型的训练操作。训练过程中,我们逐轮迭代,每次迭代中,对训练数据经过前向传播计算得到输出,再与对应的标签进行比较计算出损失,通过损失值和反向传播计算出各参数的梯度,最后更新各参数。同时在每一轮迭代过程中,我们记录训练和测试的准确率,以便最终评估模型的性能。

在训练完毕后,我们可以绘制出训练和测试的准确率图像。

import matplotlib.pyplot as plt

plt.plot(train_accs, label='Train Accuracy')
plt.plot(test_accs, label='Test Accuracy')
plt.legend()
plt.show()

最后,我们可以使用训练好的模型对新的图片进行识别。

import cv2
import numpy as np

def predict(image_path):
    net.eval()
    img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    img = cv2.resize(img, (28,28))
    img = np.array([img], dtype=np.float32)/255.0
    img = torch.from_numpy(img).unsqueeze(1)
    pred = net(img.to(device))
    _, predicted = torch.max(pred.data, 1)
    return predicted.item()

image_path = 'test_img.png'
predicted = predict(image_path)
print('Predicted digit:', predicted)

在此代码片段中,定义了一个predict函数,用于对新的输入图片进行识别。该函数包含了图像的读取、缩放、类型转换等操作,最终利用训练好的模型进行前向传播,并返回识别结果。在示例中,我们读取一张名为test_img.png的测试图片,通过predict函数对其进行识别,并输出识别结果。

结论

本篇文章介绍了如何使用PyTorch中的MNIST数据集进行手写数字的图像识别任务。我们首先介绍了MNIST数据集的基本情况,然后通过代码片段的介绍介绍了如何利用PyTorch中相应的库导入MNIST数据集,并使用DataLoader方法对其进行数据加载和处理。接着,我们定义了一个卷积神经网络模型进行训练,并在训练过程中评估模型的性能。最终,我们还介绍了如何利用训练好的模型对新的图片进行识别,并输出识别结果。