1. 完整的模型验证套路
当我们训练好模型之后,需要对模型进行验证来判断它的好坏
验证模型的核心:利用已经训练好的模型,给它提供输入。
我们需要预检验的图片是一只狗。
接下来,直接上代码演示。
import torch
import torchvision.transforms
from PIL import Image
from torch import nn
from torchvision import transforms
# 图片路径
image_path = "./images/dog.jpg"
# 用PIL打开图片,因为transform是基于PIL的基础上处理的
image = Image.open(image_path)
print(image)
# 有些图片格式可能不是3通道,用这个不管是几通道都可以转换成3通道,保险起见还是加上
image = image.convert('RGB')
# 把图片转化为 32*32大小,然后再toTensor
transform = transforms.Compose([torchvision.transforms.Resize((32, 32)),
torchvision.transforms.ToTensor()])
image = transform(image)
# 查看图片的大小是否正确
print(image.shape)
# 网络模型,因为是自己编写的,所以需要在这里编写出来,否则load会报错
class MCifar(torch.nn.Module):
def __init__(self):
super(MCifar, self).__init__()
self.model = nn.Sequential(
nn.Conv2d(3, 32, 5, 1, 2),
nn.MaxPool2d(2, 2),
nn.Conv2d(32, 32, 5, 1, 2),
nn.MaxPool2d(2, 2),
nn.Conv2d(32, 64, 5, 1, 2),
nn.MaxPool2d(2, 2),
nn.Flatten(),
nn.Linear(1024, 64),
nn.Linear(64, 10),
)
def forward(self, x):
x = self.model(x)
return x
# 导入训练好的模型参数。
# 注意:如果是在GPU上训练,在加载模型时,要切换为cpu
model = torch.load("cifar10_99.pth", map_location=torch.device('cpu'))
print(model)
# batch_size = 1(单张图片);通道数为3(RGB);高度宽度为32*32
image = torch.reshape(image, (1, 3, 32, 32))
# 表面为验证模块
model.eval()
# 梯度始终为0,减少不必要的运算消耗资源
with torch.no_grad():
output = model(image)
# 输出预测结果下标
print(output.argmax(1))
结果如下:
预测为dog,结果正确。
2. Github开源项目——pytorch-CycleGAN-and-pix2pix
链接如下:
pytorch-CycleGAN-and-pix2pix
在GitHub上看开源项目的时候,我们要看 README ,看看这个项目具体是干什么的。
从图片上,我们很明显可以看出来GAN就是负责在原来图片基础上进行“创造”
例如:
给出的是一匹普通的马,经过CycleGAN-and-pix2pix后就变成了一批斑马
往下面滑动,README中会叫我们如何安装项目
例如:克隆存储库、下载 CycleGAN 数据集(例如地图)、测试模型等等
所以在github找项目首先看README是很重要的
然后我们点击进入项目中的 train.py 查看具体情况。
以下是train.py的具体内容
其实就和我们训练的套路差不多
先获取数据集
然后导入模型
然后设置epoch(训练轮数),开始训练,然后训练多少次打印结果、训练多少次保存模型,到最后训练多少轮保存我们最新的模型
import time
from options.train_options import TrainOptions
from data import create_dataset
from models import create_model
from util.visualizer import Visualizer
if __name__ == '__main__':
opt = TrainOptions().parse() # 获取训练选项
dataset = create_dataset(opt) # 根据 opt.dataset_mode 和其他选项创建数据集
dataset_size = len(dataset) # 获取数据集中的图像数量。
print('训练图像的数量 = %d' % dataset_size)
model = create_model(opt) # 根据 opt.model 和其他选项创建模型
model.setup(opt) # 常规设置:加载并打印网络;创建调度器
visualizer = Visualizer(opt) # 创建一个可视化工具,用于显示/保存图像和图表
total_iters = 0 # 训练迭代的总次数
for epoch in range(opt.epoch_count, opt.n_epochs + opt.n_epochs_decay + 1): # 每一轮用于不同的周期;我们通过 <epoch_count>, <epoch_count>+<save_latest_freq> 保存模型
epoch_start_time = time.time() # 训练一轮的计时器
iter_data_time = time.time() # 每一轮迭代数据加载的计时器
epoch_iter = 0 # 当前轮数的训练次数,每一轮重置为0
visualizer.reset() # 重置可视化工具:确保它至少每一轮保存结果到HTML一次
model.update_learning_rate() # 在每一轮的开始更新学习率。
for i, data in enumerate(dataset): # 开始一轮中的每一次的内部循环
iter_start_time = time.time() # 每次计算的计时器
if total_iters % opt.print_freq == 0:
t_data = iter_start_time - iter_data_time
total_iters += opt.batch_size
epoch_iter += opt.batch_size
model.set_input(data) # 从数据集解包数据并应用预处理
model.optimize_parameters() # 计算损失函数,获取梯度,更新网络权重
if total_iters % opt.display_freq == 0: # 每训练<opt.display_freq>次在 visdom 上显示图像并将图像保存到 HTML 文件
save_result = total_iters % opt.update_html_freq == 0
model.compute_visuals()
visualizer.display_current_results(model.get_current_visuals(), epoch, save_result)
if total_iters % opt.print_freq == 0: # 每训练<opt.print_freq>次打印训练损失并将日志信息保存到磁盘
losses = model.get_current_losses()
t_comp = (time.time() - iter_start_time) / opt.batch_size
visualizer.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: # 每训练<save_latest_freq> 次迭代保存我们的最新模型
print('saving the latest model (epoch %d, total_iters %d)' % (epoch, total_iters))
save_suffix = 'iter_%d' % total_iters if opt.save_by_iter else 'latest'
model.save_networks(save_suffix)
iter_data_time = time.time()
if epoch % opt.save_epoch_freq == 0: # 每训练<save_epoch_freq> 轮保存我们的模型
print('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))
引入项目的过程中调参是我们最麻烦的一个问题,下面我们就来了解一下如何调参
train.py 有一个TrainOptions()
我们点击进入TrainOptions()就可以查看参数的设置
我们可以多观察后面的注释来了解具体的参数是干什么的
然后在README中,我们可以看到官网给了我么如何训练和测试的方法
就是通过控制台上输入代码测试,但是往往在这个过程的参数调整也是我们的一大困扰,下面就让我们来解读一下如何修改参数
首先我们要找到dataroot这个单词
就在base_options.py (是TrainOptions的父类)
注意事项如图所示:
从上图中我们可以看到,
1、有些属性只有 require 没有 default 的参数;
(这类属性,说明我们必须要赋予其一个值)
2、有些属性只有default 没有 require 参数;
(这类属性,如果我们不赋值,它就使用默认值,即default里面的内容)
一般我们运行项目的时候,先看看这个文件中有没有 require = True 的,有的话就把他们替换为default就直接运行即可。(一般数据集正确或者路径无错误,都可以正常运行)