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()