写在前面:
翻译这篇文章的时候,正好读到了一篇讲述 GAN 的文章,不过忍住没看到了翻译完再仔细看了一遍。一对比确实发现了翻译还是比较生硬的问题。
文章是OpenAI 公司关于深度学习方面的经验分享,专业术语也比较多。自己翻译完倒算是了解了关于深度学习方面的科普
原文链接: Infrastructure for Deep Learning
译文部分:
深度学习属于经验学科,随着现在研究的进展所用到的基础框架也在不断地完善。幸运地是,开源系统让任何人都有搭建一个深度学习架构的可能。
在这篇文章中,我们将要分享如何进行深度学习的研究,以及我们选择的基础框架和用来批量优化 Kubernetes 的规模化管理的开源项目 Kubernetes-ec2-autoscaler。希望会对你有帮助。
用例
一个典型的深度学习案例都起源于一个想法,通常这个想法用来解决一个小问题。这个时候,你一般会跑几个特定的方法,最好的是你可以添加一个SSH协议,跑一个脚本然后一个小时内就可以得到结果。
验证一个深度学习模型是否有效通常需要验证它在所有可能想到的场景下失败的案例,同时也要找到解决这些失败问题的方法。(这个和开发一个新软件的过程很像— 不停的编译调试来验证自己的想要的结果)
视频地址
(你需要从不同角度去观察你的模型,来获得一种觉得模型会从中学到什么的直觉。图中的强化学习游戏(控制右侧的面板)最终拿到了很高的分数,但是当你仔细观察你会发现右侧的绿色面板一动不动。所以深度学习的基础框架需要学者学会反向思考,只是总结数据是不够的。)
一旦模型按如期分析时进展,你就可以扩大整个数据集合和GPU (不确定是不是指显卡)。这个过程要花好几轮同时也会持续很多天。你会需要细致的方法管理,而且对于选择的超参数类型也要极为小心。
(这里应该说的是深度学习中的专业名词,可能翻译得不太对-0-)
案例
持续双向网络训练提高的技术 论文主要讲述了 Tim Salimans 为提高持续双向网络训练所发明的几个方法。下面我们主要简单讲述一下这些方法(这些方法恰好产出了最好看的案例,却不是最好的半监督算法方式)
GANs 由一个生成网络和鉴别网络构成。生成网络会试图欺骗鉴别网络,鉴别网络需要分辨生成网络中的数据和真数据。一般生成网络可以非常容易地欺骗任何鉴别网络。但是有一个难以修复的失败模式:生成网络可以通过“自毁”输出完全一样的样本(就像真实可见!)。
Tim 提出了一个方法,给鉴别网络一份批梯度下降(Mini-Batch)的完整样本作为输入,而不是仅仅是一个样本。这样鉴别器就可以分别是不是生成器在持续输出一张图片。当自毁模式被发现,梯度数据就会被传送给生成器来纠正问题。
下一步就是在 MNIST 和 CIFAR-10 上画出原型。这需要快速画出一个小模型并用正式数据跑通来观测结果。在几次快速迭代之后,Tim 得到了一个不错的 CIFAR-10 样本--差不多是我们在这个数据集中看到的最好样本。
然而,深度学习(实际上也是 AI 算法)必须被应用到大范围内容才会更出色--一个小的神经网络只能作为一些概念的证明,大的神经网络才能解决问题。所以Ian Goodfellow 持续研究模型并应用到了 ImageNet 上。
(我们的模型 正在学习生成 ImageNet 的图片)
因为包含了更大的模型和数据集,Ian 需要将模型在多个GPU上平行放置处理。每一项都需要90%CPU 和 GPU 的利用率,即使这样,模型也花费了好几天来训练。在这种方式中,每一次试验都很珍贵,所以Ian会给每一个结果和试验仔细地写上日志。
最终结果还不错,但还没有达到我们想要的地步。我们测试了许多问题可能造成的原因,但仍旧还没有攻破。这就是科学研究的自然现象。
基础框架
软件
(一段 关于样本的TensorFlow 代码
我们大量的研究代码是用Python写的,在我们的开源项目中就有体现。在GPU计算方面我们大部分用的是TensorFlow (特殊情况下会用到 Theano); CPU 也用到Numpy, 研究人员也会用到TensorFlow中更高级别的框架,例如 Keras.
和许多其他深度学习社区一样,我们用Python 2.7, 通常使用 Anaconda 安装管理程式。它有比 OpenCV 和 performance optimizations 更严谨的库类型
硬件
对一个理想化的批处理工作而言,将数据组中的节点加倍则能缩短程序运行时间一倍。然而,在深度学习中,人们总是会在许多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 模板(Amazon 系统映像).我们所有的集群都用的是非重叠的IP列并且用OpenVPN和用户的公共网络连接,用strongSwan作为物理节点(以AWS Customer Gateways 运行)
我们使用NFS(在硬件服务器上运行)和EFS / S3(在AWS服务上)存储用户的主目录,数据集合运行结果。
精心部署
可扩展的框架结构最终会让简单的案例变得困难。所以我们在不论大或小扩展项目的框架选取上采取了公平的力度,同时我们也经常完善我们的工具包让分布的用例也能像本地一样容易被获取。
我们提供了SSH 节点群(包含和非包含GPU)用于特定试验,同时使用 Kubernetes 作为云服务和和服务器节点的集群调度。我们的集群在AWS 上用到3个区域—整个任务非常具有突发性素以有时我们也会在单独区域试验。
Kubernetes 规定每一项任务都要在Docker容器上运行,这样更利于模块和代码之间独立。然而,创建一个Docker容器也需要再让研究人员花时间迭代循环。所以我们也提供了一个工具,让研究人员电脑上的代码转移到一个标准图表中。
我们直接将Kubernetes 中的flannel 网络映射到研究人员的电脑上,让用户能持续获取他们的运行任务。这对获取监测服务尤其有效,例如 TensorBoard 。(我们最初的设想———比一个严格分开的视角更清晰 —需要用户为他们想要的每个接口创建一个Kurbernetes 服务,但是我们发现这样也会更复杂。)
kubernetes-ec2-autoscaler
我们的工作量比较波动也很难预估:一次简单的调研可能从至需要一个单机器试验增加到1000个。例如,在几个星期内,有个试验本来是在一个Titan X 上进行交互的阶段,最后要60个Titan X, 用到了接近1600 个AWS GPU.我们的云框架因此需要动态提供Kubernetes 节点。
在Auto Scaling 组中运行 Kubernetes 更容易,但却很难精确控制组件的大小。在梯度任务提交后,集群能精确知道它需要多少资源,也知道如何去分配。(相反,AWS 的 Scaling Policies 会启用新节点直到资源用尽,这样也会造成更多迭代)同样,集群会在终止节点前耗尽它们以避免丢失运行中的任务。
我们也打算使用 raw EC2 来运行更大的梯度任务。然而,Kubernetes 生态系统有更多的价值:低摩擦工具,日志,监测,将物理节点从正在运行的实例中分开,等等.让Kubernetes 精确地自动监测比在raw EC2 上重建整个系统要容易。(这里大概是在给 lKubernetes 打广告吧)
我们发布了 Kubernetes-ec2-autoscaler, 一个专门为Kubernetes 优化的梯度优化扩展管理器。它会在Kubernetes上隔离运行,也只需要在自动扩展组件中的一些工作节点。
自动监测管理器通过推送 Kubernetes 的master状态来工作。master分支上包含了所有需要计算集群资源并请求分配的内容。如果容量负载,它会终止相关节点运行。如果有更多资源需要掉配,它会计算需要被创建的服务然后适当的增加自动扩展组件的大小(或者解除受限节点,也避免了新节点的运转时间)。
Kubernetes-ec2-autoscaler 能处理多个自动扩展组件,CPU以外的资源(存储器和 GPU),以及任务处理上的细微限制,例如AWS 阵列和实例大小。另外,突发性的工作量也可能会让自动扩展组件超时甚至报错,因为AWS 也没有无限容量,所以 Kubernetes-ec2-autoscaler 会监测到错误和溢出转而使用第二级AWS 阵列。