#AI挑战营第一站#手写数字MNIST识别实验记录
[复制链接]
本帖最后由 undo110 于 2024-4-13 00:57 编辑
因为需要使用到MNIST中手写数字的数据集,而该数据集中每张图片的大小为28x28,所以需要输入数据的维度需要设置为784。同时,我们需要识别的数字为0~9,需将输出层设为10个。应题目要求,中间层神经元数量设为15。
MNIST数据集,选择直接从pytorch包中所带的dataset数据集中导入。将数据集分为训练和测试两部分。在训练过程中,需要加入BP算法来对调整网络的权重。而,在测试过程中,则不再需要反向传播。
使用pytorch包来构建三层神经网络,使用的是ReLU激活函数,交叉熵损失函数。
同时基于个人电脑配置,将设置迭代训练次数为10次,同时精确度也已经得到很好的收敛。
from torchvision.datasets import mnist
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
from torch import nn
import torch.optim as optim
meta_size = 70 # 限定每次从数据集中取出数量,为70
epoches = 10
lr = 0.01 # 设置超参数学习率为0.01
momentum = 0.5
# 数据 预处理Compose方法即是将两个操作合并一起
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize([0.1307], [0.3081])])
# 下载数据集
train_dataset = mnist.MNIST('mnist', train=True, transform=transform, download=True)
# 非训练集,train参数设为False
test_dataset = mnist.MNIST('mnist', train=False, transform=transform, download=True)
# dataloader是可迭代对象,迭代取出大小meta-size
train_loader = DataLoader(train_dataset, batch_size=meta_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=meta_size, shuffle=False)
# 定义三层神经网络
# 因为需要使用到MNIST中手写数字的数据集,而该数据集中每张图片的大小为# 28x28,所以需要输入数据的维度需要设置为784。同时,我们需要识别的数 # 字为0~9,需将输出层设为10个。应题目要求,中间层神经元数量设为15。
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.layer1 = nn.Sequential(nn.Linear(784, 784), nn.ReLU(True)) #使用ReLU激活函数
self.layer2 = nn.Sequential(nn.Linear(784, 15), nn.ReLU(True))
self.layer3 = nn.Linear(15, 10)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
return x
model = Net()
# 定义模型训练中用到的损失函数和优化器
criterion = nn.CrossEntropyLoss() # 交叉熵损失函数
optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum)
train_losses = [] # 记录训练集损失
train_acces = [] # 用于收集训练集准确率
test_losses = [] # 收集测试集损失
test_acces = [] # 收集每次测试集准确率
for epoch in range(epoches):
train_loss = 0
train_acc = 0
model.train() # model的训练过程
for img, label in train_loader:
img = img.view(img.size(0), -1) # 把输入图像转化为2维
# 前向传播
out = model(img)
loss = criterion(out, label)
# 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()
train_loss += loss.item() # 所有批次损失的和
# 计算分类的准确率
_, pred = out.max(1)
num_correct = (pred == label).sum().item()
acc = num_correct / img.shape[0] # 每一批样本的准确率
train_acc += acc
train_losses.append(train_loss / len(train_loader)) # 所有样本平均损失
train_acces.append(train_acc / len(train_loader)) # 所有样本的平均准确率
# 测试
test_loss = 0
test_acc = 0
# 将模型改为预测模式
# 在训练过程中,需要加入BP算法来对调整网络的权重。而,在测试过程 # 中,则不再需要反向传播。
model.eval()
for img, label in test_loader:
img = img.view(img.size(0), -1)
out = model(img)
loss = criterion(out, label)
test_loss += loss.item()
_, pred = out.max(1)
num_correct = (pred == label).sum().item()
acc = num_correct / img.shape[0]
test_acc += acc
test_losses.append(test_loss / len(test_loader))
test_acces.append(test_acc / len(test_loader))
print('轮次: {}, 训练损失: {:.4f}, 训练准确率: {:.4f}, 测试损失: {:.4f}, 测试准确率: {:.4f}'
.format(epoch, train_loss / len(train_loader), train_acc / len(train_loader),
test_loss / len(test_loader), test_acc / len(test_loader)))
导出文件:
|