其他

想独立开展深度学习研究,你准备好了吗?

2017-12-05 Be humble AI前线
作者 | VICKI CHEUNG, JONAS SCHNEIDER, ILYA SUTSKEVER & GREG BROCKMAN
译者 | 王妙琼
AI 前线导读:OpenAI 的工程师们将在这篇文章中和大家分享他们开展深度学习研究的经验及案例,并会详细介绍选用的研发基础架构以及开源技术 kubernetes-ec2-autoscaler。如果你的团队正准备开启自己的深度学习之旅,不妨从这篇文章开始。

更多干货内容请关注微信公众号“AI 前线”(ID:ai-front)

深度学习是一门经验科学,具备优质的研发基础架构通常能令科研团队事半功倍。幸运的是,依托现有的开源生态,任何人都能构建出非常不错的深度学习基础架构。

在这篇文章中,我们会和大家分享如何开展深度学习的研究,也会一并介绍我们在研究中选用的基础架构和开源技术 kubernetes-ec2-autoscaler,这是一种用于 Kubernetes 批处理任务的弹性伸缩管理器(batch-optimized scaling manager)。

用例

深度学习的演进通常源于一个能够在小问题上被验证的构想。在这个阶段,你需要快速地进行大量随机实验。理想情况下,只需远程登录到一台机器,运行一个脚本,不到一个小时就可以得到结果。

但是构建一个真正可用的模型通常会经历很多次失败,需要我们不停地去修复这些缺陷。(这和其他新建的软件系统一样,你需要多次运行代码才能判断它是如何运转的。)

你需要通过多个角度的计算来检测模型,从而意识到它是如何学习的。Dario Amodei 的这种增强学习机制(控制右侧的球拍)可以在击球游戏中获得很高的分数,但你会发现,游戏中右侧的球拍完全没有移动。

因此深度学习的基础架构要能允许用户灵活地反观模型,仅仅展示一些统计结果是不够的。

当模型表现出一定的应用前景,你会希望将它扩展到更大的数据集和更多的 GPU 上运行,但这会花费大量的时间。而且你需要认真地管理实验并非常谨慎地去选择超参数(hyperparameters)的范围。

这种科研的过程在早期是快速且缺乏系统性的;到了后期,过程会逐渐有条理却很耗费精力,但为了获得完美的结果,这是必不可少的。

案例

论文 Improved Techniques for Training GANs 开篇讲述了 Tim Salimans 对于如何改进生成对抗网络(GAN)训练机制的一些看法。我们会挑其中较简单的一个进行介绍(这虽然不是最好的半监督学习案例,但它生成了最好看的样本)。

GANs 由一个生成器网络和一个鉴别器网络构成。生成器会不停地去干扰鉴别器,而鉴别器会尽力地将生成器造出的数据和真实数据区分开来。通常来说,判断生成器的好坏,看它能不能骗过所有鉴别器就行了,但难题仍然存在:如果生成器一直输出完全相同的(几乎和真实的一样)样本会造成网络的崩溃。

Tim 提出可以用小批次的样本数据代替原先的一整个样本提供给鉴别器。这样鉴别器就可以判断生成器是否一直在传同样的图像。当“崩溃”发生时,生成器将会进行梯度调整来修正这个问题。

下一步就是基于 MNIST 和 CIFAR-10 将构想转化为原型。这需要快速地构建出一个初步的模型,然后运行真实的数据并检测结果。在经过几次快速的迭代之后,Tim 得到了 CIFAR-10 的样本,这次的结果十分振奋人心,几乎是我们见过的在这个数据集上跑出的最好样本了。

深度学习(以及常说的 AI 算法)如果要真正形成一定影响就必须扩大实验规模,一个小型神经网络可以验证概念,而大型的神经网络才能真正解决问题。因此 Ian Goodfellow 开始把模型扩展到 ImageNet 进行验证。

模型学习生成 ImageNet 的图像

有了更大的模型和数据集,Ian 就需要用更多的 GPU 来并行地运行模型。任务运行时机器的 CPU 和 GPU 利用率会飙升至 90%,但是即使这样仍需要花费很多天才能完成模型训练。在这种模式下,每一次实验机会都显得无比珍贵,他也会非常细致地记录下每次实验的结果。

虽然实验最终得到了不错的结果,但仍没有达到我们的预期。为了找到原因我们做了很多尝试,但仍然攻克不了。这大概就是科学的本质吧。

基础架构
40 28998 40 11787 0 0 7462 0 0:00:03 0:00:01 0:00:02 7460n> 软件

TensorFlow 代码的样例

我们绝大部分的研究代码是用 Python 完成的,详细内容可以在我们的开源项目中查看到。我们通常使用 TensorFlow(在特殊情况下也会使用 Theano)来进行 GPU 计算;使用 Numpy 或其他方法来进行 CPU 计算。研究人员有时也会使用更上层的框架,比如基于 TensorFlow 的 Keras。

和多数深度学习社区一样,我们会使用 Python2.7。Anaconda 也经常会用到,它可以方便地给 OpenCV 打包,并对一些科学算法库进行性能优化。

硬件

对于理想的批处理任务,将集群计算节点的数量翻倍会减半任务执行时间。不幸的是,在深度学习中,GPU 数量的增加只会引起任务亚线性的加速。因此顶级的计算性能只能依靠顶级的 GPU 来实现。我们也使用了许多 CPU 用于构建模拟器、增强学习环境或是小规模的模型(这类模型跑在 GPU 上时运行效率不会有明显的增加)。

