Pytorch-Lightning中的训练器—Trainer

Trainer()

常用参数 由于文件过大,为了加速训练时间,先训练模型,然后再说其他的理由与打算。

训练器Trainer

自动获取Batch size-Automatic Batch Size Finder

auto_scale_batch_size

Batch size一般会对模型的训练结果有影响i,一般越大的batch size模型训练的结果会越好,有时候,我们不知道自己的模型在当前机器上最多能用多大的batch size,,这时候通过Lightning Trainer的这个flag就可以帮助我们找到最大的batch size。

model = ...

# 设置为True,Trainer就会依次尝试用2的幂次方的batch size,直到超出内存

trainer = pl.Trainer(auto_scale_batch_size=True)

trainer.fit(model)

# 设置为'binsearch',Trainer会用Binary Search的方式帮你找到最大的Batch Size

trainer = pl.Trainer(auto_scale_batch_size='binsearch')

trainer.tune(model)

# 注意:如果要用这个功能,在Module里面的__init__()函数中要有:

self.batch_size = batch_size

# 或者在__init__()里面调用:

self.save_hyperparameters()

自动获取初始学习率—Automatic Learning Rate Finder

auto_lr_find

学习率learning rate是很重要的一个超参,选取一个合适的初始学习率也是很重要的,Lightning提供了这个有用的flag。 20)目前只支持单优化器(Optimizer),预计在未来的几个月内会支持多优化器

import pytorch_lightning as pl

model = ...

# 可以直接设置为True,Trainer会自动用不同的学习率运行model,然后画出loss和学习率的曲线,帮你找到最合适的学习率

trainer = pl.Trainer(auto_lr_find=True)

trainer.tune(model)

print(model.learning_rate)

# 有时候我们会在model中给学习率起其他的名字,比如:

self.my_learning_rate = lr

# 这个时候我们可以用变量名直接设置auto_lr_find:

trainer = pl.Trainer(auto_lr_find='my_learing_rate')

# 开始寻找合适的学习率

lr_finder = trainer.tuner.lr_find(model)

# 展示loss和学习率的曲线

fig = lr_finder.plot(suggest=True)

fig.show()

# 设置为推荐的学习率

model.hyparams.learning_rate = lr_finder.suggestion()

# 开始训练

model.fit(model, train_loader, val_loader)

重新加载数据:Reload DataLoaders Every Epoch

reload_dataloaders_every_epoch

一般数据只会在一开始加载一次**,即在epochs循环前面加载一次**,然后每个循环都会shuffle之类的(如果你设置shuffle为True的话)。有时候我们的数据在训练过程中是会改变的,这个时候我们就需要在每个epoch都要再加载一次数据,Lightning就提供了这样一个flag,将其设置为True即可

# 相当于:

# if False (default)

train_loader = model.train_dataloader()

for epoch in epochs:

for batch in train_loader:

...

# if True

for epoch in epochs:

train_loader = model.train_dataloader()

for batch in train_loader:

回调函数: Callbacks

callbacks

回调函数 (Callbacks) 在机器学习中也是很重要的工具,一般可以用来进行模型的断点断续,模型权重的存储,提早停止 (Early stop),动态调整训练参数以及tensorboard之类的训练可视化等等**。Lightning也支持非常灵活的Callbacks**,只需要把Callbacks放进flag:callbacks中即可。Lightning提供了一些built-in的callbacks,同样也支持自定义callbacks类,所以非常灵活

# 自定义Callback类

from pytorch_lightning.callbacks import Callback

class MyPrintingCallback(Callback):

def on_init_start(self, trainer):

print('Starting to init trainer!')

def on_init_end(self, trainer):

print('trainer is init now')

def on_train_end(self, trainer, pl_module):

print('do something when training ends')

trainer = Trainer(callbacks=[MyPrintingCallback()])

# 使用built-in的Callbacks

from pytorch_lightning.callbacks import EarlyStopping

# 可以直接使用默认的Callbacks

trainer = pl.Trainer(callbacks=[EarlyStopping('val_loss')])

# 也可以自己设置Callbacks的参数

early_stop = EarlyStopping(

monitor='val_loss',

patience=3,

strict=False,

verbose=False,

mode='min'

)

trainer = pl.Trainer(callbacks=[early_stop])

展示网络信息——Weights Summary

weights_summary

一般我们搭完模型都会去检查模型结构,计算模型的大小以及占用内存,之前需要安装一个额外的torchsummary的包可以用来输出pytorch模型的信息,Lightning则直接集成了这个功能,它提供三个参数:‘top’,'full’和None。

