仅用于站内搜索,没有排版格式,具体信息请跳转上方微信公众号内链接
点击上方“小白学视觉”,选择加”星标”或“置顶”
重磅干货,第一时间送达
掌握这17种方法,用最省力的方式,加速你的Pytorch深度学习训练。
近日,Reddit上一个帖子热度爆表。主题内容是关于怎样加速PyTorch训练。原文作者是来自苏黎世联邦理工学院的计算机科学硕士生LORENZKUHN,文章向我们介绍了在使用PyTorch训练深度模型时最省力、最有效的17种方法。
该文所提方法,都是假设你在GPU环境下训练模型。具体内容如下。
17种加速PyTorch训练的方法
1.考虑换一种学习率schedule
Sylvain写到:1Cycle包括两个等长的步幅,一个步幅是从较低的学习率到较高的学习率,另一个是回到最低水平。最大值来自学习率查找器选取的值,较小的值可以低十倍。然后,这个周期的长度应该略小于总的epochs数,并且,在训练的最后阶段,我们应该允许学习率比最小值小几个数量级。
与传统的学习率schedule相比,在最好的情况下,该schedule实现了巨大的加速(Smith称之为超级收敛)。例如,使用1Cycle策略在ImageNet数据集上训练ResNet-56,训练迭代次数减少为原来的1/10,但模型性能仍能比肩原论文中的水平。在常见的体系架构和优化器中,这种schedule似乎表现得很好。
Pytorch已经实现了这两种方法:「torch.optim.lr_scheduler.CyclicLR」和「torch.optim.lr_scheduler.OneCycleLR」。
参考文档:https ://pytorch.org/docs/stable/optim.html
2.在DataLoader中使用多个worker和页锁定内存
当使用torch.utils.data.DataLoader时,设置num_workers>0,而不是默认值0,同时设置pin_memory=True,而不是默认值False。
参考文档:https ://pytorch.org/docs/stable/data.html
来自NVIDIA的高级CUDA深度学习算法软件工程师SzymonMicacz就曾使用四个worker和页锁定内存(pinnedmemory)在单个epoch中实现了2倍的加速。人们选择worker数量的经验法则是将其设置为可用GPU数量的四倍,大于或小于这个数都会降低训练速度。请注意,增加num_workers将增加CPU内存消耗。
3.把batch调到最大
把batch调到最大是一个颇有争议的观点。一般来说,如果在GPU内存允许的范围内将batch调到最大,你的训练速度会更快。但是,你也必须调整其他超参数,比如学习率。一个比较好用的经验是,batch大小加倍时,学习率也要加倍。
然而,使用大batch的不足是,这可能导致解决方案的泛化能力比使用小batch的差。
4.使用自动混合精度(AMP)
PyTorch1.6版本包括对PyTorch的自动混合精度训练的本地实现。这里想说的是,与单精度(FP32)相比,某些运算在半精度(FP16)下运行更快,而不会损失准确率。AMP会自动决定应该以哪种精度执行哪种运算。这样既可以加快训练速度,又可以减少内存占用。
在最好的情况下,AMP的使用情况如下:
5.考虑使用另一种优化器
AdamW是由fast.ai推广的一种具有权重衰减(而不是L2正则化)的Adam,在PyTorch中以torch.optim.AdamW实现。AdamW似乎在误差和训练时间上都一直优于Adam。
Adam和AdamW都能与上面提到的1Cycle策略很好地搭配。
目前,还有一些非本地优化器也引起了很大的关注,最突出的是LARS和LAMB。NVIDA的APEX实现了一些常见优化器的融合版本,比如Adam。与PyTorch中的Adam实现相比,这种实现避免了与GPU内存之间的多次传递,速度提高了5%。
6.cudNN基准
如果你的模型架构保持不变、输入大小保持不变,设置torch.backends.cudnn.benchmark=True。
7.小心CPU和GPU之间频繁的数据传输
如果你创建了一个新的张量,可以使用关键字参数device=torch.device(‘cuda:0’)将其分配给GPU。
如果你需要传输数据,可以使用.to(non_blocking=True),只要在传输之后没有同步点。
8.使用梯度/激活checkpointing
Checkpointing的工作原理是用计算换内存,并不存储整个计算图的所有中间激活用于backwardpass,而是重新计算这些激活。我们可以将其应用于模型的任何部分。
因此,虽然这可能会略微增加给定batch大小的运行时间,但会显著减少内存占用。这反过来又将允许进一步增加所使用的batch大小,从而提高GPU的利用率。
PriyaGoyal教程地址:
9.使用梯度积累
增加batch大小的另一种方法是在调用optimizer.step()之前在多个.backward()传递中累积梯度。
这个方法主要是为了规避GPU内存的限制而开发的。
10.使用分布式数据并行进行多GPU训练
分布式训练文档地址:https ://pytorch.org/tutorials/beginner/dist_overview.html
11.设置梯度为None而不是0
梯度设置为.zero_grad(set_to_none=True)而不是.zero_grad()。这样做可以让内存分配器处理梯度,而不是将它们设置为0。正如文档中所说,将梯度设置为None会产生适度的加速,但不要期待奇迹出现。注意,这样做也有缺点,详细信息请查看文档。
文档地址:https ://pytorch.org/docs/stable/optim.html
12.使用.as_tensor()而不是.tensor()
torch.tensor()总是会复制数据。如果你要转换一个numpy数组,使用torch.as_tensor()或torch.from_numpy()来避免复制数据。
13.必要时打开调试工具
14.使用梯度裁剪
关于避免RNN中的梯度爆炸的问题,已经有一些实验和理论证实,梯度裁剪(gradient=min(gradient,threshold))可以加速收敛。HuggingFace的Transformer实现就是一个非常清晰的例子,说明了如何使用梯度裁剪。本文中提到的其他一些方法,如AMP也可以用。
在PyTorch中可以使用torch.nn.utils.clip_grad_norm_来实现。
15.在BatchNorm之前关闭bias
在开始BatchNormalization层之前关闭bias层。对于一个2-D卷积层,可以将bias关键字设置为False:torch.nn.Conv2d(…,bias=False,…)。
16.在验证期间关闭梯度计算
在验证期间关闭梯度计算,设置:torch.no_grad()。
17.使用输入和batch归一化
要再三检查一下输入是否归一化?是否使用了batch归一化?
原文链接:https ://efficientdl.com/faster-deep-learning-in-pytorch-a-guide/
本文仅做学术分享,如有侵权,请联系删文。
下载1:OpenCV-Contrib扩展模块中文版教程
在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。
下载2:Python视觉实战项目52讲
在「小白学视觉」公众号后台回复:Python视觉实战项目,即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。
下载3:OpenCV实战项目20讲
在「小白学视觉」公众号后台回复:OpenCV实战项目20讲,即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。
交流群
欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三+上海交大+视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~