Bootstrap

Training端深度学习框架(tensorflow和pytorch)

Training端深度学习框架

Pytorch VS Tensorflow

Google 的 Tensorflow

TensorFlow 是谷歌的开发者创造的一款开源的深度学习框架,于 2015 年发布。官方研究发布于论文《TensorFlow:异构分布式系统上的大规模机器学习》。

论文地址:http://download.tensorflow.org/paper/whitepaper2015.pdf

TensorFlow 现已被公司、企业与创业公司广泛用于自动化工作任务和开发新系统,其在分布式训练支持、可扩展的生产和部署选项、多种设备(比如安卓)支持方面备受好评。

Facebook的Pytorch

PyTorch 是由 Facebook 的团队开发,并于 2017 年在 GitHub 上开源。有关其开发的更多信息请参阅论文《PyTorch 中的自动微分》。

论文地址:https://openreview.net/pdf?id=BJJsrmfCZ

PyTorch 很简洁、易于使用、支持动态计算图而且内存使用很高效,因此越来越受欢迎。

  • PyTorch是Torch框架的表亲,Torch是基于lua开发的,在Facebook公司里被广泛使用。然而,PyTorch的出现并不是为了支持流行语言而对Torch进行简单的包装,它被重写和定制出来是为了得到更快的速度和本地化。
  • TensorFlow由谷歌开发,并且在谷歌公司中广泛地应用于研究和生产需求。它的前身是闭源的DistBelief。

比较这两个框架最好的方法就是用它们编写代码。我专门为这篇文章写了一个jupyter笔记,你可以在这里找到代码,文章涉及到的所有的代码都有。

Pytorch

与 PyTorch 相比,TensorFlow 的学习曲线相对较徒。Python 程序员需要较少的时间即可使用 PyTorch,因为对他们来说,PyTorch 更像是 Python 框架的扩展。简单的调试和一套优秀的简单 API 就能使程序员轻松驾驭 PyTorch。PyTorch 是研究人员的神器,因为事实证明,开发框架的研究人员至少有 70% 都在使用 PyTorch。尽管 TensorFlow 是业界领先的应用开发选择,但它在这方面还没有赶上 PyTorch。这背后的一个原因可能是 PyTorch 的简单易用性和更好的性能。在 TensorFlow 的世界里, PyTorch 能够凭借自己的强项坚守自己。下面是 PyTorch 的一些亮点,解释了为什么 PyTorch 适合深度学习项目。

Pytorch更“Python”化

PyTorch 是一个实用框架,它可以让我们以更 “Python 化” 的方式编写代码。此外,它是使用朴素的 Python 代码所支持的那种动态特性。

与任何其他库相比,PyTorch 更倾向于 Python。这是因为 PyTorch 相对容易理解,而且感觉更自然、更原生,和 Python 代码一致。对于任何使用过 PyTorch 的人来说,比如损失函数、优化器、转换、数据加载器以及更多的类都是非常容易实现的。

每个 PyTorch 示例(计算机视觉和自然语言处理)的代码都有一个共同的结构:

data/
experiments/
model/
    net.py
    data_loader.py
train.py
evaluate.py
search_hyperparams.py
synthesize_results.py
evaluate.py
utils.py

  • model/net.py:指定神经网络架构、损失函数和评估指标。
  • model/data_loader.py:指定数据应如何馈送到网络。
  • train.py:包含主训练循环。
  • evaluate.py:包含用于评估模型的主循环。
  • utils.py:用于处理超参数/日志/存储模型的实用功能。

有用的库

  • pro_gan_pytorch:利用 ProGAN 功能。
  • BoTorch:使用贝叶斯优化。
  • ParlAI:用于共享、训练和测试对话模型。
  • OpenNMT-py:用于实现神经机器翻译系统。
  • MUSE:用于多语言词嵌入。
  • skorch:用于将 scikit-learn 代码与 PyTorch 融合。

轻松实现数据并行

PyTorch 中的数据并行(Data Parallel)非常高效,可以将数据分成若干批,然后发送到多个 GPU 进行处理。使用这种技术,PyTorch 可以将很大一部分工作负载从 CPU 转移到 GPU。为了实现数据并行,它使用了 torch.nn.DataParallel 类。

Distributed Data-Parallel(分布式数据并行)是 PyTorch 的一项特性,你可以将其与 Data-Parallel(数据并行)结合使用来处理需要大型数据集和模型的用例,这些数据集和模型对单个 GPU 来说过于庞大。当 GPU 池上的所有任务完成之后,结果将被收集、合并,再由 Data-Parallel 发回给你。

