Pytorch如何优雅地训练模型(一):构建和训练深度学习模型(ResNet)实例

为什么scikit-learn中训练模型就一句model.fit(),而pytorch中训练模型却要写一个for循环,并在循环内完成计算损失、误差反向传播、梯度更新等过程?

从现在开始,你可以将pytorch的训练过程用model.fit()完成。

scient

scient一个用python实现科学计算相关算法的包,包括自然语言、图像、神经网络、优化算法、机器学习、图计算等模块。

scient源码和编译安装包可以在Python package index获取。

The source code and binary installers for the latest released version are available at the [Python package index].

https://pypi.org/project/scient

可以用pip安装scient

You can install scient like this:

pip install scient

也可以用setup.py安装。

Or in the scient directory, execute:

python setup.py install

scient.neuralnet

神经网络相关算法模块,包括attention、transformer、bert、lstm、resnet、crf、dataset、fit等。

scient.neuralnet.fit

神经网络训练模块,将torch构建的神经网络模型的训练方式简化为model.fit(),使torch神经网络模型训练更简捷,更优雅。

使用步骤:

(1)基于torch构建模型model,采用torch.utils.data.DataLoader加载训练数据集train_loader、验证数据集eval_loader(可选);

(2)采用fit.set()设置模型训练参数,参数详情:

  • optimizer=None: 优化器,可以用类似torch.optim模块内的优化器来定义;
  • scheduler=None: 优化器的调度器,可以用类似torch.optim.lr_scheduler模块内的调度器来定义;
  • loss_func=None: 损失函数,可以用类似torch.nn.CrossEntropyLoss()来定义;
  • grad_func=None: 梯度操作函数,可进行如梯度裁剪的操作;
  • perform_func=None: 模型性能函数,模型传入预测值和实际值,用以评估模型性能;
  • n_iter=10: 模型在数据集上迭代训练的次数;
    • 如果n_iter为int,表示模型在数据集上迭代训练n_iter后停止;
    • 如果n_iter为(int,int),表示模型在数据集上迭代训练的最小min_iter和最大max_iter次数, 如果迭代次数超过min_iter且eval的perform_func比上一个iter小,结束训练。n_iter为(int,int)时,必须提供eval_loader,且perform_func必须是一个数值,且值越大模型性能越好;
  • device=None: 模型训练的设备,如device = torch.device(‘cuda’ if torch.cuda.is_available() else ‘cpu’);
  • n_batch_step: 每n个batch更新一次optimizer的梯度,以节省显存及计算量;
  • n_batch_plot: 每n个batch更新一下损失曲线,训练过程中会实时绘制损失曲线;
  • save_path: 每个iter完成后模型保存路径,模型名为“模型类名_iter_i.checkpoint”,保存的内容为{‘model_state_dict’:model.state_dict(),‘optimizer_state_dict’:optimizer.state_dict(),‘batch_loss’:batch_loss},如果训练时未提供eval_loader,batch_loss=train_batch_loss, 否则batch_loss=[train_batch_loss,eval_batch_loss]

(3)采用model.fit(train_loader,eval_loader,mode=(‘input’,‘target’))训练模型:

  • train_loader: 训练数据集
  • eval_loader: 验证数据集
  • mode: 数据集包含的内容,分四种情况:
    • mode=(‘input’,‘target’), loader data item is one input and one target;
    • mode=‘input’, loader data item is only one input;
    • mode=(‘inputs’,‘target’), loader data item is a list of input and one target;
    • mode=‘inputs’, loader data item is a list of input.
    • mode中不包含target时,不能使用perform_func

Examples

首先构建模型model、训练数据加载器train_loader、验证数据加载器eval_loader:

import os
import torch
from scient.neuralnet import resnet, fit
import torchvision.transforms as tt
from torchvision.datasets import ImageFolder

