Pytorch 您所在的位置:网站首页 checkpoint插件 Pytorch

Pytorch

2023-06-21 20:53| 来源: 网络整理| 查看: 265

在深度学习实践中,如何构建一个系统往往需要阅读大量的开源项目、自己总结经验。这里根据我的习惯,总结了常用框架和工具链的使用逻辑。也可搜索Havard CS197系统学习。

pytorch-lightning

基本逻辑被LightningModule(简称LM)封装net,里边forward方法负责inference,在此基础上定义training_step 利用forward的输出logits计算loss,以及valid_step等等hook去控制。剩下一切项目配置都在Trainer中指定。

Trainer中可以指定参数,还可以引入callbacks和plugin。前者例如ckpt,后者例如amp和ddp strategy。logger是单独的一个参数,也可以继承后传入。

1. 关于log:

普通的tensorboard SummaryWriter可以add_text 添加文本信息,还可以传入数值信息化成曲线。但是PL封装的没有add_text接口,记录文字很不方便,所以可以全局维护一个loguru的日志去单独记录文字(或者封装两个logger 成为一个大的logger)这也是为什么深度学习系统一般是两个logger。

使用方法:

        1. pl_loggers.TensorBoardLogger() 作为参数传进Trainer,成为LM成员

        2. LM中使用self.log / self.log_dict 即可访问到它,向日志写入内容(key-alue形式,Value

来自于train step输出的东西)图片等需要不同的方法

        3. log记录的东西也能被其他组件捕捉到,例如ModelCheckpoint的filename,可以自定义格式化参数,你log的loss可以作为文件名

        4. metrics:self.log能够智慧的累加取平均。如果想定义更复杂的算子,使用torch.Metrics,它也能自动累加、平均,而且比self.log还支持了ddp自动reduce

        5. 其他:

                如何用epoch而非step做x-axis链接,重写log ‘step’变量即可

                想看lr使用 callbacks = LearnRateMonitor,它添加所有的optimizer的lr曲线

        6. Trying to infer the `batch_size` from an ambiguous collection. The batch size we found is To avoid any miscalculations, use self.log(...,batch_size=batch_size)`[issue] 。这个warning说的是log可以自动累加计算metric,但是batch_size不明确的话“平均”操作会意义不统一,要求在log时显式的声明batch size

2. 关于checkpoint(文档)

内置的ModelCheckpoint是包办lr, opt, stateful datamodule和 stateful callbacks的(什么是stateful)。根据官方文档,想继续训练只需创建一个model,其他都不用创建。不过这听起来不大科学,据我实验,至少在1.8 之前的版本,datamodule和callbacks都需要手动传入,不过它们的state可以保存,比如“ModelCheckpoint的保存目录”这个state,继续训练后还是会保持之前的,而不是新建文件夹。

model = LitModel() trainer = Trainer() # automatically restores model, epoch, step, LR schedulers, apex, etc... trainer.fit(model, ckpt_path="some/path/to/my_checkpoint.ckpt")

想只load模型inference:

model = MyLightningModule.load_from_checkpoint

save_hyperparameters是LM init时候传入的超参。可以把配置参数也存入ckpt,省的每次去修改config文件了,直接跑就行.

但是,如果hyperparameters有被写进ignore列表,就不会记录进ckpt,那么load_from_checkpoint这个方法就用不了了,会报错缺少初始化参数。解决办法是还用torch的老办法,写入state_dict。(其中torch.load的是字典,load_state_dict是把字典加载到模型权重里)

checkpoint = torch.load(checkpoint_path) checkpoint.keys() >>> dict_keys(['epoch', 'global_step', 'pytorch-lightning_version', 'state_dict', 'callbacks', 'optimizer_states', 'lr_schedulers', 'native_amp_scaling_state', 'hparams_name', 'hyper_parameters', 'hparams_type']) #传统的torch存储的pth的内容 >>> dict_keys(['meta', 'state_dict', 'lr_scheduler', 'optimizer', 'amp']) cfg = OmegaConf.to_object(checkpoint['hyper_parameters']) cfg = DictConfig(cfg) model = build_model(cfg) model.load_state_dict(checkpoint['state_dict'])

综上,比较好的实践是:LM只传入cfg,完全保存 hyperparameters,构建backbone和loss、metrics等操作放在LM内部。

参数重载

参数的应用场景有两个:要么构建模型时传入,要么发给trainner,前者作为hyperparmeters保存,用load_from_checkpoint重载,后者用Trainer()里边的字典重载

eg,如果你训了10个epoch,又想再来5个,但是之前参数传入的是10,这样一开始训练就会stop了。那怎么重载呢?可以只设定 Trainer(max_epoches=15)。参考issue:

https://github.com/Lightning-AI/lightning/issues/2823

部分参数重载

如果我只想重载weights,lr,optmizer等等使用新的重新训练可以吗?有没有可选择的重载方式?2023.1.8日为止,没有。github上该issue还是open状态,等待新的feature引入吧!现在的办法有2种:

        1. 在load_from_checkpoint之前修改ckpt。如果想改存ckpt的文件夹,可以修改ModelCheckpoint的状态。但是把lr和opti的state dict删除掉可能会导致error。这种等同于只load weights作为初始化参数了。

        2. issue的第三个回答,使用configure_optimizer函数,在一定epoch开始之后reset opti和lrscheduler

https://github.com/Lightning-AI/lightning/issues/5339

存储规则:

ModelCheckpoint这个;类在初始化时候有个‘monitor’可以监控self.log下来的参数。比如你记录的accu,可设它是accu,就会根据这个保存topk。如果只是想傻瓜的每轮都保存,使用参数:

save_top_k = -1 every_n_train_steps = cfg.CHECKPOINT_INTERVAL, 3. 关于optimizer:

train step:可以renturn 一个scalar,也可以是带‘loss’的key的字典

optimizer:在LM 里用configure** 定义,

manual optimize可以控制如强化学习等高度自由的优化过程

配套的lr scheduler也可以在里边调整,返回一个字典

return [optimizer], [{'scheduler': scheduler, 'interval': 'epoch'}] # interval step or epoch

容易犯的bug:如果interval写成了 ‘step’,是每个batch都会更新lr,lr快速逼近0!

4. 关于AMP:文档

 Pytorch半精度网络训练需要注意哪些问题? | w3c笔记

有2个backend,PL推荐native后端。amp_level是专门给apex后端设的。1.10建议用plugin而不是参数配置了。注意有的操作必须在32bit下完成!

warn

Do not cast anything to other dtypes manually using torch.autocast or tensor.half() when using native precision because this can bring instability.

【BUG】现在amp会有过度调整lr的bug,此bug源于torch内部,和PL无关!

        这个bug会产生warning:

UserWarning: Detected call of `lr_scheduler.step()` before `optimizer.step()`. In PyTorch 1.1.0 and later, you should call them in the opposite order: `optimizer.step()` before `lr_scheduler.step()`. Failure to do this will result in PyTorch skipping the first value of the learning rate schedule. See more details at https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate

它是在开始几个epoch调用lr_scheduler.step() when the scaler skips optimizer.step()带来的。可以看下列issue

Mixed precision: scheduler and optimizer are called in the wrong order · Issue #5558 · Lightning-AI/lightning · GitHub

Fix LR scheduler getting called excessively with amp by akihironitta · Pull Request #11542 · Lightning-AI/lightning · GitHub

5. 关于config:

hydra层次化读取,omegaconf解析引用(yaml里边的value可以引用其他的key,hydra读出来都是str,需要这个包解析(Omegaconf.resolve))

注意,yaml中defaults list是从上往下重载的,有同名的取最后一个的值

Installation — OmegaConf 2.1.3.dev0 documentation

Tutorial: Learning Hydra for configuring ML experiments - Simone Scardapane

6. 关于wandb、tensorboard和可视化:

6.1 tensorboard:它的曲线经过smooth,所以有时候要看value,而不是smooth,这才是真实的log值,后者是tb插值得到的!

在服务器上docker内部需要加  --bind_all

6.2 wandb:

7. 关于DDP:

lightning 在validation阶段是不会自动聚合不同gpu上的loss的,所以你需要手动all gather一下,具体做法在这里。不过,torchmetrics包(用法在这里)支持了自动all gather,此时不用手动操作了。顺便,lr是和optimizer绑定的,lr调度时候的“monitor”依据的指标就是这里同步下来的才行?

syncbatchnorm:  多gpu时如果单卡的batchsize太小,统计的方差也会不准,所以把多卡算出来的方差放一起。torch.nn.SyncBatchNorm.convert_sync_batchnorm 可以把所有的模块统一转换,不过PL中只需Trainer的参数设一下就好了。这里主要是训练时的动作,推理时不需要。

其他trick

2. torch.cuda.synchronize():应对异步情况,比如 tensor.to(non_blocking=True)送数据,用它同步

3. 类似的深度好文   pytorch_lightning 全程笔记 - 知乎

4. 可以通过 len(tensor.shape) 判断



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有