使用 Keras Plato区块链数据智能进行多 GPU 训练的 5 个技巧。垂直搜索。人工智能。

使用Keras进行多GPU训练的5个技巧

深度学习(2010年代后期最受欢迎的流行语以及区块链/比特币和数据科学/机器学习)使我们能够在过去几年中做一些非常酷的事情。 除了算法的进步(公认的是基于1990年代自称为“数据挖掘时代”的思想)以外,其成功的主要原因还可以归因于大型免费数据集的可用性,开放源代码库的引入以及使用GPU。 在此博客文章中,我将重点介绍最后两个,并与您分享一些我从艰难的道路中学到的技巧。

为什么选择TensorFlow和Keras?

TensorFlow 是Google开发的非常流行的深度学习库,它使您可以快速构建复杂网络的原型。 它具有许多有趣的功能,例如自动求差(使您免于估计/编码成本函数的梯度)和GPU支持(使您可以使用适当的硬件轻松实现200倍的速度提升)。 此外,它提供了Python接口,这意味着您可以快速编写原型,而无需编写C或CUDA代码。 诚然,除了TensorFlow之外,还有很多其他框架可以使用,例如Torch,MXNet,Theano,Caffe,Deeplearning4j,CNTK等,但这都归结为您的用例和您的个人喜好。

但为什么 Keras? 对我而言,直接使用TF就像使用Numpy进行机器学习一样。 是的,这是可行的,您有时需要这样做(特别是如果您编写自定义图层/损失函数),但是您是否真的想编写将复杂网络描述为一系列矢量操作的代码(是的,我知道TF中有更高级的方法,但是它们不像Keras那样酷)? 另外,如果您想移至其他图书馆怎么办? 那么,您可能需要重写代码,这很糟糕。 Ta ta taaa,Keras来营救! Keras允许您使用高级概念来描述网络,并编写与后端无关的代码,这意味着您可以在不同的深度学习库中运行网络。 我对Keras所钟爱的东西很少是它写得好,具有面向对象的体系结构,易于贡献并且具有友好的社区。 如果喜欢,请说谢谢 弗朗索瓦·乔莱特 开发和开放源代码。

多GPU培训的提示和技巧

事不宜迟,让我们跳到一些技巧,了解如何在Keras上充分利用GPU培训以及您应该记住的一些陷阱:

1.多GPU训练不是自动的

使用Keras和Tensorflow在GPU上训练模型是无缝的。 如果您具有NVIDIA卡并且已安装CUDA,则库将自动检测到该卡并将其用于培训。 非常酷! 但是,如果您是被宠坏的孩子,并且拥有多个GPU,该怎么办? 不幸的是,您将需要花点时间才能完成多GPU培训。
使用 Keras Plato区块链数据智能进行多 GPU 训练的 5 个技巧。垂直搜索。人工智能。
有多种方法可以使网络并行化,具体取决于您要实现的目标,但是主要的两种方法是模型并行化和数据并行化。 如果您的模型过于复杂而无法容纳在单个GPU中,则前者可以为您提供帮助;而当您想加快执行速度时,后者可以为您提供帮助。 通常,当人们谈论多GPU培训时,他们指的是后者。 过去很难实现,但值得庆幸的是Keras最近提供了一种称为 多 GPU 模型 这使得并行训练/预测更加容易(当前仅适用于TF后端)。 主要思想是通过该方法传递模型,然后将模型复制到不同的GPU中。 原始输入被分为多个块,这些块被馈送到各个GPU,然后将它们聚合为单个输出。 该方法可用于实现并行训练和预测,但是请记住,由于所需的同步性,该方法并不随GPU的数量线性缩放。

2.注意批次大小

进行多GPU训练时,请注意批次大小,因为批次大小对速度/内存,模型收敛性有多种影响,如果不小心,可能会破坏模型权重!

速度/内存: 显然,批次越大,训练/预测就越快。 这是因为从GPU放入和取出数据会产生开销,因此小批量会有更多开销。 在另一方面,批处理越大,GPU中所需的内存就越多。 尤其是在训练期间,每层的输入都会在反向传播步骤中保留在内存中,因此,过多增加批处理大小可能会导致内存不足错误。

