Apache MXNet - Python 包


在本章中,我们将了解 Apache MXNet 中可用的 Python 包。

重要的 MXNet Python 包

MXNet 具有以下重要的 Python 包,我们将逐一讨论 −

  • Autograd(自动微分)

  • NDArray

  • KVStore

  • Gluon

  • 可视化

首先让我们从 Apache MXNet 的 Autograd Python 包开始。

Autograd

Autograd 代表自动微分,用于反向传播来自损失度量返回到每个参数。与反向传播一起,它使用动态规划方法来有效地计算梯度。它也被称为反向模式自动微分。这种技术在"扇入"情况下非常有效,在这种情况下,许多参数都会影响单个损失度量。

什么是梯度?

梯度是神经网络训练过程的基础。它们基本上告诉我们如何改变网络的参数来提高其性能。

众所周知,神经网络 (NN) 由诸如求和、乘积、卷积等运算符组成。这些运算符在计算时使用诸如卷积核中的权重之类的参数。我们应该找到这些参数的最优值,梯度为我们指明了方向,并引导我们找到解决方案。

Graph_of_Gradients

我们感兴趣的是改变参数对网络性能的影响,梯度告诉我们,当我们改变一个变量所依赖的变量时,给定变量会增加或减少多少。性能通常通过使用我们试图最小化的损失指标来定义。例如,对于回归,我们可能会尝试最小化预测值和精确值之间的 L2 损失,而对于分类,我们可能会最小化 交叉熵损失

一旦我们根据损失计算出每个参数的梯度,我们就可以使用优化器,例如随机梯度下降。

如何计算梯度?<​​/h2>

我们有以下选项来计算梯度 −

  • 符号微分 − 第一个选项是符号微分,它计算每个梯度的公式。这种方法的缺点是,随着网络越来越深,运算符变得越来越复杂,它将很快导致非常长的公式。

  • 有限差分 −另一种选择是使用有限差分,尝试对每个参数进行细微的差异,并查看损失度量如何响应。这种方法的缺点是,计算成本高,数值精度可能较差。

  • 自动微分 − 解决上述方法缺点的方法是使用自动微分将梯度从损失度量反向传播回每个参数。传播允许我们采用动态规划方法来有效地计算梯度。这种方法也称为反向模式自动微分。

自动微分 (autograd)

在这里,我们将详细了解 autograd 的工作原理。它基本上分为以下两个阶段 −

第 1 阶段 − 此阶段称为训练的"前向传递"。顾名思义,在此阶段,它会创建网络用于进行预测和计算损失指标的运算符的记录。

第 2 阶段 − 此阶段称为训练的"反向传递"。顾名思义,在此阶段,它会通过此记录向后工作。向后计算每个运算符的偏导数,一直回到网络参数。

自动微分

自动求导的优势

以下是使用自动求导 (autograd) 的优势 −

  • 灵活 − 灵活性,它在定义我们的网络时给予我们,是使用 autograd 的巨大好处之一。我们可以在每次迭代时更改操作。这些被称为动态图,在需要静态图的框架中实现起来要复杂得多。即使在这种情况下,Autograd 仍然能够正确地反向传播梯度。

  • 自动 − Autograd 是自动的,即它为您处理了反向传播过程的复杂性。我们只需要指定我们感兴趣的梯度计算。

  • 高效 − Autogard 可以非常高效地计算梯度。

  • 可以使用本机 Python 控制流运算符 − 我们可以使用本机 Python 控制流运算符,例如 if 条件和 while 循环。 autograd 仍将能够有效且正确地反向传播梯度。

在 MXNet Gluon 中使用 autograd

在这里,借助一个示例,我们将了解如何在 MXNet Gluon 中使用 autograd

实现示例

在下面的示例中,我们将实现具有两层的回归模型。实现之后,我们会使用 autograd 自动计算 loss 的梯度,参考每个权重参数 −

首先导入 autogrard 和其他需要的包,如下所示 −

from mxnet import autograd
import mxnet as mx
from mxnet.gluon.nn import HybridSequential, Dense
from mxnet.gluon.loss import L2Loss

现在,我们需要定义网络,如下所示 −

N_net = HybridSequential()
N_net.add(Dense(units=3))
N_net.add(Dense(units=1))
N_net.initialize()

现在我们需要定义 loss,如下所示 −

loss_function = L2Loss()

接下来,我们需要创建虚拟数据,如下所示 −

x = mx.nd.array([[0.5, 0.9]])
y = mx.nd.array([[1.5]])

现在,我们已准备好第一次通过网络进行前向传递。我们希望 autograd 记录计算图,以便我们可以计算梯度。为此,我们需要在 autograd.record 上下文范围内运行网络代码,如下所示 −

使用 autograd.record():
y_hat = N_net(x)
loss = loss_function(y_hat, y)

现在,我们已准备好进行反向传递,首先对感兴趣的数量调用反向方法。在我们的示例中,感兴趣的量是损失,因为我们试图根据参数 − 计算损失的梯度。

loss.backward()

现在,我们有了网络每个参数的梯度,优化器将使用这些梯度来更新参数值以提高性能。让我们检查一下第一层的梯度,如下所示 −

N_net[0].weight.grad()

输出

输出如下−

[[-0.00470527 -0.00846948]
[-0.03640365 -0.06552657]
[ 0.00800354 0.01440637]]
<NDArray 3x2 @cpu(0)>

完整实现示例

下面给出了完整的实现示例。

from mxnet import autograd
import mxnet as mx
from mxnet.gluon.nn import HybridSequential, Dense
from mxnet.gluon.loss import L2Loss
N_net = HybridSequential()
N_net.add(Dense(units=3))
N_net.add(Dense(units=1))
N_net.initialize()
loss_function = L2Loss()
x = mx.nd.array([[0.5, 0.9]])
y = mx.nd.array([[1.5]])
with autograd.record():
y_hat = N_net(x)
loss = loss_function(y_hat, y)
loss.backward()
N_net[0].weight.grad()