东莞凤岗企业网站建设推广,杭州 电商设计网站建设,手机百度官网,找个人做网站此文章为【我是土堆 - Pytorch教程】 知识点 学习总结笔记#xff08;五#xff09;包括#xff1a;完整的模型训练套路#xff08;一#xff09;、完整的模型训练套路#xff08;二#xff09;、完整的模型训练套路#xff08;三#xff09;、利用GPU训练#xff08…此文章为【我是土堆 - Pytorch教程】 知识点 学习总结笔记五包括完整的模型训练套路一、完整的模型训练套路二、完整的模型训练套路三、利用GPU训练一、利用GPU训练二、完整的模型验证套路、【完结】看看开源项目。 学习系列笔记(已完结)
【我是土堆 - Pytorch教程】 知识点 学习总结笔记一_耿鬼喝椰汁的博客-CSDN博客
【我是土堆 - Pytorch教程】 知识点 学习总结笔记二_耿鬼喝椰汁的博客-CSDN博客
【我是土堆 - Pytorch教程】 知识点 学习总结笔记三_耿鬼喝椰汁的博客-CSDN博客
【我是土堆 - Pytorch教程】 知识点 学习总结笔记四_耿鬼喝椰汁的博客-CSDN博客
【我是土堆 - Pytorch教程】 知识点 学习总结笔记五_耿鬼喝椰汁的博客-CSDN博客 目录
一、完整的模型训练套路一 1.model.py 文件代码
2.train.py 文件代码
二、完整的模型训练套路二
1.如何知道模型是否训练好或达到需求
完整代码
2. 与 TensorBoard 结合 3. 保存每一轮训练的模型
4.正确率的实现对分类问题 三、完整的模型训练套路三
此章节注意一些细节
1.train.py 完整代码
2.model.train() 和 model.eval()
3.作用
回顾案例
四、利用GPU训练一
1.第一种使用GPU训练的方式 1.网络模型
2.数据包括输入、标注
3.损失函数
2. 比较CPU/GPU训练时间
1对于CPU
2 对于GPU
3查看GPU信息 3.Google Colab 1.如何在Google Colab使用GPU
五、利用GPU训练一
1.第二种使用GPU训练的方式更常用
六完整的模型验证测试、demo套路
1.示例 1
test.py把训练模型运用到实际环境中完整代码
2.示例二
(七)、看看开源项目
README.md train.py 训练参数设置 一、完整的模型训练套路一
以 CIFAR10 数据集为例分类问题10分类 pycharm中 在语句后面按 Ctrl d 可以复制这条语句 此教程搭建的网络模型 1.model.py 文件代码
import torch
from torch import nn# 搭建神经网络10分类网络
class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()# 把网络放到序列中self.model nn.Sequential(nn.Conv2d(in_channels3,out_channels32,kernel_size5,stride1,padding2), #输入是32x32的输出还是32x32的padding经计算为2nn.MaxPool2d(kernel_size2),nn.Conv2d(in_channels32,out_channels32,kernel_size5,stride1,padding2), #输入输出都是16x16的同理padding经计算为2nn.MaxPool2d(kernel_size2),nn.Conv2d(in_channels32,out_channels64,kernel_size5,stride1,padding2),nn.MaxPool2d(kernel_size2),nn.Flatten(), # 展平nn.Linear(in_features64*4*4,out_features64),nn.Linear(in_features64,out_features10))def forward(self,x):x self.model(x)return xif __name__ __main__:# 测试网络的验证正确性tudui Tudui()input torch.ones((64,3,32,32)) # batch_size64代表64张图片,3通道32x32output tudui(input)print(output.shape)
运行结果如下 返回64行数据每一行数据有10个数据代表每一张图片在10个类别中的概率。
2.train.py 文件代码
与 model.py 文件必须在同一个文件夹底下
import torchvision.datasets
from model import *
from torch import nn
from torch.utils.data import DataLoader# 准备数据集CIFAR10 数据集是PIL Image要转换为tensor数据类型
train_data torchvision.datasets.CIFAR10(root../data,trainTrue,transformtorchvision.transforms.ToTensor(),downloadTrue)
test_data torchvision.datasets.CIFAR10(root../data,trainFalse,transformtorchvision.transforms.ToTensor(),downloadTrue)# 看一下训练数据集和测试数据集都有多少张如何获得数据集的长度
train_data_size len(train_data) # length 长度
test_data_size len(test_data)
# 如果train_data_size10那么打印出的字符串为训练数据集的长度为10
print(训练数据集的长度为{}.format(train_data_size)) # 字符串格式化把format中的变量替换{}
print(测试数据集的长度为{}.format(test_data_size))# 利用 DataLoader 来加载数据集
train_dataloader DataLoader(train_data,batch_size64)
test_dataloader DataLoader(test_data,batch_size64)# 创建网络模型
tudui Tudui()# 创建损失函数
loss_fn nn.CrossEntropyLoss() # 分类问题可以用交叉熵# 定义优化器
learning_rate 0.01 # 另一写法1e-2即1x 10^(-2)0.01
optimizer torch.optim.SGD(tudui.parameters(),lrlearning_rate) # SGD 随机梯度下降# 设置训练网络的一些参数
total_train_step 0 # 记录训练次数
total_test_step 0 # 记录测试次数
epoch 10 # 训练轮数for i in range(epoch):print(----------第{}轮训练开始-----------.format(i1)) # i从0-9# 训练步骤开始for data in train_dataloader: # 从训练的dataloader中取数据imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets)# 优化器优化模型optimizer.zero_grad() # 首先要梯度清零loss.backward() # 反向传播得到每一个参数节点的梯度optimizer.step() # 对参数进行优化total_train_step 1print(训练次数{},loss{}.format(total_train_step,loss.item()))
运行结果如下 print(a) 和 print(a.item()) 的区别
import torch
a torch.tensor(5)
print(a)
print(a.item()) 二、完整的模型训练套路二
1.如何知道模型是否训练好或达到需求
每次训练完一轮就进行测试以测试数据集上的损失或正确率来评估模型有没有训练好
测试过程中不需要对模型进行调优利用现有模型进行测试所以有以下命令
with torch.no_grad():
在上述 train.py 代码后继续写
# 测试步骤开始total_test_loss 0with torch.no_grad(): # 无梯度不进行调优for data in test_dataloader:imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets) # 该loss为部分数据在网络模型上的损失为tensor数据类型# 求整体测试数据集上的误差或正确率total_test_loss total_test_loss loss.item() # loss为tensor数据类型而total_test_loss为普通数字所以要.item()一下print(整体测试集上的Loss{}.format(total_test_loss))
结果如下 此处为了使测试的 loss 结果易找在 train.py 中添加了一句 if 的代码使train每训练100轮才打印1次
if total_train_step % 100 0: # 逢百才打印记录print(训练次数{},loss{}.format(total_train_step,loss.item()))
完整代码
import torchvision.datasets
from model import *
from torch import nn
from torch.utils.data import DataLoader# 准备数据集CIFAR10 数据集是PIL Image要转换为tensor数据类型
train_data torchvision.datasets.CIFAR10(root../data,trainTrue,transformtorchvision.transforms.ToTensor(),downloadTrue)
test_data torchvision.datasets.CIFAR10(root../data,trainFalse,transformtorchvision.transforms.ToTensor(),downloadTrue)# 看一下训练数据集和测试数据集都有多少张如何获得数据集的长度
train_data_size len(train_data) # length 长度
test_data_size len(test_data)
# 如果train_data_size10那么打印出的字符串为训练数据集的长度为10
print(训练数据集的长度为{}.format(train_data_size)) # 字符串格式化把format中的变量替换{}
print(测试数据集的长度为{}.format(test_data_size))# 利用 DataLoader 来加载数据集
train_dataloader DataLoader(train_data,batch_size64)
test_dataloader DataLoader(test_data,batch_size64)# 创建网络模型
tudui Tudui()# 创建损失函数
loss_fn nn.CrossEntropyLoss() # 分类问题可以用交叉熵# 定义优化器
learning_rate 0.01 # 另一写法1e-2即1x 10^(-2)0.01
optimizer torch.optim.SGD(tudui.parameters(),lrlearning_rate) # SGD 随机梯度下降# 设置训练网络的一些参数
total_train_step 0 # 记录训练次数
total_test_step 0 # 记录测试次数
epoch 10 # 训练轮数for i in range(epoch):print(----------第{}轮训练开始-----------.format(i1)) # i从0-9# 训练步骤开始for data in train_dataloader:imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets)# 优化器优化模型optimizer.zero_grad() # 首先要梯度清零loss.backward() # 反向传播得到每一个参数节点的梯度optimizer.step() # 对参数进行优化total_train_step 1if total_train_step % 100 0: # 逢百才打印记录print(训练次数{},loss{}.format(total_train_step,loss.item()))# 测试步骤开始total_test_loss 0with torch.no_grad(): # 无梯度不进行调优for data in test_dataloader:imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets) # 该loss为部分数据在网络模型上的损失为tensor数据类型# 求整体测试数据集上的误差或正确率total_test_loss total_test_loss loss.item() # loss为tensor数据类型而total_test_loss为普通数字print(整体测试集上的Loss{}.format(total_test_loss))
2. 与 TensorBoard 结合
添加TensorBoard后的代码
import torchvision.datasets
from torch.utils.tensorboard import SummaryWriterfrom model import *
from torch import nn
from torch.utils.data import DataLoader# 准备数据集CIFAR10 数据集是PIL Image要转换为tensor数据类型
train_data torchvision.datasets.CIFAR10(root../data,trainTrue,transformtorchvision.transforms.ToTensor(),downloadTrue)
test_data torchvision.datasets.CIFAR10(root../data,trainFalse,transformtorchvision.transforms.ToTensor(),downloadTrue)# 看一下训练数据集和测试数据集都有多少张如何获得数据集的长度
train_data_size len(train_data) # length 长度
test_data_size len(test_data)
# 如果train_data_size10那么打印出的字符串为训练数据集的长度为10
print(训练数据集的长度为{}.format(train_data_size)) # 字符串格式化把format中的变量替换{}
print(测试数据集的长度为{}.format(test_data_size))# 利用 DataLoader 来加载数据集
train_dataloader DataLoader(train_data,batch_size64)
test_dataloader DataLoader(test_data,batch_size64)# 创建网络模型
tudui Tudui()# 创建损失函数
loss_fn nn.CrossEntropyLoss() # 分类问题可以用交叉熵# 定义优化器
learning_rate 0.01 # 另一写法1e-2即1x 10^(-2)0.01
optimizer torch.optim.SGD(tudui.parameters(),lrlearning_rate) # SGD 随机梯度下降# 设置训练网络的一些参数
total_train_step 0 # 记录训练次数
total_test_step 0 # 记录测试次数
epoch 10 # 训练轮数# 添加tensorboard
writer SummaryWriter(../logs_train)for i in range(epoch):print(----------第{}轮训练开始-----------.format(i1)) # i从0-9# 训练步骤开始for data in train_dataloader:imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets)# 优化器优化模型optimizer.zero_grad() # 首先要梯度清零loss.backward() # 反向传播得到每一个参数节点的梯度optimizer.step() # 对参数进行优化total_train_step 1if total_train_step % 100 0: # 逢百才打印记录print(训练次数{},loss{}.format(total_train_step,loss.item()))writer.add_scalar(train_loss,loss.item(),total_train_step)# 测试步骤开始total_test_loss 0with torch.no_grad(): # 无梯度不进行调优for data in test_dataloader:imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets) # 该loss为部分数据在网络模型上的损失为tensor数据类型# 求整体测试数据集上的误差或正确率total_test_loss total_test_loss loss.item() # loss为tensor数据类型而total_test_loss为普通数字print(整体测试集上的Loss{}.format(total_test_loss))writer.add_scalar(test_loss,total_test_loss,total_test_step)total_test_step 1writer.close()
运行结果 在 Terminal 里输入
tensorboard --logdirlogs_train
打开网页后显示图片 3. 保存每一轮训练的模型
添加两句代码 torch.save(tudui,tudui_{}.pth.format(i)) # 每一轮保存一个结果print(模型已保存)writer.close()
运行后 正确率的实现对分类问题
4.正确率的实现对分类问题
即便得到整体测试集上的 loss也不能很好说明在测试集上的表现效果
在分类问题中可以用正确率表示下述代码改进在目标检测/语义分割中可以把输出放在tensorboard里显示看测试结果
例子 第一步个人理解argmax()返回数组中最大值的索引。
import torchoutputs torch.tensor([[0.1,0.2],[0.3,0.4]])
print(outputs.argmax(1)) # 0或1表示方向1为横向比较大小. 运行结果tensor([1, 1]) 第二步
preds outputs.argmax(1)
targets torch.tensor([0,1])
print(preds targets) # tensor([False, True])
print(sum(preds targets).sum()) # tensor(1)对应位置相等的个数
上例说明了基本用法现对原问题的代码再进一步优化计算整体正确率 # 测试步骤开始total_test_loss 0total_accuracy 0with torch.no_grad(): # 无梯度不进行调优for data in test_dataloader:imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets) # 该loss为部分数据在网络模型上的损失为tensor数据类型# 求整体测试数据集上的误差或正确率total_test_loss total_test_loss loss.item() # loss为tensor数据类型而total_test_loss为普通数字# 求整体测试数据集上的误差或正确率accuracy (outputs.argmax(1) targets).sum() # 1横向比较True或Falsesum计算True或False个数total_accuracy total_accuracy accuracyprint(整体测试集上的Loss{}.format(total_test_loss))print(整体测试集上的正确率{}.format(total_accuracy/imgs.size(0)))writer.add_scalar(test_loss,total_test_loss,total_test_step)writer.add_scalar(test_accuracy,total_accuracy/imgs.size(0),total_test_step)total_test_step 1torch.save(tudui,tudui_{}.pth.format(i)) # 每一轮保存一个结果print(模型已保存)writer.close()
运行结果 在 Terminal 里输入
tensorboard --logdirlogs_train
打开网址 三、完整的模型训练套路三
此章节注意一些细节
1.train.py 完整代码
import torchvision.datasets
from torch.utils.tensorboard import SummaryWriterfrom model import *
from torch import nn
from torch.utils.data import DataLoader# 准备数据集CIFAR10 数据集是PIL Image要转换为tensor数据类型
train_data torchvision.datasets.CIFAR10(root../data,trainTrue,transformtorchvision.transforms.ToTensor(),downloadTrue)
test_data torchvision.datasets.CIFAR10(root../data,trainFalse,transformtorchvision.transforms.ToTensor(),downloadTrue)# 看一下训练数据集和测试数据集都有多少张如何获得数据集的长度
train_data_size len(train_data) # length 长度
test_data_size len(test_data)
# 如果train_data_size10那么打印出的字符串为训练数据集的长度为10
print(训练数据集的长度为{}.format(train_data_size)) # 字符串格式化把format中的变量替换{}
print(测试数据集的长度为{}.format(test_data_size))# 利用 DataLoader 来加载数据集
train_dataloader DataLoader(train_data,batch_size64)
test_dataloader DataLoader(test_data,batch_size64)# 创建网络模型
tudui Tudui()# 创建损失函数
loss_fn nn.CrossEntropyLoss() # 分类问题可以用交叉熵# 定义优化器
learning_rate 0.01 # 另一写法1e-2即1x 10^(-2)0.01
optimizer torch.optim.SGD(tudui.parameters(),lrlearning_rate) # SGD 随机梯度下降# 设置训练网络的一些参数
total_train_step 0 # 记录训练次数
total_test_step 0 # 记录测试次数
epoch 10 # 训练轮数# 添加tensorboard
writer SummaryWriter(../logs_train)for i in range(epoch):print(----------第{}轮训练开始-----------.format(i1)) # i从0-9# 训练步骤开始for data in train_dataloader:imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets)# 优化器优化模型optimizer.zero_grad() # 首先要梯度清零loss.backward() # 反向传播得到每一个参数节点的梯度optimizer.step() # 对参数进行优化total_train_step 1if total_train_step % 100 0: # 逢百才打印记录print(训练次数{},loss{}.format(total_train_step,loss.item()))writer.add_scalar(train_loss,loss.item(),total_train_step)# 测试步骤开始total_test_loss 0total_accuracy 0with torch.no_grad(): # 无梯度不进行调优for data in test_dataloader:imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets) # 该loss为部分数据在网络模型上的损失为tensor数据类型# 求整体测试数据集上的误差或正确率total_test_loss total_test_loss loss.item() # loss为tensor数据类型而total_test_loss为普通数字# 求整体测试数据集上的误差或正确率accuracy (outputs.argmax(1) targets).sum() # 1横向比较True或Falsesum计算True或False个数total_accuracy total_accuracy accuracyprint(整体测试集上的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 1torch.save(tudui,tudui_{}.pth.format(i)) # 每一轮保存一个结果print(模型已保存)writer.close()
2.model.train() 和 model.eval() 训练步骤开始之前会把网络模型我们这里的网络模型叫 tudui设置为train并不是说把网络设置为训练模型它才能够开始训练 测试网络前写 网络.eval()并不是说需要这一行才能把网络设置成 eval 状态才能进行网络测试。
3.作用
这两句不写网络依然可以运行它们的作用是 本节写的案例没有 Dropout 层或 BatchNorm 层所以有没有这两行无所谓
如果有这些特殊层一定要调用。
回顾案例
首先要准备数据集准备对应的 dataloader
import torchvision.datasets
from torch.utils.tensorboard import SummaryWriterfrom model import *
from torch import nn
from torch.utils.data import DataLoader# 准备数据集CIFAR10 数据集是PIL Image要转换为tensor数据类型
train_data torchvision.datasets.CIFAR10(root../data,trainTrue,transformtorchvision.transforms.ToTensor(),downloadTrue)
test_data torchvision.datasets.CIFAR10(root../data,trainFalse,transformtorchvision.transforms.ToTensor(),downloadTrue)# 看一下训练数据集和测试数据集都有多少张如何获得数据集的长度
train_data_size len(train_data) # length 长度
test_data_size len(test_data)
# 如果train_data_size10那么打印出的字符串为训练数据集的长度为10
print(训练数据集的长度为{}.format(train_data_size)) # 字符串格式化把format中的变量替换{}
print(测试数据集的长度为{}.format(test_data_size))# 利用 DataLoader 来加载数据集
train_dataloader DataLoader(train_data,batch_size64)
test_dataloader DataLoader(test_data,batch_size64)
调用
tudui.train()
使网络进入训练状态从训练的 dataloader 中不断取数据算出误差放到优化器中进行优化采用某种特定的方式展示输出一轮结束后或特定步数后进行测试 # 训练步骤开始for data in train_dataloader:imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets)# 优化器优化模型optimizer.zero_grad() # 首先要梯度清零loss.backward() # 反向传播得到每一个参数节点的梯度optimizer.step() # 对参数进行优化total_train_step 1if total_train_step % 100 0: # 逢百才打印记录print(训练次数{},loss{}.format(total_train_step,loss.item()))writer.add_scalar(train_loss,loss.item(),total_train_step)
测试过程中可以设置 tudui.eval()
要设置 with torch.no_grad(): 让网络模型中的参数都没有因为我们只需要进行测试不需要对网络模型进行调整更不需要利用梯度来优化。 从测试数据集中取数据计算误差构建特殊指标显示出来。 for data in test_dataloader:imgs,targets dataoutputs tudui(imgs)loss loss_fn(outputs,targets) # 该loss为部分数据在网络模型上的损失为tensor数据类型# 求整体测试数据集上的误差或正确率total_test_loss total_test_loss loss.item() # loss为tensor数据类型而total_test_loss为普通数字# 求整体测试数据集上的误差或正确率accuracy (outputs.argmax(1) targets).sum() # 1横向比较True或Falsesum计算True或False个数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 1
在特定步数或某一轮可以保存模型保存模型的方式是之前讲的方式1 torch.save(tudui,tudui_{}.pth.format(i))
回忆官方推荐的方式2 torch.save(tudui.state_dict,tudui_{}.pth.format(i))
将网络模型的状态转化为字典型展示它的特定保存位置
四、利用GPU训练一
两种方式实现代码在GPU上训练
1.第一种使用GPU训练的方式 1.网络模型 2.数据包括输入、标注 训练过程 测试过程
3.损失函数 更好的写法其他几个地方也可以类似这样写 其他地方同理加上
这种写法在CPU和GPU上都可以跑优先在GPU上跑
train_gpu_1 整体完整代码
import torch
import torchvision.datasets
from torch.utils.tensorboard import SummaryWriter
from torch import nn
from torch.utils.data import DataLoader# 准备数据集CIFAR10 数据集是PIL Image要转换为tensor数据类型
train_data torchvision.datasets.CIFAR10(root../data, trainTrue, transformtorchvision.transforms.ToTensor(),downloadTrue)
test_data torchvision.datasets.CIFAR10(root../data, trainFalse, transformtorchvision.transforms.ToTensor(),downloadTrue)# 看一下训练数据集和测试数据集都有多少张如何获得数据集的长度
train_data_size len(train_data) # length 长度
test_data_size len(test_data)
# 如果train_data_size10那么打印出的字符串为训练数据集的长度为10
print(训练数据集的长度为{}.format(train_data_size)) # 字符串格式化把format中的变量替换{}
print(测试数据集的长度为{}.format(test_data_size))# 利用 DataLoader 来加载数据集
train_dataloader DataLoader(train_data, batch_size64)
test_dataloader DataLoader(test_data, batch_size64)# 创建网络模型class Tudui(nn.Module):def __init__(self):super(Tudui, 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(64 * 4 * 4,64),nn.Linear(64, 10))def forward(self, x):x self.model(x)return xtudui Tudui()
if torch.cuda.is_available():tudui tudui.cuda()# 创建损失函数
loss_fn nn.CrossEntropyLoss() # 分类问题可以用交叉熵
if torch.cuda.is_available():loss_fn loss_fn.cuda()
# 定义优化器
learning_rate 0.01 # 另一写法1e-2即1x 10^(-2)0.01
optimizer torch.optim.SGD(tudui.parameters(), lrlearning_rate) # SGD 随机梯度下降# 设置训练网络的一些参数
total_train_step 0 # 记录训练次数
total_test_step 0 # 记录测试次数
epoch 10 # 训练轮数# 添加tensorboard
writer SummaryWriter(../logs_train)
for i in range(epoch):print(----------第{}轮训练开始-----------.format(i 1)) # i从0-9# 训练步骤开始for data in train_dataloader:imgs, targets dataif torch.cuda.is_available():imgs imgs.cuda()targets targets.cuda()outputs tudui(imgs)loss loss_fn(outputs, targets)# 优化器优化模型optimizer.zero_grad() # 首先要梯度清零loss.backward() # 反向传播得到每一个参数节点的梯度optimizer.step() # 对参数进行优化total_train_step 1if total_train_step % 100 0: # 逢百才打印记录print(训练次数{},loss{}.format(total_train_step, loss.item()))writer.add_scalar(train_loss, loss.item(), total_train_step)# 测试步骤开始tudui.eval()total_test_loss 0total_accuracy 0with torch.no_grad(): # 无梯度不进行调优for data in test_dataloader:imgs, targets dataif torch.cuda.is_available():imgs imgs.cuda()targets targets.cuda()outputs tudui(imgs)loss loss_fn(outputs, targets) # 该loss为部分数据在网络模型上的损失为tensor数据类型# 求整体测试数据集上的误差或正确率total_test_loss total_test_loss loss.item() # loss为tensor数据类型而total_test_loss为普通数字# 求整体测试数据集上的误差或正确率accuracy (outputs.argmax(1) targets).sum() # 1横向比较True或Falsesum计算True或False个数total_accuracy total_accuracy accuracyprint(整体测试集上的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 1torch.save(tudui, tudui_{}.pth.format(i)) # 每一轮保存一个结果print(模型已保存)writer.close()
2. 比较CPU/GPU训练时间
为了比较时间引入 time 这个 package
1对于CPU
1.引用 time 的 package 2.记录开始时间 3. 记录截至时间并输出所用时间 4. 运行 train.py可以看到它的运行时间 2 对于GPU
与上面相同的步骤相同地方引入time运行后结果如下 时间竟然比CPU长我不理解呜呜呜
3查看GPU信息
在 Terminal 里输入
nvidia-smi
会出现一些GPU的信息 3.Google Colab
Google 为我们提供了一个免费的GPU默认提供的环境当中就有Pytorch使用过程需要魔法tz哦
colab 网站https://colab.research.google.com/
进来时候新建笔记本 输入代码运行后我们发现现在还不能使用GPU 1.如何在Google Colab使用GPU 修改 —— 笔记本设置 —— 硬件加速器选择GPU每周免费使用30h
(使用GPU后会重新启动环境) 设置后对比 将 train_gpu_1.py 代码复制进去运行速度很快结果如下 查看GPU配置
在 Google Colab 上运行 terminal 中运行的东西在语句前加 !感叹号 五、利用GPU训练一
1.第二种使用GPU训练的方式更常用 以下两种写法对于单显卡来说等价
device torch.device(cuda)device torch.device(cuda:0)
1.定义训练的设备 通过这个变量可以控制是在CPU上运行还是GPU改成 cuda 或 cuda:0 上运行 2.模型 这里第二句可以不用再赋值给 tudui直接 tudui.to(device) 也可以
3.损失函数 4.输入输出数据必须要赋值 网络模型、损失函数都不需要另外赋值直接 .to(device) 就可以
但是数据图片、标注需要另外转移之后再重新赋值给变量
语法糖一种语法的简写程序在 CPU 或 GPU/cuda 环境下都能运行
device torch.device(cuda if torch.cuda.is_available() else cpu)
六完整的模型验证测试、demo套路
核心利用已经训练好的模型给它提供输入进行测试类似之前案例中测试集的测试部分 pytorch-CycleGAN-and-pix2pix 1.示例 1
Resize() 随便在网络上找图片通过 Resize() 使图片符合模型
# 如何从test.py文件去找到dog文件相对路径
import torch
import torchvision.transforms
from PIL import Image
from torch import nnimage_path ../imgs/dog.png # 或右键- Copy Path- Absolute Path绝对路径
# 读取图片PIL Image再用ToTensor进行转换
image Image.open(image_path) # 现在的image是PIL类型
print(image) # PIL.PngImagePlugin.PngImageFile image modeRGB size430x247 at 0x1DF29D33AF0# image image.convert(RGB)
# 因为png格式是四通道除了RGB三通道外还有一个透明度通道所以要调用上述语句保留其颜色通道
# 当然如果图片本来就是三颜色通道经过此操作不变
# 加上这一步后可以适应 png jpg 各种格式的图片# 该image大小为430x247网络模型的输入只能是32x32进行一个Resize()
# Compose()把transforms几个变换联立在一起
transform torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)), # 32x32大小的PIL Imagetorchvision.transforms.ToTensor()]) # 转为Tensor数据类型
image transform(image)
print(image.shape) # torch.Size([3, 32, 32])# 加载网络模型之前采用的是第一种方式保存故需要采用第一种方式加载
# 首先搭建神经网络10分类网络
class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()# 把网络放到序列中self.model nn.Sequential(nn.Conv2d(in_channels3,out_channels32,kernel_size5,stride1,padding2), #输入是32x32的输出还是32x32的padding经计算为2nn.MaxPool2d(kernel_size2),nn.Conv2d(in_channels32,out_channels32,kernel_size5,stride1,padding2), #输入输出都是16x16的同理padding经计算为2nn.MaxPool2d(kernel_size2),nn.Conv2d(in_channels32,out_channels64,kernel_size5,stride1,padding2),nn.MaxPool2d(kernel_size2),nn.Flatten(), # 展平nn.Linear(in_features64*4*4,out_features64),nn.Linear(in_features64,out_features10))def forward(self,x):x self.model(x)return x
# 然后加载网络模型
model torch.load(tudui_0.pth) # 因为test.py和tudui_0.pth在同一个层级下所以地址可以直接写
print(model)output model(image)
print(output)
运行会报错报错提示如下
RuntimeError: Expected 4-dimensional input for 4-dimensional weight [32, 3, 5, 5], but got 3-dimensional input of size [3, 32, 32] instead 原因要求是四维的输入 [batch_size,channel,length,width]但是获得的图片是三维的 —— 图片没有指定 batch_size网络训练过程中是需要 batch_size 的而图片输入是三维的需要reshape() 一下
解决torch.reshape() 方法
在上述代码后面加上
image torch.reshape(image,(1,3,32,32))
model.eval() # 模型转化为测试类型
with torch.no_grad(): # 节约内存和性能output model(image)
print(output)
运行结果 1.3220 概率最大预测的是第六类
print(output.argmax(1)) CIFAR10 对应的真实类别: 怎么找到 第六类对应的是 frog青蛙 预测错误的原因可能是训练次数不够多在 Google Colab 里将训练轮数 epoch 改为 30 次完整代码train.py
import torch
import torchvision.datasets
from torch.utils.tensorboard import SummaryWriter# from model import *
from torch import nn
from torch.utils.data import DataLoader
import time # time这个package是用来计时的# 准备数据集CIFAR10 数据集是PIL Image要转换为tensor数据类型
device torch.device(cuda)
print(device)
train_data torchvision.datasets.CIFAR10(root../data,trainTrue,transformtorchvision.transforms.ToTensor(),downloadTrue)
test_data torchvision.datasets.CIFAR10(root../data,trainFalse,transformtorchvision.transforms.ToTensor(),downloadTrue)# 看一下训练数据集和测试数据集都有多少张如何获得数据集的长度
train_data_size len(train_data) # length 长度
test_data_size len(test_data)
# 如果train_data_size10那么打印出的字符串为训练数据集的长度为10
print(训练数据集的长度为{}.format(train_data_size)) # 字符串格式化把format中的变量替换{}
print(测试数据集的长度为{}.format(test_data_size))# 利用 DataLoader 来加载数据集
train_dataloader DataLoader(train_data,batch_size64)
test_dataloader DataLoader(test_data,batch_size64)# 搭建神经网络10分类网络
class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()# 把网络放到序列中self.model nn.Sequential(nn.Conv2d(in_channels3,out_channels32,kernel_size5,stride1,padding2), #输入是32x32的输出还是32x32的padding经计算为2nn.MaxPool2d(kernel_size2),nn.Conv2d(in_channels32,out_channels32,kernel_size5,stride1,padding2), #输入输出都是16x16的同理padding经计算为2nn.MaxPool2d(kernel_size2),nn.Conv2d(in_channels32,out_channels64,kernel_size5,stride1,padding2),nn.MaxPool2d(kernel_size2),nn.Flatten(), # 展平nn.Linear(in_features64*4*4,out_features64),nn.Linear(in_features64,out_features10))def forward(self,x):x self.model(x)return x# 创建网络模型
tudui Tudui()
tudui.to(device)# 创建损失函数
loss_fn nn.CrossEntropyLoss() # 分类问题可以用交叉熵
loss_fn.to(device)# 定义优化器
learning_rate 0.01 # 另一写法1e-2即1x 10^(-2)0.01
optimizer torch.optim.SGD(tudui.parameters(),lrlearning_rate) # SGD 随机梯度下降# 设置训练网络的一些参数
total_train_step 0 # 记录训练次数
total_test_step 0 # 记录测试次数
epoch 30 # 训练轮数# 添加tensorboard
writer SummaryWriter(../logs_train)
start_time time.time() # 记录下此时的时间赋值给开始时间for i in range(epoch):print(----------第{}轮训练开始-----------.format(i1)) # i从0-9# 训练步骤开始tudui.train()for data in train_dataloader:imgs,targets dataimgs imgs.to(device)targets targets.to(device)outputs tudui(imgs)loss loss_fn(outputs,targets)# 优化器优化模型optimizer.zero_grad() # 首先要梯度清零loss.backward() # 反向传播得到每一个参数节点的梯度optimizer.step() # 对参数进行优化total_train_step 1if total_train_step % 100 0: # 逢百才打印记录end_time time.time()print(end_time - start_time) # 第一次训练100次所花费的时间print(训练次数{},loss{}.format(total_train_step,loss.item()))writer.add_scalar(train_loss,loss.item(),total_train_step)# 测试步骤开始tudui.eval()total_test_loss 0total_accuracy 0with torch.no_grad(): # 无梯度不进行调优for data in test_dataloader:imgs,targets dataimgs imgs.to(device)targets targets.to(device)outputs tudui(imgs)loss loss_fn(outputs,targets) # 该loss为部分数据在网络模型上的损失为tensor数据类型# 求整体测试数据集上的误差或正确率total_test_loss total_test_loss loss.item() # loss为tensor数据类型而total_test_loss为普通数字accuracy (outputs.argmax(1) targets).sum() # 1横向比较True或Falsesum计算True或False个数total_accuracy total_accuracy accuracyprint(整体测试集上的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_test_loss,total_test_step,total_test_step)total_test_step 1torch.save(tudui,tudui_{}_gpu.pth.format(i)) # 每一轮保存一个结果print(模型已保存)writer.close()
运行结果 下载后复制到 PyCharm 中 Learn_Torch 的 src 文件夹下然后将之前 test.py 中的路径修改为
model torch.load(tudui_29_gpu.pth)
运行后报错报错提示
RuntimeError: Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor) should be the same or input should be a MKLDNN tensor and weight is a dense tensor
原因采用GPU训练的模型在CPU上加载要从GPU上映射到CPU上在不同环境中加载已经训练好的模型需要经过映射
解决
model torch.load(tudui_29_gpu.pth,map_locationtorch.device(cpu)) test.py把训练模型运用到实际环境中完整代码
# 如何从test.py文件去找到dog文件相对路径
import torch
import torchvision.transforms
from PIL import Image
from torch import nnimage_path ../imgs/airplane.png # 或右键- Copy Path- Absolute Path绝对路径
# 读取图片PIL Image再用ToTensor进行转换
image Image.open(image_path) # 现在的image是PIL类型
print(image) # PIL.PngImagePlugin.PngImageFile image modeRGB size430x247 at 0x1DF29D33AF0# image image.convert(RGB)
# 因为png格式是四通道除了RGB三通道外还有一个透明度通道所以要调用上述语句保留其颜色通道
# 当然如果图片本来就是三颜色通道经过此操作不变
# 加上这一步后可以适应 png jpg 各种格式的图片# 该image大小为430x247网络模型的输入只能是32x32进行一个Resize()
# Compose()把transforms几个变换联立在一起
transform torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)), # 32x32大小的PIL Imagetorchvision.transforms.ToTensor()]) # 转为Tensor数据类型
image transform(image)
print(image.shape) # torch.Size([3, 32, 32])# 加载网络模型之前采用的是第一种方式保存故需要采用第一种方式加载
# 首先搭建神经网络10分类网络
class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()# 把网络放到序列中self.model nn.Sequential(nn.Conv2d(in_channels3,out_channels32,kernel_size5,stride1,padding2), #输入是32x32的输出还是32x32的padding经计算为2nn.MaxPool2d(kernel_size2),nn.Conv2d(in_channels32,out_channels32,kernel_size5,stride1,padding2), #输入输出都是16x16的同理padding经计算为2nn.MaxPool2d(kernel_size2),nn.Conv2d(in_channels32,out_channels64,kernel_size5,stride1,padding2),nn.MaxPool2d(kernel_size2),nn.Flatten(), # 展平nn.Linear(in_features64*4*4,out_features64),nn.Linear(in_features64,out_features10))def forward(self,x):x self.model(x)return x
# 然后加载网络模型
model torch.load(tudui_29_gpu.pth,map_locationtorch.device(cpu)) # 因为test.py和tudui_0.pth在同一个层级下所以地址可以直接写
print(model)
image torch.reshape(image,(1,3,32,32))
model.eval() # 模型转化为测试类型
with torch.no_grad():output model(image)
print(output)
print(output.argmax(1))
2.示例二
再以飞机的图片为例airplane.png 保存在 imgs 文件夹里
# 如何从test.py文件去找到dog文件相对路径
import torch
import torchvision.transforms
from PIL import Image
from torch import nnimage_path ../imgs/airplane.png # 或右键- Copy Path- Absolute Path绝对路径
# 读取图片PIL Image再用ToTensor进行转换
image Image.open(image_path) # 现在的image是PIL类型
print(image) # PIL.PngImagePlugin.PngImageFile image modeRGB size430x247 at 0x1DF29D33AF0# image image.convert(RGB)
# 因为png格式是四通道除了RGB三通道外还有一个透明度通道所以要调用上述语句保留其颜色通道
# 当然如果图片本来就是三颜色通道经过此操作不变
# 加上这一步后可以适应 png jpg 各种格式的图片# 该image大小为430x247网络模型的输入只能是32x32进行一个Resize()
# Compose()把transforms几个变换联立在一起
transform torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)), # 32x32大小的PIL Imagetorchvision.transforms.ToTensor()]) # 转为Tensor数据类型
image transform(image)
print(image.shape) # torch.Size([3, 32, 32])# 加载网络模型之前采用的是第一种方式保存故需要采用第一种方式加载
# 首先搭建神经网络10分类网络
class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()# 把网络放到序列中self.model nn.Sequential(nn.Conv2d(in_channels3,out_channels32,kernel_size5,stride1,padding2), #输入是32x32的输出还是32x32的padding经计算为2nn.MaxPool2d(kernel_size2),nn.Conv2d(in_channels32,out_channels32,kernel_size5,stride1,padding2), #输入输出都是16x16的同理padding经计算为2nn.MaxPool2d(kernel_size2),nn.Conv2d(in_channels32,out_channels64,kernel_size5,stride1,padding2),nn.MaxPool2d(kernel_size2),nn.Flatten(), # 展平nn.Linear(in_features64*4*4,out_features64),nn.Linear(in_features64,out_features10))def forward(self,x):x self.model(x)return x
# 然后加载网络模型
model torch.load(tudui_29_gpu.pth,map_locationtorch.device(cpu)) # 因为test.py和tudui_0.pth在同一个层级下所以地址可以直接写
print(model)
image torch.reshape(image,(1,3,32,32))
model.eval() # 模型转化为测试类型
with torch.no_grad():output model(image)
print(output)
print(output.argmax(1)) # 把输出转换为一种利于解读的方式 运行结果 第 0 类就是 airplane预测正确
注意
model.eval() # 模型转化为测试类型
with torch.no_grad():
(这两行不写也可以但为了养成良好的代码习惯最好写上。如果网络模型中正好有 Dropout 或 BatchNorm 时不写的话预测就会有问题)
(七)、看看开源项目 网站地址GitHub - junyanz/pytorch-CycleGAN-and-pix2pix: Image-to-Image Translation in PyTorch
README.md
先读 README.md怎么安装、注意事项 train.py
General-purpose training script for image-to-image translation.
This script works for various models (with option --model: e.g., pix2pix, cyclegan, colorization) and
different datasets (with option --dataset_mode: e.g., aligned, unaligned, single, colorization).
You need to specify the dataset (--dataroot), experiment name (--name), and model (--model).
It first creates model, dataset, and visualizer given the option.
It then does standard network training. During the training, it also visualize/save the images, print/save the loss plot, and save models.
The script supports continue/resume training. Use --continue_train to resume your previous training.
Example:Train a CycleGAN model:python train.py --dataroot ./datasets/maps --name maps_cyclegan --model cycle_ganTrain a pix2pix model:python train.py --dataroot ./datasets/facades --name facades_pix2pix --model pix2pix --direction BtoA
See options/base_options.py and options/train_options.py for more training options.
See training and test tips at: https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix/blob/master/docs/tips.md
See frequently asked questions at: https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix/blob/master/docs/qa.mdimport time
from options.train_options import TrainOptions
from data import create_dataset
from models import create_model
from util.visualizer import Visualizerif __name__ __main__:opt TrainOptions().parse() # get training optionsdataset create_dataset(opt) # create a dataset given opt.dataset_mode and other optionsdataset_size len(dataset) # get the number of images in the dataset.print(The number of training images %d % dataset_size)model create_model(opt) # create a model given opt.model and other optionsmodel.setup(opt) # regular setup: load and print networks; create schedulersvisualizer Visualizer(opt) # create a visualizer that display/save images and plotstotal_iters 0 # the total number of training iterationsfor epoch in range(opt.epoch_count, opt.n_epochs opt.n_epochs_decay 1): # outer loop for different epochs; we save the model by epoch_count, epoch_countsave_latest_freqepoch_start_time time.time() # timer for entire epochiter_data_time time.time() # timer for data loading per iterationepoch_iter 0 # the number of training iterations in current epoch, reset to 0 every epochvisualizer.reset() # reset the visualizer: make sure it saves the results to HTML at least once every epochmodel.update_learning_rate() # update learning rates in the beginning of every epoch.for i, data in enumerate(dataset): # inner loop within one epochiter_start_time time.time() # timer for computation per iterationif total_iters % opt.print_freq 0:t_data iter_start_time - iter_data_timetotal_iters opt.batch_sizeepoch_iter opt.batch_sizemodel.set_input(data) # unpack data from dataset and apply preprocessingmodel.optimize_parameters() # calculate loss functions, get gradients, update network weightsif total_iters % opt.display_freq 0: # display images on visdom and save images to a HTML filesave_result total_iters % opt.update_html_freq 0model.compute_visuals()visualizer.display_current_results(model.get_current_visuals(), epoch, save_result)if total_iters % opt.print_freq 0: # print training losses and save logging information to the disklosses model.get_current_losses()t_comp (time.time() - iter_start_time) / opt.batch_sizevisualizer.print_current_losses(epoch, epoch_iter, losses, t_comp, t_data)if opt.display_id 0:visualizer.plot_current_losses(epoch, float(epoch_iter) / dataset_size, losses)if total_iters % opt.save_latest_freq 0: # cache our latest model every save_latest_freq iterationsprint(saving the latest model (epoch %d, total_iters %d) % (epoch, total_iters))save_suffix iter_%d % total_iters if opt.save_by_iter else latestmodel.save_networks(save_suffix)iter_data_time time.time()if epoch % opt.save_epoch_freq 0: # cache our model every save_epoch_freq epochsprint(saving the model at the end of epoch %d, iters %d % (epoch, total_iters))model.save_networks(latest)model.save_networks(epoch)print(End of epoch %d / %d \t Time Taken: %d sec % (epoch, opt.n_epochs opt.n_epochs_decay, time.time() - epoch_start_time)) 训练参数设置 from .base_options import BaseOptionsclass TrainOptions(BaseOptions):This class includes training options.It also includes shared options defined in BaseOptions.def initialize(self, parser):parser BaseOptions.initialize(self, parser)# visdom and HTML visualization parametersparser.add_argument(--display_freq, typeint, default400, helpfrequency of showing training results on screen)parser.add_argument(--display_ncols, typeint, default4, helpif positive, display all images in a single visdom web panel with certain number of images per row.)parser.add_argument(--display_id, typeint, default1, helpwindow id of the web display)parser.add_argument(--display_server, typestr, defaulthttp://localhost, helpvisdom server of the web display)parser.add_argument(--display_env, typestr, defaultmain, helpvisdom display environment name (default is main))parser.add_argument(--display_port, typeint, default8097, helpvisdom port of the web display)parser.add_argument(--update_html_freq, typeint, default1000, helpfrequency of saving training results to html)parser.add_argument(--print_freq, typeint, default100, helpfrequency of showing training results on console)parser.add_argument(--no_html, actionstore_true, helpdo not save intermediate training results to [opt.checkpoints_dir]/[opt.name]/web/)# network saving and loading parametersparser.add_argument(--save_latest_freq, typeint, default5000, helpfrequency of saving the latest results)parser.add_argument(--save_epoch_freq, typeint, default5, helpfrequency of saving checkpoints at the end of epochs)parser.add_argument(--save_by_iter, actionstore_true, helpwhether saves model by iteration)parser.add_argument(--continue_train, actionstore_true, helpcontinue training: load the latest model)parser.add_argument(--epoch_count, typeint, default1, helpthe starting epoch count, we save the model by epoch_count, epoch_countsave_latest_freq, ...)parser.add_argument(--phase, typestr, defaulttrain, helptrain, val, test, etc)# training parametersparser.add_argument(--n_epochs, typeint, default100, helpnumber of epochs with the initial learning rate)parser.add_argument(--n_epochs_decay, typeint, default100, helpnumber of epochs to linearly decay learning rate to zero)parser.add_argument(--beta1, typefloat, default0.5, helpmomentum term of adam)parser.add_argument(--lr, typefloat, default0.0002, helpinitial learning rate for adam)parser.add_argument(--gan_mode, typestr, defaultlsgan, helpthe type of GAN objective. [vanilla| lsgan | wgangp]. vanilla GAN loss is the cross-entropy objective used in the original GAN paper.)parser.add_argument(--pool_size, typeint, default50, helpthe size of image buffer that stores previously generated images)parser.add_argument(--lr_policy, typestr, defaultlinear, helplearning rate policy. [linear | step | plateau | cosine])parser.add_argument(--lr_decay_iters, typeint, default50, helpmultiply by a gamma every lr_decay_iters iterations)self.isTrain Truereturn parser 没有dataroot 点进其继承的父类查看可以看到有dataroot 下载代码用 PyCharm 打开后查看代码里有没有 requiredTrue若有删掉 requiredTrue 加一个默认值 default./dataset/maps 就可以在 PyCharm 里右键运行了 即找到所有 requiredTrue 的参数将它删去并添加上默认值default 。 这篇课程的学习和总结到这里就结束啦如果有什么问题可以在评论区留言呀~
如果帮助到大家可以一键三连关注支持下~ 学习系列笔记(已完结)
【我是土堆 - Pytorch教程】 知识点 学习总结笔记一_耿鬼喝椰汁的博客-CSDN博客
【我是土堆 - Pytorch教程】 知识点 学习总结笔记二_耿鬼喝椰汁的博客-CSDN博客
【我是土堆 - Pytorch教程】 知识点 学习总结笔记三_耿鬼喝椰汁的博客-CSDN博客
【我是土堆 - Pytorch教程】 知识点 学习总结笔记四_耿鬼喝椰汁的博客-CSDN博客
【我是土堆 - Pytorch教程】 知识点 学习总结笔记五_耿鬼喝椰汁的博客-CSDN博客