收敛: 如果使用随机梯度体面(SGD)或其某些变体来训练模型,则应记住,批处理大小会影响网络收敛和泛化的能力。 在许多计算机视觉问题中,典型的批处理大小在32-512个示例之间。 如 Keskar等 简而言之,“在实践中已经观察到,使用更大的批次(大于512)时,模型的质量会因模型的泛化能力而降低。” 请注意,其他不同的优化器具有不同的属性,专门的分布式优化技术可以帮助解决该问题。 如果您对数学细节感兴趣,建议阅读Joeri Hermans的论文“关于可扩展深度学习和并行化梯度下降“。
使用 Keras Plato区块链数据智能进行多 GPU 训练的 5 个技巧。垂直搜索。人工智能。
破坏权重: 这是一个令人讨厌的技术细节,可能会造成毁灭性的后果。 进行多GPU训练时,重要的是为所有GPU提供数据。 可能发生的是,该时期的最后一批数据少于定义的数据(因为数据集的大小无法精确地除以该批的大小)。 这可能会导致某些GPU在最后一步不接收任何数据。 不幸的是,某些Keras层(最著名的是批处理归一化层)无法解决导致权重(BN层中的运行均值和方差)中出现nan值的问题。 为了使事情变得更简单,在培训期间(学习阶段为1),人们不会观察到该问题,因为特定层在估计中使用了批次的均值/方差。 然而,在预测期间(学习阶段设置为0),使用了运行均值/方差,在我们的情况下,该均值/方差可能会变小,导致结果不佳。 因此,请帮自己一个忙,在进行多GPU训练时,请务必确保批次大小固定。 实现此目的的两种简单方法是拒绝不符合预定义大小的批处理,或者重复批处理中的记录直到达到预定义大小。 最后但并非最不重要的一点是,请记住,在多GPU设置中,批处理大小应为系统上可用GPU数量的倍数。

3. GPU数据匮乏,即CPU跟不上GPU

通常,训练/预测深度网络时最昂贵的部分是在GPU上进行的估计。 数据在后台的CPU中进行预处理,并定期送入GPU。 然而,不应低估GPU的速度。 如果您的网络太浅或预处理步骤太复杂,以致您的CPU无法跟上GPU的速度,或者换句话说,它们无法足够快地向其提供数据,则可能会发生这种情况。 这可能导致GPU使用率降低,从而浪费金钱/资源。
使用 Keras Plato区块链数据智能进行多 GPU 训练的 5 个技巧。垂直搜索。人工智能。
但是,由于Python的GIL(全局解释器锁),Keras通常并行执行批处理的估计,因此您无法真正在Python中实现真正的多线程。 有两种解决方案:要么使用多个流程(请注意,在此不涉及很多陷阱),或者使您的预处理步骤保持简单。 过去,我在Keras上发送了Pull-Request来减轻我们在图像预处理过程中对CPU造成的不必要负担,因此,如果大多数用户使用标准生成器,则不会受到影响。 如果您有自定义生成器,请尝试将尽可能多的逻辑推入C库(例如Numpy),因为实际上其中一些方法 释放GIL 这意味着您可以提高并行度。 检测您是否面临GPU数据匮乏的一种好方法是监视GPU利用率,但是请注意,这并不是观察到的唯一原因(在跨多个GPU训练期间发生的同步也应归咎于利用率低下) )。 通常,可以通过观察GPU突发然后长时间停顿而没有利用来检测GPU数据不足。 过去,我公开了Dstat的扩展程序,该扩展程序可以帮助您衡量GPU的利用率,因此请查看 原创博客文章.

4.保存并行模型

假设您使用mutli_gpu_model方法来并行化模型,训练结束了,现在您要保持其权重。 坏消息是您不能只对它调用save()。 目前Keras有一个限制,不允许您 保存并行模型。 有两种解决方法:要么在原始模型的引用上调用save()(权重将自动更新),要么需要通过减少并行化版本并清理所有不必要的连接来序列化模型。 第一种方法很容易,但是将来我计划开源执行该方法的serialize()方法。

5.计数可用的GPU有讨厌的副作用

不幸的是,目前,在tensorflow.python.client.device_lib.list_local_devices()方法上存在一个令人讨厌的副作用,这会导致创建新的TensorFlow会话并初始化系统上所有可用的GPU。 这可能会导致意外结果,例如查看比指定数量更多的GPU或过早初始化新会话(您可以阅读此内容的所有详细信息 拉取请求)。 为避免类似的意外,建议您改用Keras的K.get_session()。list_devices()方法,该方法将在会话中返回所有当前已注册的GPU。 最后但并非最不重要的一点是,请记住,调用list_devices()方法在某种程度上是昂贵的,因此,如果您仅对可用GPU的数量感兴趣,请一次调用该方法并将其数量存储在局部变量中。

而已! 希望您发现此列表有用。 如果您发现在Keras上进行GPU培训的其他陷阱/技巧,请在下面的评论中分享。 🙂

时间戳记:

更多来自 基准框