# 数据转换(归一化和数据增强)
stats = ((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
train_tfms = tt.Compose([tt.RandomCrop(160, padding=4, padding_mode='reflect'), 
                         tt.RandomHorizontalFlip(), 
                         tt.ToTensor(), 
                         tt.Normalize(*stats,inplace=True)])
valid_tfms = tt.Compose([tt.Resize([160,160]),tt.ToTensor(), tt.Normalize(*stats)])

# 创建ImageFolder对象
data_train = ImageFolder(os.path.join(os.path.dirname(fit.__file__),'..','test/data/imagewoof/train'), train_tfms)
data_eval = ImageFolder(os.path.join(os.path.dirname(fit.__file__),'..','test/data/imagewoof/val'), valid_tfms)

# 设置批量大小
batch_size = 2

# 创建训练集和验证集的数据加载器
train_loader = torch.utils.data.DataLoader(data_train, batch_size=batch_size, shuffle=True)
eval_loader = torch.utils.data.DataLoader(data_eval, batch_size=batch_size, shuffle=False)

#resnet50模型
model=resnet.ResNet50(n_class=3)

然后设置模型训练参数、训练模型:

#设置训练参数
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001, weight_decay=1e-4)
loss_func=torch.nn.CrossEntropyLoss()
model=fit.set(model,optimizer=optimizer,loss_func=loss_func,n_iter=5,device=device)

#训练
model.fit(train_loader=train_loader,eval_loader=eval_loader,mode=('input','target'))

运行结果:

train iter 0: avg_batch_loss=1.27345: 100%|██████████| 60/60 [00:04<00:00, 12.92it/s]                   
eval iter 0: avg_batch_loss=1.33363: 100%|██████████| 8/8 [00:00<00:00, 59.44it/s]                   
train iter 1: avg_batch_loss=1.24023: 100%|██████████| 60/60 [00:04<00:00, 13.39it/s]                   
eval iter 1: avg_batch_loss=1.08319: 100%|██████████| 8/8 [00:00<00:00, 58.83it/s]                   
train iter 2: batch_loss=1.42699 avg_batch_loss=1.16666:  63%|██████▎   | 38/60 [00:02<00:01, 13.37it/s]

Examples: 训练时不使用eval_loader

#设置训练参数
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001, weight_decay=1e-4)
loss_func=torch.nn.CrossEntropyLoss()
model=fit.set(model,optimizer=optimizer,loss_func=loss_func,n_iter=5,device=device)

#训练
model.fit(train_loader=train_loader,mode=('input','target'))

运行结果:

train iter 0: avg_batch_loss=1.07998: 100%|██████████| 60/60 [00:04<00:00, 12.27it/s]                   
train iter 1: avg_batch_loss=1.16323: 100%|██████████| 60/60 [00:04<00:00, 12.95it/s]                   
train iter 2: batch_loss=0.61398 avg_batch_loss=1.00838:  67%|██████▋   | 40/60 [00:03<00:01, 13.06it/s]

Examples: 使用scheduler在训练过程中改变学习率等optimizer参数

#设置训练参数
n_iter=5
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001, weight_decay=1e-4)
scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr=0.0001, epochs=n_iter,steps_per_epoch=len(train_loader))
loss_func=torch.nn.CrossEntropyLoss()
model=fit.set(model,optimizer=optimizer,loss_func=loss_func,n_iter=n_iter,device=device)

#训练
model.fit(train_loader=train_loader,eval_loader=eval_loader,mode=('input','target'))

Examples: 训练过程中实时显示loss曲线,并在每一个iter完成后保存模型

设置n_batch_plot和save_path,保存的模型以checkpoint为后缀名,可以用torch.load打开保存的模型,模型里保存了3项内容:model_state_dict、optimizer_state_dict、batch_loss

#设置训练参数
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001, weight_decay=1e-4)
loss_func=torch.nn.CrossEntropyLoss()
model=fit.set(model,optimizer=optimizer,loss_func=loss_func,n_iter=5,device=device,n_batch_plot=5,save_path='d:/')

#训练
model.fit(train_loader=train_loader,eval_loader=eval_loader,mode=('input','target'))

#打开并查看保存的模型
checkpoint=torch.load('D:/ResNet_iter_2.checkpoint')
checkpoint.keys()
checkpoint['batch_loss']
checkpoint['model_state_dict']

Examples: 使用n_batch_step在小显存上模拟大batch_size的训练

该功能实现了多次反向误差传播并累积梯度后,再让optimizer进行梯度下降优化。

#设置训练参数
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001, weight_decay=1e-4)
loss_func=torch.nn.CrossEntropyLoss()
model=fit.set(model,optimizer=optimizer,loss_func=loss_func,n_iter=5,device=device,n_batch_step=5)

#训练
model.fit(train_loader=train_loader,eval_loader=eval_loader,mode=('input','target'))

model.fit()的高级操作,如自定义性能评估、最优迭代次数、梯度操作、自定义损失函数等已发布,请查看:Pytorch如何优雅地训练模型(二):自定义性能评估、梯度操作、损失函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值