前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CVPR 2017李沐介绍MXNet新接口Gluon:高效支持命令式与符号式编程

CVPR 2017李沐介绍MXNet新接口Gluon:高效支持命令式与符号式编程

作者头像
机器之心
发布2018-05-09 15:28:17
8690
发布2018-05-09 15:28:17
举报
文章被收录于专栏:机器之心机器之心

选自Github

机器之心编译

参与:Smith、蒋思源

MXNet 现已广泛应用于生产环境中,并且因为其运行速度而饱受赞誉。现在,MXNet 有了十分重要的新接口 Gluon,MXNet 可以通过它令科研工作变得更加简单。本文将简要介绍同时具备命令式执行和符号式执行的接口 Gluon,并且为读者介绍李沐博士在 CVPR 2017 上所做的 MXNet/Gluon 教程。机器之心也将对使用 Gluon 构建卷积神经网络和实现并行计算的过程与优势这两部分内容进行展开。更详细的内容请查看李沐博士的 Github。

教程地址:https://github.com/mli/cvpr17

在本教程中,我们将体验如何使用 Gluon 来实现各种各样的算法。我们将在本教程中细细体会每一个概念,并且无需深度学习背景。读者朋友也可以使用笔记本按照以下的介绍文档尝试使用 Gluon。此外,读者也将体验到 Gluon 命令式地开发和符号式地部署,这是非常高效和便捷的方式。

下面是本教程的文档和 PPT 资源。

  • 什么是 Gluon?为什么我们要使用 Gluon?:https://github.com/mli/cvpr17/blob/master/gluon_part1.pdf

第一部分:

  • n 维数组文档:http://gluon.mxnet.io/P01-C02-ndarray.html
  • 自动微分文档:http://gluon.mxnet.io/P01-C05-autograd.html
  • 线性回归:http://gluon.mxnet.io/P02-C01-linear-regression-scratch.html(文档一),http://gluon.mxnet.io/P02-C02-linear-regression-gluon.html(文档二)
  • 卷积神经网络:http://gluon.mxnet.io/P04-C01-cnn-scratch.html(文档一),http://gluon.mxnet.io/P04-C02-cnn-gluon.html(文档二)

第二部分:

  • 混合命令(hybridizing imperative)和符号编程文档:http://gluon.mxnet.io/P14-C05-hybridize.html
  • MXNet 后端引擎幻灯片:https://github.com/mli/cvpr17/blob/master/gluon_part2.pdf
  • 多 GPU 和多机器幻灯片:https://github.com/mli/cvpr17/blob/master/gluon_part3.pdf
  • 使用多 GPU 训练模型:http://gluon.mxnet.io/P14-C02-multiple-gpus-scratch.html(文档一),http://gluon.mxnet.io/P14-C03-multiple-gpus-gluon.html(文档二)
  • 使用多机器训练模型文档:http://gluon.mxnet.io/P14-C03-multiple-gpus-gluon.html

以上所有文档笔记都是可运行的,我们可以按照以下指示安装本教程。同时机器之心也将在文章后面介绍怎样使用 Gluon 构建卷积神经网络和并行运算。

运行本教程

每一个教程的文档都是使用 Jupyter notebook 构建的,因此它们都是可编辑和可运行的。现在假定大家已经安装了 Python,除此之外,我们还需要 Jupyter 和最新版本的 MXNet。下面的命令可以使用 pip 安装这三个库:

代码语言:javascript
复制
# optional: update pip to the newest version
sudo pip install --upgrade pip
# install jupyter
pip install jupyter --user
# install the nightly built mxnet
pip install mxnet --pre --user

默认的 MXNet 包只支持 CPU,但我们有一些教程需要调用 GPU。如果我们有可用的 GPU,并且安装了 CUDA 7.5 或 8.0,那么我们就可以使用 pip 安装 GPU 支持包:

