欢迎光临散文网 会员登陆 & 注册

MNIST集的分类的实现

2023-04-04 09:32 作者:我还在等你GDF  | 我要投稿

import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

#定义训练集
train_dataset = datasets.MNIST(root='./', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='./', train=False, transform=transforms.ToTensor(), download=True)

#定义一个批次的大小
batch_size = 64

#装载训练集(dataset是指要读取的数据位置, batch_size是指每个批次读入的数据大小, shuffle是指是否在读取前进行顺序的打乱)
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)

#装载测试集
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=True)

#数据加载
for i, data in enumerate(train_loader):
   inputs, labels = data
   print(inputs.shape)
   print(labels.shape)
   break

#定义分类模型
class Net(torch.nn.Module):
   def __init__(self):
       #继承父类
       super(Net, self).__init__()
       #定义神经网络的结构
       #定义全连接层(输入的每个样本的大小为28 * 28 == 784, 所以输入神经元个数为784, 输出为0 - 9的10个类别的概率, 所以输出神经元个数为10)
       self.fcl = torch.nn.Linear(784, 10)
       #定义激活函数为softmax函数, dim=1是因为要按每一行的每一列求取概率来判断每一行属于什么类
       self.softmax = torch.nn.Softmax(dim=1)

   def forward(self, x):
       #由于x的形状为[64, 1, 28, 28], 而神经网络的计算取决于矩阵计算, 所以应该先将x转换为二维的[64, 784]的形状再进行计算
       x = x.view(x.size(0), -1)
       x = self.fcl(x)
       x = self.softmax(x)
       return x

#定义模型
model = Net()

#定义代价函数
mse_loss = torch.nn.MSELoss(reduction='mean')

#定义优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.5)

#定义模型的训练
def train():
   for i, data in enumerate(train_loader):
       inputs, labels = data
       #获得数据的输入值并将其放入模型中进行计算
       out = model(inputs)
       #将labels转换为独热编码, 先将labels数据从一维变成两维
       labels = labels.view(-1, 1)
       #使用scatter函数得到one_hot_labels
       #Tensor.scatter(dim, index, src), 沿着第dim维将Tensor中的第index(索引)位替换为src
       one_hot_labels = torch.zeros(labels.size(0), 10).scatter(1, labels, 1)
       #通过独热编码和经过softmax计算的概率值(都是从0 - 1的, 可以计算损失, 这也是将标签绘制为独热编码的意义之一)计算损失值
       loss = mse_loss(out, one_hot_labels)
       #每100个批次输出一次损失值
       if (i + 1) % 100 == 0:
           print("第", i + 1, "批次的损失值为:", loss.item())
       #在反向传播计算梯度之前, 先进行梯度清零
       optimizer.zero_grad()
       #进行反向传播求解梯度
       loss.backward()
       #通过优化器更新参数
       optimizer.step()

#定义模型的测试
def test():
   #定义一个变量correct, 用来统计测试集中正确的次数
   correct = 0
   for i, data in enumerate(test_loader):
       #获得一个批次的输入和标签
       inputs, labels = data
       #将测试集的inputs放入模型中计算得到测试集的预测结果
       test_pred = model(inputs)
       #通过max(test_pred, 1)函数得到test_pred中按照每一行取最大值的次序, _,是指无关变量, 因为max函数返回最大的值和最大的值对应的位序, 所以需要两个返回值
       _, predict = torch.max(test_pred, 1)
       #通过predict和标签进行对比(predict是第几位是最大的概率, 标签是0 - 9的数字, 所以当predict和labels相等时就相当于预测值是正确的)来得到判断正确的数量并赋给correct
       correct += (predict == labels).sum()
   #计算一整次测试的准确率
   print("第", epoch + 1, "次训练后测试的预测准确率为:", correct.item() / len(test_dataset))


#模型进行epoch次训练并且每次训练完都进行一次测试
for epoch in range(10):
   print("第", epoch + 1, "次:")
   train()
   test()

MNIST集的分类的实现的评论 (共 条)

分享到微博请遵守国家法律