完整的模型训练套路
完整的模型训练套路(以CIFAR10数据集)
完整的模型训练套路(一)
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from model import *
# 准备数据集
train_data = torchvision.datasets.CIFAR10(root="P27_train/dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_data = torchvision.datasets.CIFAR10(root="P27_train/dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
# length 长度 查看数据集有多少
train_data.size = len(train_data)
test_data.size = len(test_data)
# 如果train_data.size=10,训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data.size)) # 字符串格式化
print("测试数据集的长度为:{}".format(test_data.size)) # 字符串格式化
print("训练数据集的个数为%d,测试数据集的个数为%d" %(train_data.size, test_data.size))
# 利用Dataloader来加载数据集
train_dataLoader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)
# # 搭建神经网络
# class Pongber(nn.Module):
# def __init__(self):
# super(Pongber, self).__init__()
# self.model = nn.Sequential(
# nn.Conv2d(3, 32, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Conv2d(32, 32, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Conv2d(32, 64, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Flatten(),
# nn.Linear(1024, 64),
# nn.Linear(64, 10)
# )
#
# def forward(self, x):
# x = self.model(x)
#
# return x
# 创建网络模型
pongber = Pongber()
# 损失函数
loss_fn = nn.CrossEntropyLoss()
# 优化器
learning_rate = 0.01
# 1e-2 1e-2 = 1×(10)^(-2) = 1/100 = 0.01
# learning_rate = 1e-2
optimizer = torch.optim.SGD(pongber.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10
# epoch = 10,i 从0跑到9
for i in range(epoch):
print("------第{}轮训练开始------".format(i+1))
# 训练步骤开始
for data in train_dataLoader:
imgs, targets = data
outputs = pongber(imgs)
loss = loss_fn(outputs, targets)
# 优化器优化模型
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step = total_train_step + 1
# print("训练次数:{}, Loss:{}".format(total_train_step, loss))
print("训练次数:{}, Loss:{}".format(total_train_step, loss.item())) # 加上item就会把它转换成一个真实的数字
运行:
Files already downloaded and verified
Files already downloaded and verified
训练数据集的长度为:50000
测试数据集的长度为:10000
训练数据集的个数为50000,测试数据集的个数为10000
------第1轮训练开始------
训练次数:1, Loss:2.3051769733428955
训练次数:2, Loss:2.294654607772827
训练次数:3, Loss:2.3009750843048096
...
训练次数:782, Loss:2.1695666313171387
------第2轮训练开始------
训练次数:783, Loss:2.0236775875091553
...
训练次数:1564, Loss:2.315021514892578
------第3轮训练开始------
训练次数:1565, Loss:1.912036657333374
...
...
...
训练次数:7038, Loss:1.5217787027359009
------第10轮训练开始------
训练次数:7039, Loss:1.224427580833435
...
训练次数:7818, Loss:0.9744108319282532
训练次数:7819, Loss:1.217579960823059
训练次数:7820, Loss:1.4052762985229492
完整的模型训练套路(二)
现在整个训练步骤写完了,那我们思考一个问题,我们模型训练的时候如何得知它有没有训练好,或者说有没有达到我们想要的一个需求?
所以当我们训练完一轮的时候,在每一次训练完一轮后,进行一个测试,让它在测试数据集上跑一遍,以测试数据集上的损失或者正确率来评估有没有训练好,需要注意在测试的过程中就不需要对模型进行调优了,我们就是想用一个现有的模型进行一个测试
添加测试;每100次打印,避免一些无用的信息;添加tensorboard...
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from P22_nn_sequential import writer
from model import *
# 准备数据集
train_data = torchvision.datasets.CIFAR10(root="P27_train/dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_data = torchvision.datasets.CIFAR10(root="P27_train/dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
# length 长度 查看数据集有多少
train_data.size = len(train_data)
test_data.size = len(test_data)
# 如果train_data.size=10,训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data.size)) # 字符串格式化
print("测试数据集的长度为:{}".format(test_data.size)) # 字符串格式化
print("训练数据集的个数为%d,测试数据集的个数为%d" %(train_data.size, test_data.size))
# 利用Dataloader来加载数据集
train_dataLoader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)
# # 搭建神经网络
# class Pongber(nn.Module):
# def __init__(self):
# super(Pongber, self).__init__()
# self.model = nn.Sequential(
# nn.Conv2d(3, 32, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Conv2d(32, 32, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Conv2d(32, 64, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Flatten(),
# nn.Linear(1024, 64),
# nn.Linear(64, 10)
# )
#
# def forward(self, x):
# x = self.model(x)
#
# return x
# 创建网络模型
pongber = Pongber()
# 损失函数
loss_fn = nn.CrossEntropyLoss()
# 优化器
learning_rate = 0.01
# 1e-2 1e-2 = 1×(10)^(-2) = 1/100 = 0.01
# learning_rate = 1e-2
optimizer = torch.optim.SGD(pongber.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10
# 添加tensorboard
writer = SummaryWriter(log_dir="logs_train")
# epoch = 10,i 从0跑到9
for i in range(epoch):
print("------第{}轮训练开始------".format(i+1))
# 训练步骤开始
for data in train_dataLoader:
imgs, targets = data
outputs = pongber(imgs)
loss = loss_fn(outputs, targets)
# 优化器优化模型
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step = total_train_step + 1
# print("训练次数:{}, Loss:{}".format(total_train_step, loss))
if total_train_step % 100 == 0: # 每100次打印记录,避免一些无用的信息
print("训练次数:{}, Loss:{}".format(total_train_step, loss.item())) # 加上item就会把它转换成一个真实的数字
writer.add_scalar("train_loss", loss.item(), total_train_step)
# 测试步骤开始
total_test_loss = 0
with torch.no_grad(): # 没有梯度,保证不进行调优
for data in test_dataloader:
imgs, targets = data
outputs = pongber(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss
print("整体测试集上的Loss:{}".format(total_test_loss))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
total_test_step = total_test_step + 1
writer.close()
我们想保存每一轮训练的模型
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from P22_nn_sequential import writer
from model import *
# 准备数据集
train_data = torchvision.datasets.CIFAR10(root="P27_train/dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_data = torchvision.datasets.CIFAR10(root="P27_train/dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
# length 长度 查看数据集有多少
train_data.size = len(train_data)
test_data.size = len(test_data)
# 如果train_data.size=10,训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data.size)) # 字符串格式化
print("测试数据集的长度为:{}".format(test_data.size)) # 字符串格式化
print("训练数据集的个数为%d,测试数据集的个数为%d" %(train_data.size, test_data.size))
# 利用Dataloader来加载数据集
train_dataLoader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)
# # 搭建神经网络
# class Pongber(nn.Module):
# def __init__(self):
# super(Pongber, self).__init__()
# self.model = nn.Sequential(
# nn.Conv2d(3, 32, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Conv2d(32, 32, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Conv2d(32, 64, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Flatten(),
# nn.Linear(1024, 64),
# nn.Linear(64, 10)
# )
#
# def forward(self, x):
# x = self.model(x)
#
# return x
# 创建网络模型
pongber = Pongber()
# 损失函数
loss_fn = nn.CrossEntropyLoss()
# 优化器
learning_rate = 0.01
# 1e-2 1e-2 = 1×(10)^(-2) = 1/100 = 0.01
# learning_rate = 1e-2
optimizer = torch.optim.SGD(pongber.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10
# 添加tensorboard
writer = SummaryWriter(log_dir="logs_train")
# epoch = 10,i 从0跑到9
for i in range(epoch):
print("------第{}轮训练开始------".format(i+1))
# 训练步骤开始
for data in train_dataLoader:
imgs, targets = data
outputs = pongber(imgs)
loss = loss_fn(outputs, targets)
# 优化器优化模型
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step = total_train_step + 1
# print("训练次数:{}, Loss:{}".format(total_train_step, loss))
if total_train_step % 100 == 0: # 每100次打印记录,避免一些无用的信息
print("训练次数:{}, Loss:{}".format(total_train_step, loss.item())) # 加上item就会把它转换成一个真实的数字
writer.add_scalar("train_loss", loss.item(), total_train_step)
# 测试步骤开始
total_test_loss = 0
with torch.no_grad(): # 没有梯度,保证不进行调优
for data in test_dataloader:
imgs, targets = data
outputs = pongber(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss
print("整体测试集上的Loss:{}".format(total_test_loss))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
total_test_step = total_test_step + 1
torch.save(pongber, "pongber_{}.pth".format(i+1))
print("第{}轮训练模型已经保存".format(i+1))
writer.close()
其实还有一部分优化,就是我们发现即便我们得到整体测试集上的Loss,它好像也不能很好的说明我们在测试集上表现得效果,其实在分类问题中,我们可以用正确率来表示
这部分内容稍微也许会有点小困难,可以简单了解一下,因为这是分类问题中的常用的一种方式,如果说是普通的目标检测或者说是语义分割的时候,最简单的方法就是将输出直接在tensorboard中显示,所以我们可以在tensorboard中看到测试的结果
所以正确率其实是分类问题中比较特有的衡量指标
'''
2 × input
Model(2分类)
outputs =
[0.1, 0.2] # 代码中得到的output是这种形式
[0.3, 0.4]
0 1 # 实际的类
argmax # PyTorch给我们提供了这个方法,它能求出横向的最大值所在的位置
preds = [1] # 如何将以上形式转换为这个形式呢?argmax
[1]
inputs target = [0] [1] # 与preds对比,看正确率
preds == inputs target
[false, true].sum()=1 # 0与1比false,1与1比true,算出来了对应位置相等(正确)的个数有多少,然后再除以总的个数就可以算出正确率
'''
P27_test
import torch
outputs = torch.tensor([[0.1, 0.2],
[0.3, 0.4]])
print(outputs.argmax(1)) # 填0或1,1的时候横向看
# 返回tensor([1, 1]),横向看0.2大于0.1,0.4大于0.3,位置是[1, 1]
preds = outputs.argmax(1)
targets = torch.tensor([0, 1])
print(preds == targets) # 返回tensor([False, True])
print((preds == targets).sum()) # 返回tensor(1),记录对应位置相等的个数
经过验证,可以继续对代码进行优化,想办法计算出整体的一个正确率
import torch
import torchvision
from numpy.ma.core import argmax
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from P22_nn_sequential import writer
from model import *
# 准备数据集
train_data = torchvision.datasets.CIFAR10(root="P27_train/dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_data = torchvision.datasets.CIFAR10(root="P27_train/dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
# length 长度 查看数据集有多少
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data.size=10,训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size)) # 字符串格式化
print("测试数据集的长度为:{}".format(test_data_size)) # 字符串格式化
print("训练数据集的个数为%d,测试数据集的个数为%d" %(train_data_size, test_data_size))
# 利用Dataloader来加载数据集
train_dataLoader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)
# # 搭建神经网络
# class Pongber(nn.Module):
# def __init__(self):
# super(Pongber, self).__init__()
# self.model = nn.Sequential(
# nn.Conv2d(3, 32, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Conv2d(32, 32, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Conv2d(32, 64, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Flatten(),
# nn.Linear(1024, 64),
# nn.Linear(64, 10)
# )
#
# def forward(self, x):
# x = self.model(x)
#
# return x
# 创建网络模型
pongber = Pongber()
# 损失函数
loss_fn = nn.CrossEntropyLoss()
# 优化器
learning_rate = 0.01
# 1e-2 1e-2 = 1×(10)^(-2) = 1/100 = 0.01
# learning_rate = 1e-2
optimizer = torch.optim.SGD(pongber.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10
# 添加tensorboard
writer = SummaryWriter(log_dir="logs_train")
# epoch = 10,i 从0跑到9
for i in range(epoch):
print("------第{}轮训练开始------".format(i+1))
# 训练步骤开始
for data in train_dataLoader:
imgs, targets = data
outputs = pongber(imgs)
loss = loss_fn(outputs, targets)
# 优化器优化模型
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step = total_train_step + 1
# print("训练次数:{}, Loss:{}".format(total_train_step, loss))
if total_train_step % 100 == 0: # 每100次打印记录,避免一些无用的信息
print("训练次数:{}, Loss:{}".format(total_train_step, loss.item())) # 加上item就会把它转换成一个真实的数字
writer.add_scalar("train_loss", loss.item(), total_train_step)
# 测试步骤开始
total_test_loss = 0
total_accuracy = 0
with torch.no_grad(): # 没有梯度,保证不进行调优
for data in test_dataloader:
imgs, targets = data
outputs = pongber(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy = 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 = total_test_step + 1
torch.save(pongber, "pongber_{}.pth".format(i+1))
print("第{}轮训练模型已经保存".format(i+1))
writer.close()
'''
2 × input
Model(2分类)
outputs =
[0.1, 0.2] # 代码中得到的output是这种形式
[0.3, 0.4]
0 1 # 实际的类
argmax # PyTorch给我们提供了这个方法,它能求出横向的最大值所在的位置
preds = [1] # 如何将以上形式转换为这个形式呢?argmax
[1]
inputs target = [0] [1] # 与preds对比,看正确率
preds == inputs target
[false, true].sum()=1 # 0与1比false,1与1比true,算出来了对应位置相等(正确)的个数有多少,然后再除以总的个数就可以算出正确率
'''
完整的模型训练套路(三)
注意一些细节
训练步骤开始前,pongber.train()
并不是说要把这个写成训练模式它才开始训练,之前并没有写pongber.train()
它也能开始训练
测试步骤开始前,pongber.eval()
并不是说要把这个写成评估模式它才开始测试,之前并没有写pongber.eval()
它也能开始测试
那它们有什么作用呢?
因为神经网络继承Module,所以看这个Module
train(mode=True)
将模块设置为训练模式。
这只会影响某些特定的模块。请参阅各个模块的文档,了解它们在训练模式和评估模式下的具体行为是否会受到影响,例如 Dropout、BatchNorm 等模块。
eval()
将模块设置为评估模式。
这只会影响某些特定的模块。请参阅各个模块的文档,了解它们在训练模式和评估模式下的具体行为是否会受到影响,例如 Dropout、BatchNorm 等模块。
该方法等价于 self.train(False)。
关于 .eval() 与其他可能被混淆的类似机制(如“局部禁用梯度计算”)之间的区别,请参见“Locally disabling gradient computation”部分的说明。
以后在写代码的时候,可以关注网络层有没有这些特殊的层,当然没有的话调用也是没有问题的
添加pongber.train(mode=True)
和pongber.eval()
import torch
import torchvision
from numpy.ma.core import argmax
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from P22_nn_sequential import writer
from model import *
# 准备数据集
train_data = torchvision.datasets.CIFAR10(root="P27_train/dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_data = torchvision.datasets.CIFAR10(root="P27_train/dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
# length 长度 查看数据集有多少
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data.size=10,训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size)) # 字符串格式化
print("测试数据集的长度为:{}".format(test_data_size)) # 字符串格式化
print("训练数据集的个数为%d,测试数据集的个数为%d" %(train_data_size, test_data_size))
# 利用Dataloader来加载数据集
train_dataLoader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)
# # 搭建神经网络
# class Pongber(nn.Module):
# def __init__(self):
# super(Pongber, self).__init__()
# self.model = nn.Sequential(
# nn.Conv2d(3, 32, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Conv2d(32, 32, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Conv2d(32, 64, 5, 1, 2),
# nn.MaxPool2d(2),
# nn.Flatten(),
# nn.Linear(1024, 64),
# nn.Linear(64, 10)
# )
#
# def forward(self, x):
# x = self.model(x)
#
# return x
# 创建网络模型
pongber = Pongber()
# 损失函数
loss_fn = nn.CrossEntropyLoss()
# 优化器
learning_rate = 0.01
# 1e-2 1e-2 = 1×(10)^(-2) = 1/100 = 0.01
# learning_rate = 1e-2
optimizer = torch.optim.SGD(pongber.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10
# 添加tensorboard
writer = SummaryWriter(log_dir="logs_train")
# epoch = 10,i 从0跑到9
for i in range(epoch):
print("------第{}轮训练开始------".format(i+1))
# 训练步骤开始
pongber.train(mode=True)
for data in train_dataLoader:
imgs, targets = data
outputs = pongber(imgs)
loss = loss_fn(outputs, targets)
# 优化器优化模型
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step = total_train_step + 1
# print("训练次数:{}, Loss:{}".format(total_train_step, loss))
if total_train_step % 100 == 0: # 每100次打印记录,避免一些无用的信息
print("训练次数:{}, Loss:{}".format(total_train_step, loss.item())) # 加上item就会把它转换成一个真实的数字
writer.add_scalar("train_loss", loss.item(), total_train_step)
# 测试步骤开始
pongber.eval()
total_test_loss = 0
total_accuracy = 0
with torch.no_grad(): # 没有梯度,保证不进行调优
for data in test_dataloader:
imgs, targets = data
outputs = pongber(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy = 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 = total_test_step + 1
torch.save(pongber, "pongber_{}.pth".format(i+1))
# torch.save(pongber.state_dict(), "pongber_{}.pth".format(i+1))
print("第{}轮训练模型已经保存".format(i+1))
writer.close()
'''
2 × input
Model(2分类)
outputs =
[0.1, 0.2] # 代码中得到的output是这种形式
[0.3, 0.4]
0 1 # 实际的类
argmax # PyTorch给我们提供了这个方法,它能求出横向的最大值所在的位置
preds = [1] # 如何将以上形式转换为这个形式呢?argmax
[1]
inputs target = [0] [1] # 与preds对比,看正确率
preds == inputs target
[false, true].sum()=1 # 0与1比false,1与1比true,算出来了对应位置相等(正确)的个数有多少,然后再除以总的个数就可以算出正确率
'''
首先准备数据集
然后利用Dataloader来加载数据集
创建网络模型(一般在另一个文件里创建类,调用)
创建损失函数
创建优化器
设置训练网络的一些参数(训练的轮数、训练的次数)
pongber.train(mode=True)
进入训练状态
从train_dataLoader取数据
计算误差
放入优化器中优化
采用特定方式展示输出
在一轮训练结束后或者特定的步数之后pongber.eval()
进入测试状态
with torch.no_grad():
没有梯度,保证不进行调优
从test_dataloader取数据
计算误差
构建一些特殊的指标显示出来
最后通过一些方式展示一下我们训练的网络在测试集上的效果
最后可以某一轮或特定的步数保存这个模型(这里使用的是方式1,方式2是官方推荐的)
torch.save(pongber.state_dict(), "pongber_{}.pth".format(i+1))
原始资料地址:
完整的模型训练套路(一)
完整的模型训练套路(二)
完整的模型训练套路(三)
如有侵权联系删除 仅供学习交流使用