# (默认) 只展示顶层的模块

trainer = pl.Trainer(weights_summary='top')

# 展示所有的模块,包括子模块

trainer = pl.Trainer(weights_summary='full')

# 不打印模型信息

trainer = pl.Trainer(weights_summary=None)

进度条—Progress Bar

progress_bar_refresh_rate

进度条 (Progress Bar) 是非常有用的工具,在python中我们一般使用第三方包tqdm来创建进度条**,Lightning则集成了进度条,对应的值为steps,即每隔多少steps更新一次进度条,设置为0即不使用进度条**。

# 默认每个step更新一次

trainer = Trainer(progress_bar_refresh_rate=1)

# 关闭进度条

trainer = Trainer(progress_bar_refresh_rate=0)

训练以及测试循环 - Training and Eval Loops

min_epochs, max_epochs, min_steps和max_steps

训练的时候我们需要指定Epoch的数量,Lightning提供了相应的flags。 对min_steps和max_steps而言,中间validation的steps不计入其中。 如果同时指定max_epochs和max_steps,则max_steps优先。

trainer = Trainer(min_steps=100, max_steps=10000)

trainer = Trainer(min_epochs=10, max_epochs=100)

`

check_val_every_n_epochs

训练过程中一般我们也会做测试 (validation) 来看模型的泛化能力以及是否过拟合。Lightning提供了对应的flag,默认为1,即每个epoch结束都会做一次validation。有时候一个training epoch只需要几分钟,这时候没有必要每个epoch结束都去做一次validation,我们可以设置为10或者任意其他的整数。

# 每5个epochs做一次validation

trainer = Trainer(check_val_every_n_epochs=5)

val_check_interval

对于某些大模型或者大数据集的训练,一个epoch可能会持续几个小时甚至几天,我们当然不能过这么久才做一次validation,这时候我们要用到这个新flag,它支持0到1的浮点数以及整数。比如0.25表示每隔四分之一的epoch做一次validation,1000表示每隔1000个steps做一次validation。

# 每隔四分之一个epoch做一次validation

trainer = Trainer(val_check_interval=0.25)

# 每隔1000个steps做一次validation

trainer = Trainer(val_check_interval=1000)

num_sanity_val_steps

一般validation都会在training之后做,如果validation的代码中存在bugs,而training一个epoch可能持续很久,这时候会浪费大量的时间。Lightning提供一个flag来解决这个问题,它会在正式training开始前先做若干个batches的validation,如果没有问题才会正式训练**。它支持-1, 0以及正整数,-1表示做完整个validation,0表示不做**。

# (默认) 正式训练前先做2个batches的validation

trainer = Trainer(num_sanity_val_steps=2)

# 做完一整个validation epoch才开始训练

trainer = Trainer(num_sanity_val_steps=-1)

# 直接开始训练

trainer = Trainer(num_sanity_val_steps=0)

limit_train_batches, limit_val_batches和limit_test_batches

有时候我们为了检查代码或者做测试必须跑完一整个或者更多的epochs,如果一个epoch的时间过长则会浪费时间,Lightning提供了解决方案,它们支持0到1的浮点数和整数,比如0.1代表每个epoch只跑十分之一的数据,10代表每个epoch只跑10个batches:

# 每个训练epoch只跑十分之一的数据

trainer = Trainer(limit_train_batches=0.1)

# 每个测试epoch只跑10个batches

trainer = Trainer(limit_val_batches=10)

单GPU以及多GPUs训练 - Training on GPUs

以前GPU基本用在游戏上,而现在被广泛应用在深度学习领域,因为GPU能高效地做矩阵运算,运算速度比CPU快进几百倍。而随着网络趋于复杂,计算量越来越大,一台GPU根本不够用,这时候就要多GPUs共同训练,Pytorch本身也支持多节点多GPUs训练,比如之前的DataParallel和DistributedDataParallel,但是开发人员需要自行修改很多代码,对刚刚接触分布式训练的开发人员不太友好,而Lightning则大大简化了这个过程,我们只需去掉代码中的.cuda()和.to(device),初始化Tensor的时候使用type_as和register_buffer**,然后在为Trainer添加对应的fla**g:gpus。

# 使用Lightning之前:

def forward(self, x):

z = torch.Tensor(2, 3)

z = z.cuda(0)

# 使用Lightning之后:

def forward(self, x):

z = torch.Tensor(2, 3)

z = z.type_as(x, device=self.device)

###########################################

# 使用一个GPU

trainer = pl.Trainer(gpus=1)

# 使用8个GPU

trainer = pl.Trainer(gpus=4)

# 使用所有可用的GPU

trainer = pl.Trainer(gpus=-1)

# 指定使用哪几个GPU

trainer = pl.Trainer(gpus=[0,3,4])

auto_select_gpus

有时候,我们不知道那些GPU是被占用的,也就没办法指定GPU,Lightning为此提供了flag,它可以替我们检测可以使用的GPU个数以及序号。

# 不自动选择GPU (直接选择系统中的前两个GPU, 如果它们被占用则会失败)

trainer = Trainer(gpus=2, auto_select_gpus=False)

# 自动从系统中选择两个可用的GPU

trainer = Trainer(gpus=2, auto_select_gpus=True)

# 指定所有的GPU,不管它们是否被占用

Trainer(gpus=-1, auto_select_gpus=False)

# 指定所有可用的GPU (如果只有一个GPU可用,则只会使用一个GPU)

Trainer(gpus=-1, auto_select_gpus=True)

log_gpu_memory

如果我们想要监测GPU内存的使用状况,Lightning也提供了相应的flag。使用的话可能会使训练变慢,因为它使用的是nvidia-smi的输出。

# 默认不监测GPU内存

trainer = Trainer(log_gpu_memory=None)

# 监测主节点上的所有GPU

trainer = Trainer(log_gpu_memory='all')

# 只记录主节点上的最小以及最大GPU内存使用

trainer = Trainer(log_gpu_memory='min_max')

benchmark

如果你模型的输入大小保持不变,那么可以设置cudnn.benchmark为True,这样可以加速训练,如果输入大小不固定,那么反而会减慢训练

`