def get_cnn(self, arch, pretrained):
        """Load a pretrained CNN and parallelize over GPUs
        """
        if pretrained:
            print(("=> using pre-trained model '{}'".format(arch)))
            model = models.__dict__[](pretrained=True)
        else:
            print(("=> creating model '{}'".format(arch)))
            model = models.__dict__<a href="">arch

        if arch.startswith('alexnet') or arch.startswith('vgg'):
            model.features = nn.DataParallel(model.features)
            model.cuda()
        else:
            model = nn.DataParallel(model).cuda()

        return model
</a href="">

移动开发就绪

从版本 1.3 开始,PyTorch 就增加了对 Android 和 iOS 设备部署的支持。这一特性,为边缘设备带来了 PyTorch 的所有优势,以满足需要较低延迟的应用。PyTorch mobile 背后的目标是通过支持移动平台的基础 API 来缩短开发周期,从而无需导出到诸如 Caffe2 之类的移动框架。这样可以大大减少设备上的占用空间。此外,为了更好地控制,还增加了对构建脚本的精确调优的支持。

PyTorch Mobile 入门:

易于调试

当你可以选择访问每一行,并在每一行后打印的常规方式,PyTorch 调试起来很容易。锦上添花的是,PyTorch 中的对象和操作包含了实际的数据而不是符号引用。PyTorch 的一些标准调试器是:

  • ipdb
  • pdb
  • PyCharm

例如,你可以使用 pdb 的 pdb.set.trace() 函数在代码中放置断点,从而深入到错误的根源。此外,PyTorch 的动态计算图允许在代码执行时进行动态修改和快速调试。

支持ONNX

开放神经网络交换格式(Open Neural Network Exchange,OONX)作为人工智能的开源生态系统,为人工智能程序员提供了一个共同的平台,让他们可以在各种框架、工具和库上进行互换工作。ONNX 通过提供可跨多个框架和硬件工作的标准文件格式来实现这一目标。PyTorch中,ONNX 内置了对 PyTorch 和其他一系列框架的支持,如 Caffe2、MXNet、TensorFlow 等等。ONNX 使开发人工智能的程序员更容易导出和迁移他们的 PyTorch 模型,使之成为其他框架可以集成的开放格式。

import torch.onnx
import torchvision

  dummy_input = torch.randn(1, 3, 224, 224)
  model = torchvision.models.alexnet(pretrained=True)
  torch.onnx.export(model, dummy_input, "alexnet.onnx")

支持动态计算图

通过将每个模型视为有向无环图,PyTorch 提供了一种定义计算图的动态方法。虽然其他框架也允许静态图定义,但 PyTorch 还支持创建动态计算图,你可以随时对其进行操作。从 PyTorch 的动态特性中获益最多的一个元素是递归神经网络。

强大的社区支持

PyTorch 还提供了优秀的社区支持。PyTorch 的主页上就有关于它每个特性的详细文档。对库的所有最新更新都作了很好的解释。对于每个新添加的内容,都可以找到辅导教程和相关资源,易于上手。

下面是一些 PyTorch 开发人员社区、资源和教程,你可以通过这些资源和教程来贡献、学习和解惑:

PyTorch Discuss form

PyTorch Slack Community

PyTorch Examples

PyTorch Docs

Github Pytorch Tutorials

PyTorch Beginner Cheatsheet

PyTorch Release Notes

Deep Learning With Pytorch : A 60 Minute Blitz

Using Tutorial data from Google Drive in Colab

Docs and Tutorials in Chinese

Tutorials in Korean

TensorFlow

张量:可理解为一个 n 维矩阵,所有类型的数据,包括标量、矢量和矩阵等都是特殊类型的张量。

TensorFlow 支持以下三种类型的张量:

  1. 常量constant:常量是其值不能改变的张量。
  2. 变量variable:当一个量在会话中的值需要更新时,使用变量来表示。例如,在神经网络中,权重需要在训练期间更新,可以通过将权重声明为变量来实现。变量在使用前需要被显示初始化。另外需要注意的是,常量存储在计算图的定义中,每次加载图时都会加载相关变量。换句话说,它们是占用内存的。另一方面,变量又是分开存储的。它们可以存储在参数服务器上。
  3. 占位符placeholder:用于将值输入 TensorFlow 图中。它们可以和 feed_dict 一起使用来输入数据。在训练神经网络时,它们通常用于提供新的训练样本。在会话中运行计算图时,可以为占位符赋值。这样在构建一个计算图时不需要真正地输入数据。需要注意的是,占位符不包含任何数据,因此不需要初始化它们。

高度灵活性