代码语言:javascript
复制
pip install mxnet-cu75 --pre --user  # for CUDA 7.5
pip install mxnet-cu80 --pre --user  # for CUDA 8.0

现在我们就可以获取源代码并运行它们:

代码语言:javascript
复制
git clone https://github.com/zackchase/mxnet-the-straight-dope/
cd mxnet-the-straight-dope
jupyter notebook

最后的命令是运行 Jupyter notebook,然后我们就可以编辑和运行本教程了。

什么是 Gluon,为什么使用它?

在进入教程之前,我们需要先了解什么是 Gluon。如下图所示,我们可以看到各大主流框架的时间顺序,其中上半部分如 Chainer、Pytorch 和 MXNet 可以称为命令式(imperative)框架,下半部分可以称为符号式(symbolic)框架。我们能注意到,MXNet 同时具有命令式和符号式的特点。

如下所示,MXNet 在实现残差网络和 Adam 优化算法时所采用的代码。我们可以看到 MXNet 在定义残差网络时使用的是符号式的执行,我们需要像调用函数那样确定每一个参数而完整地定义一个神经网络。而 MXNet 在实现 Adam 优化算法时,我们可以看到它使用的是命令式的执行进行张量计算。但 MXNet 还不够优秀,我们需要更加强大的 Gluon。

因此我们可以从下图看到,Gluon 结合了命令式的框架 Pytorch、Chainer 和符号式的框架 Keras。它将更为强大,可以令科研更加轻松。

我们可以从下图查看 Gluon 的代码形式,前面一段可以看出 Gluon 使用的是符号式的执行构建神经网络,后面一部分构建 Softmax 交叉熵损失函数、计算梯度和执行反向传播等都十分简洁。net.hybridize() 函数可以将命令式执行转换为符号式执行。

总地来说符号式的执行更高效和便携,但是很难使用,而命令式的执行更灵活却可能比较慢。但是在 Gluon 中,我们可以使用命令式的执行开发模型,使用符号式的执行部署模型。因此,Gluon 将同时具备两种方法的优点,并且可以更加高效地应用在科研研究和产品中。

下面,我们分别从Gluon中的卷积神经网络和并行计算详细介绍Gluon的使用过程和特点,希望能和大家共同体会Gluon的命令式开发和符号式部署的高效性。

Gluon 中的卷积神经网络

现在我们看一下如何使用 gluon 来简洁的表示一个卷积神经网络。

代码语言:javascript
复制
from __future__ import print_function
import mxnet as mx
from mxnet import nd, autograd
from mxnet import gluon
import numpy as np
mx.random.seed(1)

设置环境

代码语言:javascript
复制
ctx = mx.gpu()

抓取 MNIST 数据集

代码语言:javascript
复制
mnist = mx.test_utils.get_mnist()
batch_size = 64
train_data = mx.io.NDArrayIter(mnist["train_data"], mnist["train_label"], batch_size, shuffle=True)
test_data = mx.io.NDArrayIter(mnist["test_data"], mnist["test_label"], batch_size, shuffle=True)

定义一个卷积神经网络

如果要改变模型,你仅需要对这些代码行进行操作,现在让我们使用 gluon.nn 填加一对卷积层。

代码语言:javascript
复制
net = gluon.nn.Sequential()
with net.name_scope():
    net.add(gluon.nn.Conv2D(channels=20, kernel_size=5, activation='relu'))
    net.add(gluon.nn.MaxPool2D(pool_size=2, strides=2))
    net.add(gluon.nn.Conv2D(channels=50, kernel_size=5, activation='relu'))
    net.add(gluon.nn.MaxPool2D(pool_size=2, strides=2))
    net.add(gluon.nn.Flatten())
    net.add(gluon.nn.Dense(500, activation="relu"))
    net.add(gluon.nn.Dense(10))

参数初始化

代码语言:javascript
复制
net.collect_params().initialize(mx.init.Xavier(magnitude=2.24), ctx=ctx)

