Apache MXNet - Python 包


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

重要的 MXNet Python 包

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

  • Autograd(自动微分)

  • ND阵列

  • KV商店

  • 胶子

  • 可视化

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

自动梯度

Autograd代表自动微分,用于将梯度从损失度量反向传播回每个参数。与反向传播一起,它使用动态编程方法来有效计算梯度。也称为反向模式自动微分。该技术在许多参数影响单个损耗指标的“扇入”情况下非常有效。

什么是梯度?

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

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

梯度图

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

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

如何计算梯度?

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

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

  • 有限差分- 另一种选择是使用有限差分,尝试每个参数上的细微差异并查看损失度量如何响应。该方法的缺点是计算量大且数值精度较差。

  • 自动微分- 上述方法缺点的解决方案是,使用自动微分将梯度从损失度量反向传播回每个参数。传播使我们能够采用动态编程方法来有效计算梯度。这种方法也称为反向模式自动微分。

自动微分(autograd)

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

第 1 阶段- 此阶段称为训练的“前向传递”。顾名思义,在此阶段,它创建网络用来进行预测和计算损失度量的运算符的记录。

第 2 阶段- 此阶段称为训练的“向后传递” 。顾名思义,在这个阶段,它会向后遍历该记录。向后看,它评估每个算子的偏导数,一直回到网络参数。

自动微分

Autograd 的优点

以下是使用自动微分(autograd)的优点 -

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

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

  • 高效- Autogard 非常有效地计算梯度。

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

在 MXNet Gluon 中使用 autograd

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

实施例

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

首先导入 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_function = L2Loss()

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

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

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

with 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()