Pytorch-Lightning中的训练器–Trainer

目录

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 等功能。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2023年12月13日
下一篇 2023年12月13日

相关推荐