以简单数据集CIFAR10为例,本次训练以GPU训练为例。
# -*- coding: utf-8 -*-
# File created on 2024/8/11
# 作者:酷尔
# 公众号:酷尔计算机
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from model import *
import torch
from torch.utils.tensorboard import SummaryWriter
train_data=torchvision.datasets.CIFAR10('./dataset',train=True,download=True,transform=torchvision.transforms.ToTensor())
test_data=torchvision.datasets.CIFAR10('./dataset',train=False,download=True,transform=torchvision.transforms.ToTensor())
train_data_size=len(train_data)
test_data_size=len(test_data)
print("训练数据集的长度为:{}".format(train_data_size),"测试数据集的长度为:{}".format(test_data_size))
train_dataloader=DataLoader(train_data,batch_size=64)
test_dataloader=DataLoader(test_data,batch_size=64)
#创建网络模型
wang=Wang()
#损失函数
loss_fn=nn.CrossEntropyLoss()
#优化器
# learning_rate=0.01
learning_rate=1e-2
optimizer=torch.optim.SGD(wang.parameters(),lr=learning_rate)
#设置训练网络的一些参数
#记录训练的次数
total_train_step=0
#记录测试的次数
total_test_step=0
#训练的轮数
epoch=10
#添加tensorboard
writer=SummaryWriter("logs_train")
for i in range(epoch):
print(f"-------------第{i+1}轮训练开始---------------")
wang.train()
for data in train_dataloader:
imgs,targets=data
output=wang(imgs)
loss=loss_fn(output,targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step+=1
if total_train_step%100==0:
print("训练次数:{},Loss:{}".format(total_train_step,loss))
writer.add_scalar("train_loss",loss.item(),total_train_step)
#测试
wang.eval()
total_test_loss=0
total_accuracy=0
with torch.no_grad():
for data in test_dataloader:
imgs,targets=data
output=wang(imgs)
loss=loss_fn(output,targets)
total_test_loss+=loss.item()
accuracy=(output.argmax(1)==targets).sum()
total_accuracy+=accuracy
print("整理测试集上的Loss:{}".format(total_test_loss))
print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
writer.add_scalar("test_loss", total_test_loss,total_test_step)
writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
total_test_step+=1
torch.save(wang,"./models/wang_{}.pth".format(i))
print("模型已保存")
writer.close()
optimizer.zero_grad() loss.backward() optimizer.step()
讲解一下这三行代码的流程,首先optimizer.zero_grad() 将梯度清零,也就是每一层里的weight的grad里的参数清零,执行loss.backward()以后,grad里存储的就是反向传播的参数,optimizer.step()执行,将grad的值对参数进行更新。
with torch.no_grad():
当你将代码块放在with torch.no_grad():
之下时,PyTorch会自动将该代码块中的所有操作设置为不计算梯度。这意味着,在这个代码块中进行的所有张量(Tensor)操作都不会追踪梯度,也不会增加计算图(computation graph)的复杂性。这对于提高代码的执行效率特别有用,尤其是在处理大规模数据或进行实时推理时。
备注;
在Python中,if __name__ == '__main__':
这行代码扮演着非常重要的角色,它主要用于判断当前运行的脚本是否是主程序。这行代码的工作原理基于Python中一个特别的内置变量__name__
。
理解__name__
- 当Python文件被直接运行时,Python解释器会将
__name__
变量设置为字符串'__main__'
。 - 如果该文件是被其他文件导入(作为模块)的,则
__name__
变量将被设置为该模块的名字(即文件名,不包括.py
扩展名)。