import torch import torchvision from torch import nn from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter # 1. 准备数据集 train_data = torchvision.datasets.CIFAR10( root="./data", train=True, transform=torchvision.transforms.ToTensor(), download=True ) test_data = torchvision.datasets.CIFAR10( root="./data", train=False, transform=torchvision.transforms.ToTensor(), download=True ) # 2. 数据加载器 train_dataloader = DataLoader(train_data, batch_size=64, shuffle=True) test_dataloader = DataLoader(test_data, batch_size=64, shuffle=False) # 3. 搭建网络(沿用之前的模型) class Tudui(nn.Module): def __init__(self): super().__init__() self.model = Sequential( Conv2d(3, 32, 5, padding=2), MaxPool2d(2), Conv2d(32, 32, 5, padding=2), MaxPool2d(2), Conv2d(32, 64, 5, padding=2), MaxPool2d(2), Flatten(), Linear(1024, 64), Linear(64, 10) ) def forward(self, x): return self.model(x) # 4. 初始化模型、损失函数和优化器 tudui = Tudui() loss_fn = nn.CrossEntropyLoss() optimizer = torch.optim.SGD(tudui.parameters(), lr=0.01) # 5. TensorBoard 记录器 writer = SummaryWriter("logs") # 6. 训练参数 epochs = 10 # 训练10轮 total_train_step = 0 # 记录训练步数 total_test_step = 0 # 记录测试步数 # 7. 训练循环 for epoch in range(epochs): print(f"-------- 第 {epoch+1} 轮训练开始 --------") # 7.1 训练模式 tudui.train() # P29 核心:切换到训练模式 for data in train_dataloader: imgs, targets = data outputs = tudui(imgs) loss = loss_fn(outputs, targets) optimizer.zero_grad() loss.backward() optimizer.step() total_train_step += 1 if total_train_step % 100 == 0: print(f"训练次数: {total_train_step}, Loss: {loss.item()}") writer.add_scalar("train_loss", loss.item(), total_train_step) # 7.2 测试步骤(P28 核心) tudui.eval() # P29 核心:切换到评估模式 total_test_loss = 0 total_accuracy = 0 with torch.no_grad(): # P28 核心:关闭梯度计算 for data in test_dataloader: imgs, targets = data outputs = tudui(imgs) loss = loss_fn(outputs, targets) total_test_loss += loss.item() # 计算准确率(P28 核心) accuracy = (outputs.argmax(1) == targets).sum() total_accuracy += accuracy print(f"整体测试集上的 Loss: {total_test_loss}") print(f"整体测试集上的正确率: {total_accuracy/len(test_data)}") writer.add_scalar("test_loss", total_test_loss, total_test_step) writer.add_scalar("test_accuracy", total_accuracy/len(test_data), total_test_step) total_test_step += 1 # 保存模型 torch.save(tudui, f"tudui_{epoch}.pth") print("模型已保存") writer.close()1.准备两个数据集,train=True是训练集50000张图片,train=False是测试集10000张图片
2.
train_dataloader = DataLoader(train_data, batch_size=64, shuffle=True) test_dataloader = DataLoader(test_data, batch_size=64, shuffle=False)
分别在测试集数据集进行64个图片一组的打包。
3.class Tudui中搭建神经网络,通过三次卷积池化,一次展平,两次全连接识别图片。
对卷积池化作用不熟悉的朋友可以看我的pytorch12->Sequential的简单应用
4.初始化模型、损失函数和优化器
对损失函数和优化器不熟悉的朋友可以看我的pytorch13,14
5.训练模式详解
tudui.train() # P29 核心:切换到训练模式 for data in train_dataloader: imgs, targets = data outputs = tudui(imgs) loss = loss_fn(outputs, targets) optimizer.zero_grad() loss.backward() optimizer.step() total_train_step += 1 if total_train_step % 100 == 0: print(f"训练次数: {total_train_step}, Loss: {loss.item()}") writer.add_scalar("train_loss", loss.item(), total_train_step)tudui.train(),模型切换到训练模式这题的tudui.train(),和tudui.eval()只是起到标志作用
如果有Dropout,训练模式会随即关闭一些神经元,防止模型死记硬背。而测试模式不会关闭神经元
训练的流程是什么?
(1)for data in train_dataloader:从数据集取图片
(2)outputs = tudui(imgs),运用神经网络进行预测
(3)loss = loss_fn(outputs, targets),通过预测结果和实际结果比较计算损失
(4)
optimizer.zero_grad() loss.backward() optimizer.step()
优化器三部曲,清空原来梯度,计算现在梯度,通过现有梯度改变神经网络卷积层和全连接层的参数
(5)total_train_step += 1,一组64张图片,训练结束后total_train_step+1
(6)
if total_train_step % 100 == 0: print(f"训练次数: {total_train_step}, Loss: {loss.item()}") writer.add_scalar("train_loss", loss.item(), total_train_step)整百的损失输出一次,把输出结果在tensorboard上画表显示出来
6.测试模式详解
tudui.eval() # P29 核心:切换到评估模式 total_test_loss = 0 total_accuracy = 0 with torch.no_grad(): # P28 核心:关闭梯度计算 for data in test_dataloader: imgs, targets = data outputs = tudui(imgs) loss = loss_fn(outputs, targets) total_test_loss += loss.item() # 计算准确率(P28 核心) accuracy = (outputs.argmax(1) == targets).sum() total_accuracy += accuracy
(1)tudui.eval(),切换到测试模式,有时和训练模式会有不同,这题纯牌位,没啥用
(2)total_test_loss:测试模式10000张图片的总损失, total_accuracy:测试模式10000张图片的总准确数
(3)with torch.no_grad():关闭梯度计算,测试时不再更新模型,打开梯度计算没有意义
(4) total_test_loss += loss.item():累加每一组图片的损失共10000张图片的损失,
loss是张量, loss.item()才能取到损失的数
(5)accuracy = (outputs.argmax(1) == targets).sum()
outputs.shape = [64, 10] outputs有64张图片,10种图片类型的得分,argmax(1)是算第一维的最大参数,也就是输出10种图片类型得分的最高值,从而判断它是哪种图片。
(outputs.argmax(1) == targets).sum(),如果算出某类结果和目标一致,代表预测正确,反之,预测错误。这里一次预测64张图片的结果,在后面累加。
7.print(f"整体测试集上的正确率: {total_accuracy/len(test_data)}")
用全部预测正确的个数除以测试集总数求正确率