ModelCheckpoint

pytorch-lightning 中保存断点用的是回调函数 ModelCheckpoint,并且必须是在验证循环结束后才会保存。这样的方式不适合于一些特殊任务,例如 Transformer 结构下的语音识别模型一般都需要 average 最后10-20 个 epoch 的模型权重。而且对于自回归模型来说进行一次真正的(即不提供真实标签)验证需要的时间较长,实际上整个训练过程中可能并没有验证过程。

SaveCheckpoint

重写 ModelCheckpoint,实现每个训练 epoch 结束都保存 checkpoint

class SaveCheckpoint(ModelCheckpoint):

"""save checkpoint after each training epoch without validation.

if ``last_k == -1``, all models are saved. and no monitor needed in this condition.

otherwise, please log ``global_step`` in the training_step. e.g. self.log('global_step', self.global_step)

:param last_k: the latest k models will be saved.

:param save_weights_only: if ``True``, only the model's weights will be saved,

else the full model is saved.

"""

def __init__(self, last_k=5, save_weights_only=False):

if last_k == -1:

super().__init__(save_top_k=-1, save_last=False, save_weights_only=save_weights_only)

else:

super().__init__(monitor='global_step', mode='max', save_top_k=last_k,

save_last=False, save_weights_only=save_weights_only)

def on_train_epoch_end(self, trainer, pl_module, outputs):

"""

save checkpoint after each train epoch

"""

self.save_checkpoint(trainer, pl_module)

def on_validation_end(self, trainer, pl_module):

"""

overwrite the methods in ModelCheckpoint to avoid save checkpoint on the end of the val loop

"""

pass

总结

慢慢的总结,会迅速的将其全部都搞定 慢慢的将各种的transformer库都给其研究彻底。将其研究搞定。

理论

pytorch-lightning 是建立在pytorch之上的高层次模型接口

pytorch-lightning 之于 pytorch,就如同keras之于 tensorflow。

通过使用 pytorch-lightning,用户无需编写自定义训练循环,就可以非常纯洁的在CPU、单GPU、多GPU,乃至多TPU上训练模型。

无需考虑模型和数据在cpu,cuda之间的移动,并且可以通过回调函数实现CheckPoint参数保存,实现断点续训功能。

设计哲学

pytorch-lightning 的核心设计哲学是将 深度学习项目中的 研究代码(定义模型) 和 工程代码 (训练模型) 相互分离

用户只需专注于研究代码(pl.LightningModule)的实现,而工程代码借助训练工具类(pl.Trainer)统一实现。

更详细的说,深度学习项目代码可以分为如下四个部分:

研究代码: 用户继承LightningModule实现

工程代码:用户无需关注通过调用Trainer实现

非必要代码 (Non-essential research code,logging, etc…),用户通过调用Callbacks实现

数据 (Data),用户通过torch.utils.data.DataLoader实现

可以通过callbacks非常方便地添加CheckPoint参数保存、early_stopping 等功能。

好文阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: