
深度学习机器学习人工智能【免费下载链接】mxnetLightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more项目地址https://gitcode.com/gh_mirrors/mxnet1/mxnet点击查看免费下载本文以 Apache MXNet 的 Gluon 命令式接口为主线与 PyTorch 进行全流程逐项对比从安装方式、张量操作、MNIST 多层感知机MLP训练到自动微分、自定义网络块、多卡与分布式训练、监控与模型序列化。读完本文你将掌握两个框架核心 API 的一一对应关系能够把 PyTorch 代码快速改写为 MXNet Gluon 代码并理解 Gluon 在梯度语义、惰性求值与混合编程Hybridize上的设计差异。说明本文中涉及性能对比的数值均引用原文档所引用的公开基准2019 年 4 月 NVIDIA 深度学习训练/推理性能基准属于特定软硬件与版本下的历史数据请结合当前环境自行实测验证。一、为什么从 PyTorch 迁移到 MXNetPyTorch 因其易于理解的 API 与完全命令式的编程风格广受欢迎。Apache MXNet 的 Gluon API 在提供与 PyTorch 相当的简洁性与灵活性的同时还允许通过hybridize()将命令式网络转换为符号图执行从而利用符号图的性能优化能力。两者的核心差异不在于能用而在于设计哲学术语差异PyTorch 沿用 Torch 的命名习惯把多维矩阵称为 TensorMXNet 沿用 NumPy 的约定称为 NDArray。梯度累积语义PyTorch 默认累积梯度每批训练前需手动zero_grad()MXNet Gluon 默认直接覆盖写入新梯度grad_reqwrite无需每批清空。执行模型MXNet 采用惰性求值lazy evaluationPython 线程把算子推入后端引擎后立即返回因此批结束处需要显式同步如asnumpy()、wait_to_read()、metric.update(...)。其余代码结构高度相似从一个框架迁移到另一个框架非常直接。二、安装方式对比PyTorch 默认使用 conda 安装例如# !conda install pytorch-cpu -c pytorchMXNet 使用 pip 安装 CPU 版本# !pip install mxnetGPU 版本需要指定 CUDA 版本号。例如安装支持 CUDA 9.2 的版本# !pip install mxnet-cuda92从仓库的 docker/Dockerfiles 目录可以看到官方镜像同样按 CUDA 8.0 / 9.0 / 9.2 划分如Dockerfile.mxnet.python.gpu.cu92印证了按 CUDA 版本选择安装包的发布约定。具体 pip 包名与可用 CUDA 版本请以当前发布渠道为准。三、数据操作Tensor 与 NDArray两个框架都以多维矩阵为数据基础。下面的代码创建一个 5×3 的全 1 矩阵逐元素加 1 后打印结果。PyTorchimport torch x torch.ones(5,3) y x 1 yMXNetfrom mxnet import nd x nd.ones((5,3)) y x 1 y除包名不同外最主要的差异是MXNet 的 shape 参数必须像 NumPy 一样以元组括号包裹传入即nd.ones((5,3))而非nd.ones(5,3)。两个框架都提供丰富的张量创建与操作函数。完整的 API 对照表见本文附录PyTorch 与 Gluon API 对照一节。四、模型训练四步走MNIST 上的 MLP 对比下面以 MNIST 手写数字分类任务为例在两个框架中分别训练一个单隐藏层多层感知机MLP整个过程分为四步。4.1 读取数据PyTorchfrom torchvision import datasets, transforms trans transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.13,), (0.31,))]) pt_train_data torch.utils.data.DataLoader(datasets.MNIST( root., trainTrue, downloadTrue, transformtrans), batch_size128, shuffleTrue, num_workers4)MXNetfrom mxnet import gluon from mxnet.gluon.data.vision import datasets, transforms trans transforms.Compose([transforms.ToTensor(), transforms.Normalize(0.13, 0.31)]) mx_train_data gluon.data.DataLoader( datasets.MNIST(trainTrue).transform_first(trans), batch_size128, shuffleTrue, num_workers4)两个框架都支持自动下载 MNIST 并只取训练集。主要区别在于MXNet 使用transform_first(trans)方法明确表示变换只作用于数据批次中的第一个元素图片而不作用于第二个元素标签PyTorch 则是把 transform 直接传给datasets.MNIST(..., transformtrans)。从源码看DataLoader与Dataset是 MXNet 数据加载的基础组件位于 python/mxnet/gluon/data 包中DataLoader类定义于 dataloader.py内置视觉数据集MNIST、CIFAR10、CIFAR100、ImageFolderDataset定义于 vision/datasets.py。4.2 创建模型PyTorchimport torch.nn as pt_nn pt_net pt_nn.Sequential( pt_nn.Linear(28*28, 256), pt_nn.ReLU(), pt_nn.Linear(256, 10))MXNetimport mxnet.gluon.nn as mx_nn mx_net mx_nn.Sequential() mx_net.add(mx_nn.Dense(256, activationrelu), mx_nn.Dense(10)) mx_net.initialize()两者都用Sequential容器逐层堆叠网络。MXNet 与 PyTorch 的差异体现在三点输入尺寸推断PyTorch 必须在Linear的第一个参数显式指定输入大小如28*28MXNet 的Dense只需指定输出单元数输入大小在第一次前向传播后自动推断。激活函数内联MXNet 可直接在全连接层和卷积层中指定激活函数如Dense(256, activationrelu)PyTorch 通常把ReLU作为独立层。显式初始化MXNet 在定义模型结构后必须显式调用mx_net.initialize()。从源码看Dense是HybridBlock的子类构造函数签名为Dense(units, activationNone, use_biasTrue, flattenTrue, ...)见 basic_layers.py。若需要更灵活的执行模型而非简单的顺序堆叠PyTorch 可以继承nn.Module并自定义forward()MXNet 对应继承nn.Block并重写forward()。4.3 损失函数与优化算法PyTorchpt_loss_fn pt_nn.CrossEntropyLoss() pt_trainer torch.optim.SGD(pt_net.parameters(), lr0.1)MXNetmx_loss_fn gluon.loss.SoftmaxCrossEntropyLoss() mx_trainer gluon.Trainer(mx_net.collect_params(), sgd, {learning_rate: 0.1})代码差异很小。MXNet 侧的关键点使用gluon.Trainer类把优化算法名如sgd作为字符串参数传入配合优化器参数字典{learning_rate: 0.1}。使用net.collect_params()收集网络全部参数对应 PyTorch 的net.parameters()见 block.py。Trainer类定义于 trainer.py其构造函数签名支持kvstore、compression_params、update_on_kvstore等分布式与梯度压缩相关参数交叉熵损失SoftmaxCrossEntropyLoss定义于 loss.py。4.4 训练循环PyTorchimport time for epoch in range(5): total_loss .0 tic time.time() for X, y in pt_train_data: pt_trainer.zero_grad() loss pt_loss_fn(pt_net(X.view(-1, 28*28)), y) loss.backward() pt_trainer.step() total_loss loss.mean() print(epoch %d, avg loss %.4f, time %.2f % ( epoch, total_loss/len(pt_train_data), time.time()-tic))MXNetfrom mxnet import autograd for epoch in range(5): total_loss .0 tic time.time() for X, y in mx_train_data: with autograd.record(): loss mx_loss_fn(mx_net(X), y) loss.backward() mx_trainer.step(batch_size128) total_loss loss.mean().asscalar() print(epoch %d, avg loss %.4f, time %.2f % ( epoch, total_loss/len(mx_train_data), time.time()-tic))注意由于权重初始化值与数据打乱顺序不同每次运行的结果会略有差异。MXNet 侧需要注意的六点差异无需手动展平MXNet 的Dense层默认flattenTrue前向传播时不必像 PyTorch 那样调用X.view(-1, 28*28)把 4-D 输入展平为 2-D。自动微分作用域MXNet 需要在autograd.record()作用域内完成前向计算以便反向传播时自动求导。无需每次清空梯度MXNet 默认grad_reqwrite新梯度直接写入覆盖不像 PyTorch 需要trainer.zero_grad()。step 需要步长trainer.step()必须传入更新步长通常是 batch size即mx_trainer.step(batch_size128)见 trainer.py。显式转标量total_loss loss.mean().asscalar()把多维数组转为 Python 标量。速度差异需谨慎解读原文档示例中 MXNet 快约两倍但作者明确提醒这类玩具级对比的结论需要谨慎对待。五、自动微分Autograd深度对比5.1 Variable 包装 vs autograd 作用域PyTorch 用Variable(..., requires_gradTrue)声明需要梯度的张量MXNet 用attach_grad()声明、autograd.record()作用域记录计算图功能PyTorchMXNet Gluon记录计算x Variable(torch.FloatTensor(1), requires_gradTrue)y x * 2y.backward()x mx.nd.ones((1,))x.attach_grad()with mx.autograd.record():y x * 2y.backward()5.2 作用域覆盖pause / train_mode / predict_modeDropout、BatchNorm 等算子在训练与推理阶段行为不同。MXNet 通过train_mode与predict_mode作用域控制这一行为pause作用域用于不需要计算梯度的代码段。这几个作用域在 autograd.py 中均有实现record(train_modeTrue)返回记录作用域pause(train_modeFalse)返回暂停作用域train_mode()与predict_mode()则只切换训练/推理行为而不改变记录状态。功能PyTorchMXNet Gluon作用域覆盖不可用x mx.nd.ones((1,))with autograd.train_mode():y mx.nd.Dropout(x)with autograd.predict_mode():z mx.nd.Dropout(y)w mx.nd.ones((1,))w.attach_grad()with autograd.record():y x * wy.backward()with autograd.pause():w w.grad5.3 批结束同步MXNet 采用惰性求值以换取性能Python 线程把算子推入后端引擎后立即返回。因此在训练阶段批结束处必须显式同步例如调用asnumpy()、wait_to_read()、metric.update(...)功能PyTorchMXNet Gluon批结束同步不可用for (data, label) in train_data:with autograd.record():output net(data)L loss(output, label)L.backward()trainer.step(data.shape[0])metric.update([label], [output])六、PyTorch Module 与 Gluon Block6.1 自定义网络块需要 name_scope自定义Block时Gluon 要求用self.name_scope()包裹子层的创建以便为每个参数赋予标识所属模型的恰当名称功能PyTorchMXNet Gluon自定义块class Net(torch.nn.Module):def __init__(self, D_in, D_out):super(Net, self).__init__()self.linear torch.nn.Linear(D_in, D_out)def forward(self, x):return self.linear(x)class Net(mx.gluon.Block):def __init__(self, D_in, D_out):super(Net, self).__init__()with self.name_scope():self.densemx.gluon.nn.Dense(D_out, in_unitsD_in)def forward(self, x):return self.dense(x)6.2 参数与初始化PyTorch 创建层时无需指定参数初始化器各层有各自的默认初始化Gluon 中既可以显式指定初始化器也可以留空所有参数在调用net.initialize(...)后完成初始化——未指定初始化器的层使用传入initialize的全局默认初始化器。Block.initialize的完整签名init、ctx、verbose、force_reinit见 block.py。功能PyTorchMXNet Gluon获取全部参数net.parameters()net.collect_params()初始化网络不可用net.initialize(mx.init.Xavier())指定层初始化器layer torch.nn.Linear(20, 10)torch.nn.init.normal(layer.weight, 0, 0.01)layer mx.gluon.nn.Dense(10, weight_initializermx.init.Normal(0.01))6.3 现有块的用法一致功能PyTorchMXNet Gluon使用现有块ynet(x)ynet(x)6.4 HybridBlock混合化与部分形状推断HybridBlock同时支持以 Symbol 和 NDArray 前向传播。hybridize()之后HybridBlock 会生成并缓存表示前向计算的符号图。大部分内置块Dense、Conv2D、MaxPool2D、BatchNorm 等都是 HybridBlock。hybridize(activeTrue, static_allocFalse, static_shapeFalse)的详细参数见 block.py。功能PyTorchMXNet Gluon部分形状 混合化不可用net mx.gluon.nn.HybridSequential()with net.name_scope():net.add(mx.gluon.nn.Dense(10))net.hybridize()6.5 SymbolBlock从符号图构建块SymbolBlock可以从符号Symbol构建网络块非常适合把预训练模型当作特征提取器使用功能PyTorchMXNet GluonSymbolBlock不可用alexnet mx.gluon.model_zoo.vision.alexnet(pretrainedTrue, prefixmodel_)out alexnet(inputs)internals out.get_internals()outputs [internals[model_dense0_relu_fwd_output]]feat_model gluon.SymbolBlock(outputs, inputs, paramsalexnet.collect_params())Block、HybridBlock、SymbolBlock三个基类在 block.py 中依次定义构成 Gluon 网络结构的完整继承体系。七、PyTorch Optimizer 与 Gluon Trainer7.1 大多数情况下无需调用 zero_gradPyTorch 优化器或 Gluon 的 Trainer中的zero_grad用于清空所有参数的梯度。Gluon 中当grad_reqwrite默认值时每批训练后梯度直接覆盖写入无需像 PyTorch 那样每批调用zero_grad()功能PyTorchMXNet Gluon清空梯度optm torch.optim.SGD(model.parameters(), lr0.1)optm.zero_grad()loss_fn(model(input), target).backward()optm.step()trainer gluon.Trainer(net.collect_params(), sgd, {learning_rate: 0.1})with autograd.record():loss loss_fn(net(data), label)loss.backward()trainer.step(batch_size)7.2 多 GPU 训练功能PyTorchMXNet Gluon数据并行net torch.nn.DataParallel(model, device_ids[0, 1, 2])output net(data)ctx [mx.gpu(i) for i in range(3)]data gluon.utils.split_and_load(data, ctx)label gluon.utils.split_and_load(label, ctx)with autograd.record():losses [loss(net(X), Y) for X, Y in zip(data, label)]for l in losses:l.backward()MXNet 侧使用gluon.utils.split_and_load把数据按设备切分然后分别前向、统一反向split_and_load位于 python/mxnet/gluon/utils.py。7.3 分布式训练功能PyTorchMXNet Gluon分布式数据并行torch.distributed.init_process_group(...)model torch.nn.parallel.distributedDataParallel(model, ...)store kv.create(dist)trainer gluon.Trainer(net.collect_params(), ..., kvstorestore)MXNet 通过 KVStore 机制实现分布式创建分布式 KVStorekv.create(dist)后把它作为kvstore参数传给Trainer参数更新即可在多机间协调。八、训练监控8.1 预定义评估指标Gluon 提供多个预定义指标可在训练中在线评估模型性能例如mx.metric.Accuracy()。源码中Accuracy、TopKAccuracy、CrossEntropy等指标类均定义于 python/mxnet/metric.py。功能PyTorchMXNet Gluon指标不可用metric mx.metric.Accuracy()with autograd.record():output net(data)L loss(ouput, label)loss(ouput, label).backward()trainer.step(batch_size)metric.update(label, output)8.2 数据可视化PyTorch 生态常用 TensorboardXMXNet 生态对应 MXBoardmxboard.SummaryWriter两者 API 风格一致PyTorchMXNetsw tensorboardX.SummaryWriter()sw mxboard.SummaryWriter()......for name, param in model.named_parameters():for name, param in net.collect_params():grad param.clone().cpu().data.numpy()grad param.grad.asnumpy().flatten()sw.add_histogram(name, grad, n_iter)sw.add_histogram(tagstr(param),...valuesgrad,sw.close()bins200,global_stepi)...sw.close()九、数据加载与模型部署9.1 数据加载组件Dataset与DataLoader是两个框架数据加载的基础组件类PyTorchMXNet Gluon数组数据集torch.utils.data.TensorDataset(data_tensor, label_tensor)gluon.data.ArrayDataset(data_array, label_array)数据加载器torch.utils.data.DataLoader(dataset, batch_size1, shuffleFalse, samplerNone, batch_samplerNone, num_workers0, collate_fnfunction default_collate, drop_lastFalse)gluon.data.DataLoader(dataset, batch_sizeNone, shuffleFalse, samplerNone, last_batchkeep, batch_samplerNone, batchify_fnNone, num_workers0)顺序采样器torch.utils.data.sampler.SequentialSampler(data_source)gluon.data.SequentialSampler(length)随机采样器torch.utils.data.sampler.RandomSampler(data_source)gluon.data.RandomSampler(length)注意gluon.data.DataLoader的last_batch参数默认keep对应 PyTorch 的drop_last。常用计算机视觉数据集在mx.gluon.data.vision包中提供数据集PyTorchMXNet GluonMNIST 手写数字torchvision.datasets.MNISTmx.gluon.data.vision.MNISTCIFAR10torchvision.datasets.CIFAR10mx.gluon.data.vision.CIFAR10CIFAR100torchvision.datasets.CIFAR100mx.gluon.data.vision.CIFAR100按文件夹组织的图片torchvision.datasets.ImageFolder(root, transformNone, target_transformNone, loaderfunction default_loader)mx.gluon.data.vision.ImageFolderDataset(root, flag, transformNone)9.2 模型序列化MXNet 的序列化通过save_parameters与load_parameters完成功能PyTorchMXNet Gluon保存模型参数torch.save(the_model.state_dict(), filename)model.save_parameters(filename)加载参数the_model.load_state_dict(torch.load(PATH))model.load_parameters(filename, ctx, allow_missingFalse, ignore_extraFalse)MXNet 的load_parameters额外支持allow_missing允许缺失参数与ignore_extra忽略多余参数方便网络结构调整后加载历史权重。附录PyTorch 与 Gluon API 完整对照A. Tensor 操作对照以下为 PyTorch Tensor 与 MXNet NDArray 中函数名存在差异的完整对照表功能PyTorchMXNet Gluon逐元素反余弦x.acos()或torch.acos(x)nd.arccos(x)批量矩阵乘积与累加torch.addbmm(M, batch1, batch2)nd.linalg_gemm(M, batch1, batch2)Leading n-2 维被约减t1、t2 逐元素相除、乘 v 再加 ttorch.addcdiv(t, v, t1, t2)t v*(t1/t2)矩阵乘积与累加torch.addmm(M, mat1, mat2)nd.linalg_gemm(M, mat1, mat2)两个向量外积加矩阵m.addr(vec1, vec2)不可用逐元素应用函数x.apply_(calllable)不可用但有nd.custom(x, op)逐元素反正弦x.asin()或torch.asin(x)nd.arcsin(x)逐元素反正切x.atan()或torch.atan(x)nd.arctan(x)两张量的正切x.atan2(y)或torch.atan2(x, y)不可用批量矩阵乘积x.bmm(y)或torch.bmm(x, x)nd.linalg_gemm2(x, y)从伯努利分布采样x.bernoulli()不可用用柯西分布随机数填充x.cauchy_()不可用按给定维切分张量x.chunk(num_of_chunk)nd.split(x, num_outputsnum_of_chunk)将张量值限制在 min 与 max 之间x.clamp(min, max)nd.clip(x, min, max)返回张量的副本x.clone()x.copy()叉积x.cross(y)不可用沿轴累积乘积x.cumprod(1)不可用沿轴累积求和x.cumsum(1)不可用首元素地址x.data_ptr()不可用创建对角张量x.diag()不可用计算张量的范数x.dist()nd.norm(x)仅计算 L2 范数计算高斯误差函数x.erf()不可用广播/扩展到新形状x.expand(3,4)x.broadcast_to([3, 4])用指数分布采样填充x.exponential_()nd.random_exponential()逐元素取模x.fmod(3)nd.module(x, 3)张量的小数部分x.frac()x - nd.trunc(x)沿 dim 指定轴取值torch.gather(x, 1, torch.LongTensor([[0,0],[1,0]]))nd.gather_nd(x, nd.array([[[0,0],[1,1]],[[0,0],[1,0]]]))最小二乘与最小范数求解B.gels(A)不可用几何分布采样x.geometric_(p)不可用张量所在设备print(x)会打印所在设备x.context重复张量x.repeat(4,2)x.tile(4,2)张量数据类型x.type()x.dtype散点写入torch.zeros(2, 4).scatter_(1, torch.LongTensor([[2], [3]]), 1.23)nd.scatter_nd(nd.array([1.23,1.23]), nd.array([[0,1],[2,3]]), (2,4))返回张量形状x.size()x.shape张量元素个数x.numel()x.size转为 NumPy ndarrayx.numpy()x.asnumpy()对称矩阵特征分解e, v a.symeig()v, e nd.linalg.syevd(a)转置x.t()x.T均匀采样torch.uniform_()nd.sample_uniform()插入新维度x.unsqueeze()nd.expand_dims(x)重塑x.view(16)x.reshape((16,))按指定张量重塑x.view_as(y)x.reshape_like(y)类型转换后返回副本x.type(type)x.astype(dtype)把一个张量的值复制到另一个dst.copy_(src)src.copyto(dst)指定形状的全 0 张量x torch.zeros(2,3)x nd.zeros((2,3))指定形状的全 1 张量x torch.ones(2,3)x nd.ones((2,3))与输入同形状、值为 1 的张量y torch.ones_like(x)y nd.ones_like(x)B. GPU 操作与 Tensor 类似MXNet NDArray 可通过指定 context 复制到 GPU 上运算功能PyTorchMXNet Gluon复制到 GPUy torch.FloatTensor(1).cuda()y mx.nd.ones((1,), ctxmx.gpu(0))转为 numpy 数组x y.cpu().numpy()x y.asnumpy()上下文作用域with torch.cuda.device(1):y torch.cuda.FloatTensor(1)with mx.gpu(1):y mx.nd.ones((3,5))C. 跨设备复制功能PyTorchMXNet Gluon从 GPU 0 复制到 GPU 1x torch.cuda.FloatTensor(1)yx.cuda(1)x mx.nd.ones((1,), ctxmx.gpu(0))yx.as_in_context(mx.gpu(1))在不同 GPU 间复制 Tensor/NDArrayy.copy_(x)x.copyto(y)结论Apache MXNet 的 Gluon API 与 PyTorch 在绝大多数场景下代码高度相似主要差异集中在两点一是术语不同Tensor vs NDArray二是梯度累积行为不同——PyTorch 累积梯度而 MXNet 默认覆盖梯度。掌握这些差异后在两个框架之间迁移代码非常直接。如果希望进一步挖掘 Gluon 的性能优势可以继续学习两个进阶主题Hybridize 教程学习如何编写既能以命令式执行、又能转换为符号图执行的混合编程代码从而获得符号图的性能优化能力。自定义层学习如何用自定义算子与自定义层扩展 MXNet实现论文中特有的网络结构。赞分享深度学习机器学习人工智能【免费下载链接】mxnetLightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more项目地址https://gitcode.com/gh_mirrors/mxnet1/mxnet点击查看免费下载相关推荐从 PyTorch 迁移到 Apache MXNetGluon API 逐行对照实战指南从 PyTorch 迁移到 Apache MXNetGluon API 逐行对照实战指南 Apache MXNet 通过 Gluon API 提供了与 PyT人工智能深度学习机器学习从 PyTorch 迁移到 Apache MXNetGluon API 逐模块对照实战指南从 PyTorch 迁移到 Apache MXNetGluon API 逐模块对照实战指南 Apache MXNet 的 Gluon API 为开发者提供了与深度学习人工智能机器学习分布式训练从 PyTorch 迁移到 Apache MXNetGluon API 全面对照指南MNIST 实战从 PyTorch 迁移到 Apache MXNetGluon API 全面对照指南MNIST 实战 本指南围绕 MXNet 官方 Moving to深度学习机器学习人工智能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考