nvidia-smi 下满载的 Titan Xs

AWS 慷慨地为我们提供了大量计算资源。这些资源被用于 CPU 实例以及 GPU 任务的水平扩展。我们也有自己的物理机,用的是 Titan X GPU。我们期望之后可以使用混合云:对不同的 GPU、连接以及其他技术开展实验是非常具有价值的,这对深度学习未来的发展也有着重要影响。

相同物理单元上的 htop 显示了大量空闲的 CPU。我们通常将 CPU 密集型和 GPU 密集型的任务分开运行。

配置

我们对待基础架构就像许多公司对待他们的产品一样:它的界面必须简洁,必须兼顾功能性和可用性。我们会使用一致的工具来统一管理所有服务器,并且尽可能地对他们进行相同的配置。

用于管理弹性伸缩组的 Terraform 配置文件片段。Terraform 可以创建、修改或销毁正在运行的云资源来匹配配置文件。

我们使用 Terraform 来创建 AWS 的云资源(实例、网络路由、DNS 记录等)。我们的云端节点和物理节点都运行 Ubuntu 系统,并使用 Chef 来做配置。为了实现加速,我们使用 Packer 来预先制作集群镜像(AMI)。我们的所有集群都使用非交叉的 IP 范围,用户可以通过笔记本上的 OpenVPN 及物理节点上的 strongSwan(AWS 的客户网关)连接到公网。

最后,我们将用户的 home 目录、数据集和结果存储在 NFS(基于物理硬件)和 EFS/S3(基于 AWS)上。

编排

可扩展的基础架构通常会使原本简单的用例复杂化。我们在对不同规模作业的基础架构研究上投入了同等的精力,也在同步优化工具套件,使得分布式的用例能像本地用例一样好用。

我们为随机实验提供了 SSH 节点的(有些有 GPU 有些没有)集群,并且使用 Kubernetes 来调度物理节点和 AWS 节点。我们的集群横跨 3 个 AWS 域——因为有时任务量会突然爆发,从而占满单个区域的所有资源。

Kubernetes 要求每一个任务都是一个 Docker 容器,这样就可以实现依赖隔离和代码快照。但是创建一个新的 Docker 容器会增加迭代周期的时间,这个时间十分宝贵,所以我们也提供工具,将研究人员笔记本上的代码转成标准镜像。

TensorBoard 中的模型学习曲线

我们将 Kubernetes 的 flannel 网络直接暴露至研究人员的电脑,使用户可以无缝访问正在运行的任务。这对于访问 TensorBoard 这类监控服务特别有帮助。(为了实现绝对的隔离,我们最初要求针对每一个暴露的端口都要创建 Kubernetes 服务,但这样会带来很多困难。)

kubernetes-ec2-autoscaler

我们的任务负载具有突发性和不可预测性:原先只需要单节点的实验可能很快就发展到需要 1000 个核。比如在几周的时间里,实验从只需要一个 Titan X 的交互阶段发展到了需要 60 个 Titan X 的实验阶段,这需要将近 1600 个 AWS 的 GPU。因此,我们的云架构要能动态配置 Kubernetes 节点。

在弹性伸缩组中运行 Kubernetes 节点非常简单,困难的是如何正确地配置这些组的规模。在提交批处理任务后,集群可以准确地知道它需要的资源并直接进行分配。(相反,AWS 的扩展策略会不断地启动新的节点碎片来提供足够的资源,这是一个多次迭代的过程。)集群还需要在终止节点前进行任务迁移(drain)操作,避免丢失正在运行的任务。

很多人想直接使用原始的 EC2 来处理大批量的任务,我们一开始也是这么做的。但是 Kubernetes 的生态具有更多优势:比如易用的工具、日志记录、监控、从运行实例中区分管理物理节点的能力等。合理配置 Kubernetes 使其能够正确地动态扩展要比在原始 EC2 上重建这种环境来的简单。

我们发布的 kubernetes-ec2-autoscaler,是一种用于 Kubernetes 批处理任务的弹性伸缩管理器。它在 Kubernetes 上作为一个普通的 Pod 运行,且只要求你的工作节点运行在弹性伸缩组内。

Kubernetes 集群的启动配置

自动扩展器会轮询 Kubernetes 主节点的状态,包括用于计算集群所需资源和容量的所有信息。如果超出了容量,它会将相关节点的任务迁移(drain)后将其终止。如果需要更多的资源,它会计算需要创建什么样的服务器并适当地增加弹性伸缩组的规模(或直接解锁 (uncordon) 执行过 drain 操作的节点,来避免新节点增加的启动时间)。

kubernetes-ec2-autoscaler 管理着多个弹性伸缩组、CPU 之外的资源(内存和 GPU)以及对任务细粒度的约束,例如 AWS 区域和实例大小。另外,突增的负载会引起弹性伸缩组的超时和报错,因为即使是 AWS 也不具备无限扩展的容量。这种情况下,kubernetes-ec2-autoscaler 会检测到错误并将超出部分的任务分配到次级的 AWS 区域执行。

我们的基础架构设计旨在最大程度地提高科研人员的工作效率,使他们能够专注于科研本身。我们将继续深入优化基础架构和工作流程,之后也会陆续和大家分享经验。我们期待与您的合作,共同促进深度学习的发展!

查看英文原文

https://blog.openai.com/infrastructure-for-deep-learning


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存