Softmax 交叉熵损失函数

代码语言:javascript
复制
loss = gluon.loss.SoftmaxCrossEntropyLoss()

优化器

代码语言:javascript
复制
trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': .1})

编写评估循环以计算精度

代码语言:javascript
复制
def evaluate_accuracy(data_iterator, net):
    numerator = 0.
    denominator = 0.
    data_iterator.reset()
    for i, batch in enumerate(data_iterator):
        data = batch.data[0].as_in_context(ctx)
        label = batch.label[0].as_in_context(ctx)
        label_one_hot = nd.one_hot(label, 10)
        output = net(data)
        predictions = nd.argmax(output, axis=1)
        numerator += nd.sum(predictions == label)
        denominator += data.shape[0]
    return (numerator / denominator).asscalar()

训练循环

代码语言:javascript
复制
epochs = 10

for e in range(epochs):
    train_data.reset()
    moving_loss = 0.
    for i, batch in enumerate(train_data):
        data = batch.data[0].as_in_context(ctx)
        label = batch.label[0].as_in_context(ctx)
        with autograd.record():
            output = net(data)
            cross_entropy = loss(output, label)
        cross_entropy.backward()
        trainer.step(data.shape[0])

        moving_loss = .99 * moving_loss + .01 * nd.mean(cross_entropy).asscalar()

    test_accuracy = evaluate_accuracy(test_data, net)
    train_accuracy = evaluate_accuracy(train_data, net)
    print("Epoch %d. Loss: %e, Train_acc %.4f, Test_acc %.4f" % (e, moving_loss, train_accuracy, test_accuracy))
代码语言:javascript
复制
Epoch 0. Loss: 7.431280e-02, Train_acc 0.9664, Test_acc 0.9627Epoch 1. Loss: 4.358178e-02, Train_acc 0.9845, Test_acc 0.9816Epoch 2. Loss: 3.054833e-02, Train_acc 0.9913, Test_acc 0.9878Epoch 3. Loss: 2.258651e-02, Train_acc 0.9942, Test_acc 0.9896Epoch 4. Loss: 1.622117e-02, Train_acc 0.9954, Test_acc 0.9900Epoch 5. Loss: 1.204737e-02, Train_acc 0.9958, Test_acc 0.9900Epoch 6. Loss: 9.149311e-03, Train_acc 0.9963, Test_acc 0.9896Epoch 7. Loss: 7.570230e-03, Train_acc 0.9962, Test_acc 0.9892Epoch 8. Loss: 5.724863e-03, Train_acc 0.9978, Test_acc 0.9900Epoch 9. Loss: 4.022369e-03, Train_acc 0.9984, Test_acc 0.9912

结论

你可能会注意到,通过使用 gluon,我们可以让代码在 CPU 或 GPU 上运行的更快。这很大程度上是因为 gluon 可以调入已用 C++ 写好的高度优化层。

多 GPU 和多机器训练

如下图所示是一个用 2 块 GPU 实现 2 层神经网络的范例。可以看到,为这个两层神经网络编写并行程序是比较麻烦的,更何况对于一个动辄几百层的神经网络来说呢?

如下图所示,应用 MXNet 的相应方式编写串行程序,就可以实现并行化的运行,这是十分便捷的。

下图是数据并行化的概述过程:

当使用多台机器进行分布式计算时,用户不再需要大量改写代码。

运用阶层式参数服务器可将运算扩展到多台 GPU 机器:

下图是相关实验的设置情况:

如下图所示是多台机器的相关扩展性结果。

下图是用不同数量 GPU 完成 top-1 精确度的相关时间情况对比:

本文为机器之心编译,转载请联系本公众号获得授权。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-07-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器之心 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 运行本教程
  • 什么是 Gluon,为什么使用它?
  • Gluon 中的卷积神经网络
  • 多 GPU 和多机器训练
相关产品与服务
GPU 云服务器
GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档