跟着视频敲的代码,记录学习过程。
完整程序:
import matplotlib.pyplot as plt import torch import os import torchvision import numpy as np import torch.nn.functional as F from torch.utils.data import DataLoader from torch import nn from PIL import Image import warnings warnings.filterwarnings("ignore") train_batch_size = 64 test_batch_size = 1000 img_size = 28 #----------------------------------------------------------------------------# # 创建一个数据加载器,用于从数据集中获取一批次的数据。 # 可以帮助在训练神经网络时进行小批量梯度下降优化,提高模型的训练效果。 #----------------------------------------------------------------------------# def get_dataloader(train = True): # -------------------------------------------------------------------------# # /data:数据集的存储路径。你可以将其更改为你想要的任何路径。 # train=train:指定是否要加载训练集或测试集的数据。 # download=True:如果数据集不存在,会自动下载并存储在指定路径中。 # transform:转换操作列表,用于对数据进行预处理。这里的操作包括将图像转换为 # 张量(ToTensor())和对图像进行标准化(Normalize())。 #batch_size 根据是否是训练数据加载器还是测试数据加载器进行不同的设置。 # 使用 torch.utils.data.DataLoader 创建数据加载器对象。 # 其中的参数包括数据集对象、批次大小、以及是否对数据进行洗牌。 #--------------------------------------------------------------------------# dataset = torchvision.datasets.MNIST("/data",train=train,download = True, transform = torchvision.transforms.Compose([ torchvision.transforms.ToTensor(), torchvision.transforms.Normalize((0.1307,),(0.3081)), ])) batch_size = train_batch_size if train else test_batch_size dataloader = torch.utils.data.DataLoader(dataset,batch_size=batch_size,shuffle=True) return dataloader class MnistNet(nn.Module): def __init__(self): super(MnistNet,self).__init__() self.fc1 = nn.Linear(784,256) self.fc2 = nn.Linear(256,64) self.fc3 = nn.Linear(64,10) def forward(self,x): x = x.view(-1,784) x = self.fc1(x) x = F.relu(x) x = self.fc2(x) x = F.relu(x) x = self.fc3(x) return F.log_softmax(x,dim=-1) mnist_net = MnistNet() #----------------# # 交叉熵损失函数 # Adam优化器 #----------------# criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(mnist_net.parameters(),lr=0.001) train_loss_list = [] train_count_list = [] def train(epoch): #-------------------------------------------------------------------------------------# # 通过调用 train() 方法将神经网络模型设置为训练模式 #调用 get_dataloader() 函数创建一个训练数据加载器 #使用 enumerate() 函数遍历训练数据加载器,获取每个批次的数据和对应的标签。 # data 是输入数据(图像),target 是对应的真实标签(类别)。 #optimizer.zero_grad():用于清空优化器中之前批次的梯度信息(梯度清零) #将输入数据 data 传入神经网络模型 mnist_net 进行前向传播,得到模型的输出结果 output。 #使用损失函数计算模型预测结果 output 和真实标签 target 之间的损失值。 #进行反向传播,自动计算梯度,并将梯度信息保存在参数的 .grad 属性中 #根据梯度信息更新模型的参数。优化器会利用参数的梯度调整参数的数值,以减小损失。 #train_loss_list.append(loss.item()):将当前批次的损失值存储到 train_loss_list 列表中。 # 这样可以记录每个批次的损失值,方便后续绘制损失曲线或进行其他分析。 #train_count_list.append(index*train_batch_size+(epoch-1)*len(train_dataloader)): #将当前批次的累计样本数加上之前所有训练样本数量存储到 train_count_list 列表中。 # 这样可以记录每个批次之前已经训练过的样本数,用于可视化训练过程中的样本数量。 #------------------------------------------------------------------------------------# mnist_net.train(True) train_dataloader = get_dataloader(True) for index,(data,target) in enumerate(train_dataloader): optimizer.zero_grad() output = mnist_net(data) loss = F.nll_loss(output,target) loss.backward() optimizer.step() if index % 100 == 0: print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( epoch, index * len(data), len(train_dataloader.dataset), 100. * index / len(train_dataloader), loss.item())) train_loss_list.append(loss.item()) train_count_list.append(index*train_batch_size+(epoch-1)*len(train_dataloader)) def test(): #--------------------------------------------------------------------------------------------# #test_loss = 0:初始化测试损失为0。该变量将用于累加每个样本的损失值。 #correct = 0:初始化正确预测的样本数为0。该变量将用于统计模型在测试集上的准确率。 #mnist_net.eval():通过调用 eval() 方法将神经网络模型设置为评估模式。 #test_dataloader = get_dataloader(train=False):调用 get_dataloader() 函数创建一个测试数据加载器 #with torch.no_grad():使用 torch.no_grad() 上下文管理器,确保在评估过程中不会记录计算图,从而节省内存空间 #for data, target in test_dataloader::遍历测试数据加载器,获取每个样本的数据和对应的标签 #将输入数据 data 传入神经网络模型 mnist_net 进行前向传播,得到模型的输出结果 output #计算当前样本的损失值,并累加到测试损失test_loss上。reduction参数设置为 'sum',表示将每个样本的损失值进行累加。 #pred = output.data.max(1, keepdim=True)[1]: # 根据模型的输出结果 output ,找到每个样本预测的最大概率对应的类别索引 #correct += pred.eq(target.data.view_as(pred)).sum(): # 统计预测正确的样本数。将预测结果 pred 与真实标签 target 进行比较,并将预测正确的样本数进行累加 #test_loss /= len(test_dataloader.dataset):将测试损失除以测试集样本数量,得到平均损失 #打印输出测试集的评估结果。包括平均损失和准确率。 #--------------------------------------------------------------------------------------------# test_loss = 0 correct = 0 mnist_net.eval() test_dataloader = get_dataloader(train=False) with torch.no_grad(): for data, target in test_dataloader: output = mnist_net(data) test_loss += F.nll_loss(output, target, reduction='sum').item() pred = output.data.max(1, keepdim=True)[1] correct += pred.eq(target.data.view_as(pred)).sum() test_loss /= len(test_dataloader.dataset) print('\nTest set: Avg. loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format( test_loss, correct, len(test_dataloader.dataset), 100. * correct / len(test_dataloader.dataset))) if __name__ == '__main__': test() for i in range(5): train(i) test()
下载数据集结果:
运行结果:
Test set: Avg. loss: 2.3212, Accuracy: 1206/10000 (12.06%)
Train Epoch: 0 [0/60000 (0%)] Loss: 2.321229
Train Epoch: 0 [6400/60000 (11%)] Loss: 0.550573
Train Epoch: 0 [12800/60000 (21%)] Loss: 0.175103
Train Epoch: 0 [19200/60000 (32%)] Loss: 0.254183
Train Epoch: 0 [25600/60000 (43%)] Loss: 0.121522
Train Epoch: 0 [32000/60000 (53%)] Loss: 0.280531
Train Epoch: 0 [38400/60000 (64%)] Loss: 0.205788
Train Epoch: 0 [44800/60000 (75%)] Loss: 0.034362
Train Epoch: 0 [51200/60000 (85%)] Loss: 0.125562
Train Epoch: 0 [57600/60000 (96%)] Loss: 0.093930
Test set: Avg. loss: 0.1192, Accuracy: 9627/10000 (96.27%)
Train Epoch: 1 [0/60000 (0%)] Loss: 0.089502
Train Epoch: 1 [6400/60000 (11%)] Loss: 0.131700
Train Epoch: 1 [12800/60000 (21%)] Loss: 0.128198
Train Epoch: 1 [19200/60000 (32%)] Loss: 0.053703
Train Epoch: 1 [25600/60000 (43%)] Loss: 0.051744
Train Epoch: 1 [32000/60000 (53%)] Loss: 0.057353
Train Epoch: 1 [38400/60000 (64%)] Loss: 0.293683
Train Epoch: 1 [44800/60000 (75%)] Loss: 0.069954
Train Epoch: 1 [51200/60000 (85%)] Loss: 0.291764
Train Epoch: 1 [57600/60000 (96%)] Loss: 0.066690
Test set: Avg. loss: 0.1065, Accuracy: 9669/10000 (96.69%)
Train Epoch: 2 [0/60000 (0%)] Loss: 0.157847
Train Epoch: 2 [6400/60000 (11%)] Loss: 0.021395
Train Epoch: 2 [12800/60000 (21%)] Loss: 0.085961
Train Epoch: 2 [19200/60000 (32%)] Loss: 0.211282
Train Epoch: 2 [25600/60000 (43%)] Loss: 0.029853
Train Epoch: 2 [32000/60000 (53%)] Loss: 0.031299
Train Epoch: 2 [38400/60000 (64%)] Loss: 0.019096
Train Epoch: 2 [44800/60000 (75%)] Loss: 0.064281
Train Epoch: 2 [51200/60000 (85%)] Loss: 0.111029
Train Epoch: 2 [57600/60000 (96%)] Loss: 0.075113
Test set: Avg. loss: 0.0832, Accuracy: 9746/10000 (97.46%)
Train Epoch: 3 [0/60000 (0%)] Loss: 0.034858
Train Epoch: 3 [6400/60000 (11%)] Loss: 0.065938
Train Epoch: 3 [12800/60000 (21%)] Loss: 0.020054
Train Epoch: 3 [19200/60000 (32%)] Loss: 0.010132
Train Epoch: 3 [25600/60000 (43%)] Loss: 0.051468
Train Epoch: 3 [32000/60000 (53%)] Loss: 0.042442
Train Epoch: 3 [38400/60000 (64%)] Loss: 0.068702
Train Epoch: 3 [44800/60000 (75%)] Loss: 0.093545
Train Epoch: 3 [51200/60000 (85%)] Loss: 0.011688
Train Epoch: 3 [57600/60000 (96%)] Loss: 0.015226
Test set: Avg. loss: 0.0780, Accuracy: 9755/10000 (97.55%)
Train Epoch: 4 [0/60000 (0%)] Loss: 0.075244
Train Epoch: 4 [6400/60000 (11%)] Loss: 0.024666
Train Epoch: 4 [12800/60000 (21%)] Loss: 0.031698
Train Epoch: 4 [19200/60000 (32%)] Loss: 0.098030
Train Epoch: 4 [25600/60000 (43%)] Loss: 0.020235
Train Epoch: 4 [32000/60000 (53%)] Loss: 0.002573
Train Epoch: 4 [38400/60000 (64%)] Loss: 0.051085
Train Epoch: 4 [44800/60000 (75%)] Loss: 0.014662
Train Epoch: 4 [51200/60000 (85%)] Loss: 0.023142
Train Epoch: 4 [57600/60000 (96%)] Loss: 0.047781
Test set: Avg. loss: 0.0777, Accuracy: 9772/10000 (97.72%)