Handwritten digit recognition on MNIST dataset based on simple CNN
创始人
2024-06-02 15:59:16
0

文章目录

  • Handwritten digit recognition on MNIST dataset based on simple CNN
    • Prepare Dataset
    • Design Model
    • Construct Loss and Optimizer
    • Training
    • Testing
    • Visualization
    • Save
    • Complete Code

Handwritten digit recognition on MNIST dataset based on simple CNN

Prepare Dataset

MNIST Introduction:http://yann.lecun.com/exdb/mnist/

MNIST Code:https://pytorch.org/vision/stable/generated/torchvision.datasets.MNIST.html#torchvision.datasets.MNIST

torchvision.datasets.MNIST(root, train, transform, target_transform, download)

Parameters:

  • root (string) – Root directory of dataset where MNIST/raw/train-images-idx3-ubyte and MNIST/raw/t10k-images-idx3-ubyte exist.
  • train (bool, optional) – If True, creates dataset from train-images-idx3-ubyte, otherwise from t10k-images-idx3-ubyte.
  • transform (callable, optional) – A function/transform that takes in an PIL image and returns a transformed version.
  • target_transform (callable, optional) – A function/transform that takes in the target and transforms it.
  • download (bool, optional) – If True, downloads the dataset from the internet and puts it in root directory. If dataset is already downloaded, it is not downloaded again.
# 加载MNIST数据集 len(train_dataset): 训练集5000 验证集1000 测试集1000
train_dataset = datasets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True)
train_dataset, val_dataset = torch.utils.data.random_split(train_dataset, [50000, 10000])
test_dataset = datasets.MNIST(root='./data', train=False, transform=transforms.ToTensor(), download=True)# 数据加载器
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=64, shuffle=False)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

Design Model

# 定义神经网络
class Model(nn.Module):def __init__(self):super(Model, self).__init__()self.conv1 = nn.Conv2d(1, 10, kernel_size=5)self.conv2 = nn.Conv2d(10, 20, kernel_size=5)self.pool = nn.MaxPool2d(2)self.fc1 = nn.Linear(320, 50)self.fc2 = nn.Linear(50, 10)def forward(self, x):x = self.pool(nn.functional.relu(self.conv1(x)))x = self.pool(nn.functional.relu(self.conv2(x)))x = x.view(-1, 320)x = nn.functional.relu(self.fc1(x))x = self.fc2(x)return nn.functional.log_softmax(x, dim=1)# 调用网络
model = Model()

Additions:

  • GPU:移植到GPU上运行(model + training + testing)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")if torch.cuda.is_available():device = torch.device("cuda")print("Using GPU:", torch.cuda.get_device_name())
else:device = torch.device("cpu")print("Using CPU")# model
model.to(device)
# training + testing
inputs, labels = inputs.to(device), labels.to(device)  # 加载到GPU

Construct Loss and Optimizer

# 损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

Training

# 训练模型
def train(model, train_loader, val_loader, optimizer, criterion, num_epochs):train_losses = []val_losses = []val_accs = []for epoch in range(num_epochs):train_loss = 0.0model.train()for i, (inputs, labels) in enumerate(train_loader):optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()train_losses.append(train_loss / (i + 1))val_loss = 0.0val_acc = 0.0model.eval()with torch.no_grad():for i, (inputs, labels) in enumerate(val_loader):inputs, labels = inputs.to(device), labels.to(device)  # 加载到GPUoutputs = model(inputs)loss = criterion(outputs, labels)val_loss += loss.item()_, preds = torch.max(outputs, 1)val_acc += torch.sum(preds == labels.data)val_losses.append(val_loss / (i + 1))val_accs.append(val_acc / len(val_dataset))print('Epoch: {}, Train Loss: {:.4f}, Val Loss: {:.4f}, Val Acc: {:.4f}'.format(epoch + 1, train_losses[-1],val_losses[-1], val_accs[-1]))return train_losses# 训练
train_losses = train(model, train_loader, val_loader, optimizer, criterion, num_epochs=10)

Testing

# 测试模型
model.eval()
test_loss = 0.0
test_acc = 0.0
with torch.no_grad():for inputs, labels in test_loader:inputs, labels = inputs.to(device), labels.to(device)  # 加载到GPUoutputs = model(inputs)loss = criterion(outputs, labels)test_loss += loss.item()_, preds = torch.max(outputs, 1)test_acc += torch.sum(preds == labels.data)
test_loss /= len(test_loader)
test_acc /= len(test_dataset)
print('Test Loss: {:.4f}, Test Acc: {:.4f}'.format(test_loss, test_acc))

Visualization

# 可视化训练过程中的损失值
plt.plot(train_losses)
plt.xlabel('Epoch')
plt.ylabel('Train Loss')
plt.show()  # 训练损失逐渐下降,并且在训练集和验证集上的损失越来越接近,表明模型已经开始收敛