TensorFlow 不是一个严格的“神经网络”库。只要你可以将你的计算表示为一个数据流图,你就可以使用Tensorflow。你来构建图,描写驱动计算的内部循环。我们提供了有用的工具来帮助你组装“子图”(常用于神经网络),当然用户也可以自己在Tensorflow基础上写自己的“上层库”。定义顺手好用的新复合操作和写一个python函数一样容易,而且也不用担心性能损耗。当然万一你发现找不到想要的底层数据操作,你也可以自己写一点c++代码来丰富底层的操作。

可移植性

Tensorflow 在CPU和GPU上运行,比如说可以运行在台式机、服务器、手机移动设备等等。想要在没有特殊硬件的前提下,在你的笔记本上跑一下机器学习的新想法?Tensorflow可以办到这点。准备将你的训练模型在多个CPU上规模化运算,又不想修改代码?Tensorflow可以办到这点。想要将你的训练好的模型作为产品的一部分用到手机app里?Tensorflow可以办到这点。你改变主意了,想要将你的模型作为云端服务运行在自己的服务器上,或者运行在Docker容器里?Tensorfow也能办到。

科研、产品紧密相联

过去如果要将科研中的机器学习想法用到产品中,需要大量的代码重写工作。那样的日子一去不复返了!在Google,科学家用Tensorflow尝试新的算法,产品团队则用Tensorflow来训练和使用计算模型,并直接提供给在线用户。使用Tensorflow可以让应用型研究者将想法迅速运用到产品中,也可以让学术性研究者更直接地彼此分享代码,从而提高科研产出率。

自动求微分

基于梯度的机器学习算法会受益于Tensorflow自动求微分的能力。作为Tensorflow用户,你只需要定义预测模型的结构,将这个结构和目标函数(objective function)结合在一起,并添加数据,Tensorflow将自动为你计算相关的微分导数。计算某个变量相对于其他变量的导数仅仅是通过扩展你的图来完成的,所以你能一直清楚看到究竟在发生什么。

多语言支持

Tensorflow 有一个合理的c++使用界面,也有一个易用的python使用界面来构建和执行你的graphs。你可以直接写python/c++程序,也可以用交互式的ipython界面来用Tensorflow尝试些想法,它可以帮你将笔记、代码、可视化等有条理地归置好。当然这仅仅是个起点——我们希望能鼓励你创造自己最喜欢的语言界面,比如Go,Java,Lua,Javascript,或者是R。

性能最优化

比如说你有一个32个CPU内核、4个GPU显卡的工作站,想要将你工作站的计算潜能全发挥出来?由于Tensorflow 给予了线程、队列、异步操作等以最佳的支持,Tensorflow 让你可以将你手边硬件的计算潜能全部发挥出来。你可以自由地将Tensorflow图中的计算元素分配到不同设备上,Tensorflow可以帮你管理好这些不同副本。

对比

上手时间 – PyTorch上手快

  • PyTorch 本质上是支持 GPU 的 NumPy 替代,配备了可用于构建和训练深度神经网络的更高级的功能。所以如果你熟悉 NumPy、Python 和常用的深度学习抽象(卷积层、循环层、SGD 等),那 PyTorch 就很容易学。
  • 另一方面,则可以将 TensorFlow 看作是一种嵌入 Python 的编程语言。当你编写 TensorFlow 代码时,它会被 Python「编译」成图(graph),然后由 TensorFlow 执行引擎运行。我看到过有些 TensorFlow 新手难以理解这额外增加的间接一层工序。同样因为这个原因,TensorFlow 还有一些需要额外学习的概念,比如会话(session)、图、变量范围和占位符。要让基本的模型跑起来也需要更多样板代码。上手 TensorFlow 的时间肯定会比 PyTorch 长。

创建图和调试 – PyTorch

创建和运行计算图可能是这两个框架差别最大的地方。在 PyTorch 中,图结构是动态的,也就是说图是在运行时创建的。在 TensorFlow 中,图结构是静态的,也就是说图在「编译」之后再运行。举个简单例子,在 PyTorch 中,你可以使用标准的 Python 句法写一个 for 循环:

而且 T 可以在这段代码的执行之间改变。在 TensorFlow 中,这需要在构建图时使用控制流操作(control flow operations),比如 tf.while_loop。TensorFlow 确实有 dynamic_rnn 可用于更常见的结构,但创建自定义的动态计算也更加困难。

PyTorch 简单的图构建方式更容易理解,但也许更重要的是也更容易调试。调试 PyTorch 代码就跟调试 Python 代码一样。你可以使用 pdb,并且可以在任何地方设置断点。调试 TensorFlow 则没这么容易。它有两个选择,一是从会话中请求你想检查的变量,而是学会使用 TensorFlow 调试器(tfdbg)。

覆盖度 – TensorFlow

