第一步:下载数据源并进行预处理
import torch
import torchvision
import torchvision.transforms as transforms
# # 定义预处理函数,这些预处理一次放在compose函数中
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize([0.5], [0.5])])
# 导入mnist数据源
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=train_batch_size, shuffle=True)
# 将数据源转化为可迭代的 训练集和测试集
testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=test_batch_size, shuffle=False)
第二步:定义超参数
# 训练集分组大小
train_batch_size = 64
# 测试集分组大小
test_batch_size = 8
# 学习率
learning_rate = 0.01
# 训练次数
num_epoches = 10
# SGD算法的动量参数
momentum = 0.5
第三步:定义神经网络结构
我们先架构好神经网络的结构:卷积层和池化层如下,全连接层略

整个网络结构为:输入→卷积层1→池化层1→卷积层2→池化层2→全连接层1→全连连接层2→全连接层3→输出
注:分类器如softmax等一般不写在网络结构中
代码:
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, 6, 5)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(16 * 4 * 4, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# 卷积层1
x = F.relu(self.conv1(x))
# 池化层1
x = self.pool1(x)
# 卷积层2
x = F.relu(self.conv2(x))
# 池化层2
x = self.pool2(x)
# 将输出展平
x = x.view(-1, 16 * 4 * 4)
# 全连接层1
x = F.relu(self.fc1(x))
# 全连接层2
x = F.relu(self.fc2(x))
# 全连接层3
x = F.relu(self.fc3(x))
return x
# 定义神经网络
net = Net()
注:池化层理论上是可以不用写入神经网络结构的(因为没有参数),在这里为了方便理解,我把池化层加到了神经网络结构中(其实就是一个函数)
第四步:定义损失函数和优化器
import torch.optim as optim
# 定义损失函数(分类问题一般使用交叉熵损失函数
criterion = nn.CrossEntropyLoss()
# 定义优化器(使用随机梯度下降算法,并加入动量)
optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=momentum)
第五步:开始训练网络并输出每一次训练的损失值
# ================================train========================================
for epoch in range(num_epoches):
running_loss = 0.0
num = 0
for i, data in enumerate(trainloader, 0):
# 获取输入和输出
inputs, labels = data
# 参数梯度清零
optimizer.zero_grad()
# 向前传播
outputs = net(inputs)
# 反向传播,计算梯度
loss = criterion(outputs, labels)
loss.backward()
# 执行优化器,使用SGD算法更新参数
optimizer.step()
running_loss += loss.item()
num += 1
# 输出每一回合训练的平均损失值
print('epoch:%d loss: %.3f' % (epoch + 1, running_loss / num))
print('Finished Training')
对应输出:
第六步:测试模型
可视化的测试:(只用测试集的一组数据)
import matplotlib.pyplot as plt
import numpy as np
# ================================test=========================================
# 将模型改为测试模式
net.eval()
# 定义一个显示图像的函数
def imgshow(img):
npimg = img.numpy()
# transpose对高维矩阵进行轴对换
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()
# 从测试集中获得一组数据
dataiter = iter(testloader)
images, labels = dataiter.next()
# torchvision.utils.make_grid函数将获的的数据合并为一张图像
imgshow(torchvision.utils.make_grid(images))
# 输出相应的标签
print('target:', ' '.join('%d' % labels[j] for j in range(8)))
# 使用训练的模型进行预测
outputs = net(images)
_, predicted = torch.max(outputs, 1)
# 输出预测结果
print('Predict:', ' '.join('%d' % predicted[j] for j in range(8)))
对应输出:

用测试集全部数据进行测试,并输出每组测试的精确率
# ================================test=========================================
for i, data in enumerate(testloader, 0):
inputs, labels = data
outputs = net(inputs)
_, predicted = outputs.max(1)
acc_num = (labels == predicted).sum().item()
acc = acc_num / labels.size(0)
if i % 64 == 0:
print('acc:%.3f' % acc)
对应输出:

本文详细介绍了一种基于PyTorch框架的手写数字识别模型构建过程。从数据预处理到模型训练,再到最终的模型测试,全面展示了如何利用深度学习技术解决实际问题。
2880

被折叠的 条评论
为什么被折叠?