Save

# 保存模型
torch.save(model.state_dict(), './cnn_mnist.pth')
# 加载模型
model = Model()
model.load_state_dict(torch.load('./cnn_mnist.pth'))
# 打印模型结构
print(model)
# 打印模型参数
# for name, param in model.named_parameters():
#     if param.requires_grad:
#         print(name, param.data)

Complete Code

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.datasets as datasets
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader# 加载MNIST数据集 len(train_dataset): 训练集5000 验证集1000 测试集1000
train_dataset = datasets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True)
train_dataset, val_dataset = torch.utils.data.random_split(train_dataset, [50000, 10000])
test_dataset = datasets.MNIST(root='./data', train=False, transform=transforms.ToTensor(), download=True)# 数据加载器
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=64, shuffle=False)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)# 定义神经网络
class Model(nn.Module):def __init__(self):super(Model, self).__init__()self.conv1 = nn.Conv2d(1, 10, kernel_size=5)self.conv2 = nn.Conv2d(10, 20, kernel_size=5)self.pool = nn.MaxPool2d(2)self.fc1 = nn.Linear(320, 50)self.fc2 = nn.Linear(50, 10)def forward(self, x):x = self.pool(nn.functional.relu(self.conv1(x)))x = self.pool(nn.functional.relu(self.conv2(x)))x = x.view(-1, 320)x = nn.functional.relu(self.fc1(x))x = self.fc2(x)return nn.functional.log_softmax(x, dim=1)# 调用网络
model = Model()device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")if torch.cuda.is_available():device = torch.device("cuda")print("Using GPU:", torch.cuda.get_device_name())
else:device = torch.device("cpu")print("Using CPU")model.to(device)# 损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)# 训练模型
def train(model, train_loader, val_loader, optimizer, criterion, num_epochs):train_losses = []val_losses = []val_accs = []for epoch in range(num_epochs):train_loss = 0.0model.train()for i, (inputs, labels) in enumerate(train_loader):inputs, labels = inputs.to(device), labels.to(device)  # 加载到GPUoptimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()train_losses.append(train_loss / (i + 1))val_loss = 0.0val_acc = 0.0model.eval()with torch.no_grad():for i, (inputs, labels) in enumerate(val_loader):inputs, labels = inputs.to(device), labels.to(device)  # 加载到GPUoutputs = model(inputs)loss = criterion(outputs, labels)val_loss += loss.item()_, preds = torch.max(outputs, 1)val_acc += torch.sum(preds == labels.data)val_losses.append(val_loss / (i + 1))val_accs.append(val_acc / len(val_dataset))print('Epoch: {}, Train Loss: {:.4f}, Val Loss: {:.4f}, Val Acc: {:.4f}'.format(epoch + 1, train_losses[-1],val_losses[-1], val_accs[-1]))return train_losses# 训练
train_losses = train(model, train_loader, val_loader, optimizer, criterion, num_epochs=10)# 测试模型
model.eval()
test_loss = 0.0
test_acc = 0.0
with torch.no_grad():for inputs, labels in test_loader:inputs, labels = inputs.to(device), labels.to(device)  # 加载到GPUoutputs = model(inputs)loss = criterion(outputs, labels)test_loss += loss.item()_, preds = torch.max(outputs, 1)test_acc += torch.sum(preds == labels.data)
test_loss /= len(test_loader)
test_acc /= len(test_dataset)
print('Test Loss: {:.4f}, Test Acc: {:.4f}'.format(test_loss, test_acc))# 可视化训练过程中的损失值
plt.plot(train_losses)
plt.xlabel('Epoch')
plt.ylabel('Train Loss')
plt.show()  # 训练损失逐渐下降,并且在训练集和验证集上的损失越来越接近,表明模型已经开始收敛# 保存模型
torch.save(model.state_dict(), './cnn_mnist.pth')
# 加载模型
model = Model()
model.load_state_dict(torch.load('./cnn_mnist.pth'))
# 打印模型结构
print(model)
# 打印模型参数
# for name, param in model.named_parameters():
#     if param.requires_grad:
#         print(name, param.data)
Using GPU: NVIDIA GeForce GTX 1050 Ti
Epoch: 1, Train Loss: 1.0488, Val Loss: 0.3327, Val Acc: 0.8924
Epoch: 2, Train Loss: 0.2292, Val Loss: 0.2650, Val Acc: 0.9176
Epoch: 3, Train Loss: 0.1465, Val Loss: 0.1260, Val Acc: 0.9621
Epoch: 4, Train Loss: 0.1132, Val Loss: 0.1200, Val Acc: 0.9623
Epoch: 5, Train Loss: 0.0953, Val Loss: 0.0961, Val Acc: 0.9698
Epoch: 6, Train Loss: 0.0837, Val Loss: 0.1250, Val Acc: 0.9613
Epoch: 7, Train Loss: 0.0746, Val Loss: 0.0734, Val Acc: 0.9769
Epoch: 8, Train Loss: 0.0671, Val Loss: 0.0719, Val Acc: 0.9765
Epoch: 9, Train Loss: 0.0621, Val Loss: 0.0730, Val Acc: 0.9772
Epoch: 10, Train Loss: 0.0570, Val Loss: 0.0606, Val Acc: 0.9809
Test Loss: 0.0527, Test Acc: 0.9835
Model((conv1): Conv2d(1, 10, kernel_size=(5, 5), stride=(1, 1))(conv2): Conv2d(10, 20, kernel_size=(5, 5), stride=(1, 1))(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(fc1): Linear(in_features=320, out_features=50, bias=True)(fc2): Linear(in_features=50, out_features=10, bias=True)
)

相关内容

热门资讯

小学三年级作文400字【实用... 小学三年级作文400字 篇一爱护小动物我家附近有一个小公园,里面有很多小动物。我喜欢去那里看它们,但...
三年级科幻作文智能干家务的机... 三年级科幻作文智能干家务的机器人 篇一智能家务机器人的出现在未来的世界里,科技发展迅速,人们的生活变...
三年级下册我做了一项小实验作... 三年级下册我做了一项小实验作文 篇一标题:探究种子发芽的条件在三年级下册的科学课上,我们进行了一项小...
三年级学生感受作文(优选6篇... 三年级学生感受作文 篇一我喜欢上学的理由我是一个三年级的学生,我非常喜欢上学。每天早上,当妈妈叫我起...
小学三年级说好普通话作文(优... 小学三年级说好普通话作文 篇一我要当一个好学生我是一个小学三年级的学生,我知道要成为一个好学生,首先...
三年级的黄果树瀑布的作文怎么... 篇一:三年级的黄果树瀑布之旅黄果树瀑布是中国贵州省的一处自然景观,也是我国最大的瀑布之一。作为一个三...
三年级作文抓鱼趣事21篇【最... 三年级作文抓鱼趣事21篇 篇一:我和小伙伴们的抓鱼经历在一个阳光明媚的周末,我和几个小伙伴决定去河边...
三年级作文:踢足球(精简6篇... 三年级作文:踢足球 篇一踢足球是我最喜欢的运动之一。我每天放学后都会和朋友们一起来到学校的操场上踢球...
写快乐的一件事三年级的作文3... 篇一:快乐的一件事在我三年级的时候,有一次我和妈妈一起去公园玩,那是一个阳光明媚的周末早上。我们带了...
秦皇岛黄金海岸游记三年级作文... 秦皇岛黄金海岸游记三年级作文 篇一我和家人去了秦皇岛黄金海岸度假,这是我人生中最美好的一次旅行。黄金...
一次旅行的经历作文三年级作文... 一次旅行的经历作文三年级作文 篇一我最难忘的一次旅行是和爸爸妈妈去海边玩的那次。那是一个阳光明媚的早...
三年级看图写作文借伞【优质6... 三年级看图写作文借伞 篇一今天,我们班级进行了一次有趣的活动,每个同学都被要求写一篇关于“借伞”的作...
三年级上册语文句子复习(优质... 三年级上册语文句子复习 篇一在三年级上册的语文学习中,我们学习了许多句子,现在让我们来进行一次复习吧...
三年级作文这一次我被感动了4... 篇一:三年级作文这一次我被感动了43篇这一次我被感动了43篇作文,这是我在三年级最难忘的一次经历。这...
木鱼岛小学三年级作文300字... 木鱼岛小学三年级作文300字 篇一我的梦想我是木鱼岛小学三年级的学生,我的名字叫小明。我有一个美丽的...
三年级的海边作文200字【精... 三年级的海边作文200字 篇一我在海边玩耍今天是个晴朗的日子,我和爸爸妈妈一起去海边玩耍。海边的沙滩...
三年级作文我的爸爸300字(... 三年级作文我的爸爸300字 篇一我的爸爸是一个非常疼爱我的人。他虽然有时候工作很忙,但是每天晚上都会...
我的植物朋友三年级作文(精彩... 我的植物朋友三年级作文 篇一我的植物朋友我家有一盆小红花,它是我的植物朋友。我每天都会给它浇水,晒太...
我的中秋节三年级作文400字... 我的中秋节三年级作文400字 篇一我和家人一起过中秋节中秋节是中国的传统节日,我和家人一起过了一个特...
三年级作文我可爱的小妹妹(推... 三年级作文我可爱的小妹妹 篇一我家有一个可爱的小妹妹,她叫小婷婷。她今年三岁,是一个活泼开朗的小女孩...