随着 PyTorch 的发展,这两者之间的差距会缩小至零。但是,TensorFlow 仍然支持一些 PyTorch 并不支持的功能。PyTorch 目前还不具备的特性包括:

  • 沿维度方向的张量翻转(np.flip、 np.flipud、 np.fliplr)
  • 检查张量是否为 NaN 和无穷大(np.is_nan、np.is_inf)
  • 快速傅立叶变换(np.fft)

而 TensorFlow 支持所有这些。另外比起 PyTorch,TensorFlow 的 contrib 包也有远远更多更高级的函数和模型。

序列化(serialization) – TensorFlow

在这两种框架中,保存和加载模型都很简单。PyTorch 有一个非常简单的 API,既可以保存模型的所有权重,也可以 pickle(加工)整个类。TensorFlow 的 Saver 对象也很容易使用,而且也为检查点提供了更多选择。

TensorFlow 在序列化方面的主要优势是整个计算图都可以保存为 protocol buffer。这既包括参数,也包括运算。然后这个图可以用其它支持的语言(C++、Java)加载。对于不支持 Python 的部署环境来说,这是非常重要的功能。而且理论上,这个功能也可以在你修改模型的源代码,但又想运行旧模型时为你提供帮助。

部署 – TensorFlow

对于小型服务器(比如 Flask 网页服务器)上的部署,两种框架都很简单。

TensorFlow 支持移动和嵌入式部署,而包括 PyTorch 在内的很多深度学习框架都没有这个能力。在 TensorFlow 上,要将模型部署到安卓或 iOS 上需要不小的工作量,但至少你不必使用 Java 或 C++ 重写你模型的整个推理部分。

对于高性能服务器上的部署,还有 TensorFlow Serving 可用。对于严重依赖机器学习的服务,TensorFlow Serving 可能就是继续使用 TensorFlow 的充分理由。除了性能方面的优势,TensorFlow Serving 的另一个重要特性是无需中断服务,就能实现模型的热插拔。

数据加载 – PyTorch

  • PyTorch 的数据加载 API 设计得很好。数据集、采样器和数据加载器的接口都是特定的。数据加载器可以接收一个数据集和一个采样器,并根据该采样器的调度得出数据集上的一个迭代器(iterator)。并行化数据加载很简单,只需为数据加载器传递一个 num_workers 参数即可。
  • TensorFlow 还没有非常有用的数据加载工具(读取器、队列、队列运行器等等)。部分原因是要将你想并行运行的所有预处理代码加入到 TensorFlow 图中并不总是那么简单直接(比如计算频谱图)。另外,TensorFlow 的 API 本身也更加冗长,学习起来也更难。

设备管理 – TensorFlow

TensorFlow 的设备管理的无缝性能非常好。通常你不需要指定任何东西,因为默认的设置就很好。比如说,TensorFlow 假设如果存在可用的 GPU,你就希望在 GPU 上运行。而在 PyTorch 中,你必须在启用了 CUDA 之后明确地将所有东西移到 GPU 上。

TensorFlow 设备管理的唯一缺陷是它会默认占用所有可用的 GPU 上的所有内存,即使真正用到的只有其中一个。但也有一种简单的解决方案,就是指定 CUDA_VISIBLE_DEVICES。有时候人们会忘记这一点,就会让 GPU 看起来很繁忙,尽管实际上它们啥也没干。

在使用 PyTorch 时,我发现我的代码需要更频繁地检查 CUDA 的可用性和更明确的设备管理。尤其是当编写可以在 CPU 和 GPU 上同时运行的代码时更是如此。另外,要将 GPU 上的 PyTorch Variable 等转换成 NumPy 数组也较为繁琐。

自定义扩展 – PyTorch

这两种框架都可以构建或绑定用 C、C++ 或 CUDA 写的扩展。TensorFlow 还是需要更多样板代码,尽管有人认为它能更简单清晰地支持多种类型和设备。在 PyTorch 中,你只需要简单地为每个 CPU 和 GPU 版本写一个接口和对应实现即可。这两种框架对扩展的编译都很直接,不需要下载 pip 安装之外的任何头文件或源代码。

总结

TensorFlow是一个非常强大非常成熟的深度学习库,具有非常强大的可视化功能,以及有多个可供选择的框架来进行高级模型开发。它具有用于生产的部署选项,以及对移动平台的支持。

  • 开发生产模型
  • 开发需要部署在移动平台上的模型
  • 需要良好的社区支持和齐全的文档
  • 想要各种形式的丰富的学习资源
  • 想要或需要使用Tensorboard(可视化工具)
  • 需要大规模的分布式模型训练

PyTorch仍然是一个年轻的框架,但其发展速度越来越快。它可能会比较适合:

  • 用于研究,或者是用于生产的非功能性需求并不是很苛刻
  • 需要更好的开发和调试体验
  • 所有Python化的东西
;