Apache MXNet - Python API Symbol


在本章中,我们将了解 MXNet 中称为 Symbol 的接口。

Mxnet.ndarray

Apache MXNet 的 Symbol API 是一个用于符号编程的接口。 Symbol API 具有以下使用功能 −

  • 计算图

  • 减少内存使用

  • 使用前函数优化

下面给出的示例展示了如何使用 MXNet 的 Symbol API −

创建一个简单的表达式

使用常规 Python 列表中的一维和二维"数组"创建 NDArray −

import mxnet as mx
# 使用 mx.sym.variable 创建两个占位符,即 x 和 y
x = mx.sym.Variable('x')
y = mx.sym.Variable('y')
# 此处的符号使用加号"+"运算符构造。
z = x + y

输出

您将看到以下输出 −

<Symbol _plus0>

示例

(x, y, z)

输出

输出如下所示 −

(<Symbol x>, <Symbol y>, <Symbol _plus0>)

现在让我们详细讨论一下 MXNet 的 ndarray API 的类、函数和参数。

下表包含 MXNet 的 Symbol API 类 −

定义
Symbol(handle) 这个名为 symbol 的类是 Apache MXNet 的符号图。

函数及其参数

以下是 mxnet.Symbol API 中涵盖的一些重要函数及其参数 −

函数及其参数 定义
Activation([data, act_type, out, name]) 它将激活函数逐个元素应用于输入。它支持 relu、sigmoid、tanh、softrelu、softsign 激活函数。
BatchNorm([data, gamma, beta, moving_mean, …]) 它用于批量归一化。此函数通过均值和方差对数据批次进行归一化。它应用了比例gamma和偏移beta
BilinearSampler([data, grid, cudnn_off, …]) 此函数将双线性采样应用于输入特征图。实际上,它是"空间变换网络"的关键。如果您熟悉 OpenCV 中的 remap 函数,则此函数的用法与之非常相似。唯一的区别是它具有后向传递。
BlockGrad([data, out, name]) 顾名思义,此函数停止梯度计算。它基本上阻止了输入的累积梯度以向后方向流过此运算符。
cast([data, dtype, out, name]) 此函数会将输入的所有元素转换为新类型。
此函数会将输入的所有元素转换为新类型。 此函数,正如名称所指定,返回给定形状和类型的新符号,并用零填充。
ones(shape[, dtype]) 此函数,正如名称所指定,返回给定形状和类型的新符号,并用一填充。
full(shape, val[, dtype]) 此函数,正如名称所指定,返回给定形状和类型的新数组,并用给定值 val
arange(start[, stop, step, repeat, …]) 它将返回给定间隔内均匀分布的值。这些值是在半开间隔 [start, stop) 内生成的,这意味着间隔包括 start 但不包括 stop
linspace(start, stop, num[, end, name, …]) 它将返回指定间隔内均匀分布的数字。与函数arrange()类似,值是在半开区间[start,stop)内生成的,这意味着区间包括start但不包括stop
histogram(a[, bins, range]) 顾名思义,此函数将计算输入数据的直方图。
power(base, exp) 顾名思义,此函数将返回base元素的元素结果,该结果以exp元素为指数。两个输入,即base和exp,都可以是符号或标量。请注意,不允许广播。如果您想使用广播功能,可以使用 broadcast_pow
SoftmaxActivation([data, mode, name, attr, out]) 此函数将 softmax 激活应用于输入。它适用于内部层。它实际上已被弃用,我们可以改用 softmax()

实施示例

在下面的示例中,我们将使用函数 power(),它将返回以基数元素为底,以 exp 元素为幂的元素结果:

import mxnet as mx
mx.sym.power(3, 5)

输出

您将看到以下输出 −

243

示例

x = mx.sym.Variable('x')
y = mx.sym.Variable('y')
z = mx.sym.power(x, 3)
z.eval(x=mx.nd.array([1,2]))[0].asnumpy()

输出

这将产生以下输出 −

array([1., 8.], dtype=float32)

示例

z = mx.sym.power(4, y)
z.eval(y=mx.nd.array([2,3]))[0].asnumpy()

输出

执行上述代码时,您应该看到以下输出 −

array([16., 64.], dtype=float32)

示例

z = mx.sym.power(x, y)
z.eval(x=mx.nd.array([4,5]), y=mx.nd.array([2,3]))[0].asnumpy()

输出

输出如下 −

array([ 16., 125.], dtype=float32)

在下面给出的示例中,我们将使用函数 SoftmaxActivation() (或 softmax()),该函数将应用于输入并用于内部层。

input_data = mx.nd.array([[2., 0.9, -0.5, 4., 8.], [4., -.7, 9., 2., 0.9]])
soft_max_act = mx.nd.softmax(input_data)
print (soft_max_act.asnumpy())

输出

您将看到以下输出 −

[[2.4258138e-03 8.0748333e-04 1.9912292e-04 1.7924475e-02 9.7864312e-01]
[6.6843745e-03 6.0796250e-05 9.9204916e-01 9.0463174e-04 3.0112563e-04]]

symbol.contrib

Contrib NDArray API 在 symbol.contrib 包中定义。它通常为新功能提供许多有用的实验性 API。此 API 是社区可以试用新功能的地方。功能贡献者也会得到反馈。

函数及其参数

以下是 mxnet.symbol.contrib API 中涵盖的一些重要函数及其参数 −

函数及其参数 定义
rand_zipfian(true_classes, num_sampled, …) 此函数从近似 Zipfian 分布中抽取随机样本。此函数的基本分布是 Zipfian 分布。此函数随机抽样 num_sampled 个候选对象,sampled_candidates 的元素来自上面给出的基本分布。
foreach(body, data, init_states) 顾名思义,此函数在维度 0 的 NDArrays 上运行一个循环,其中包含用户定义的计算。此函数模拟 for 循环,body 具有 for 循环迭代的计算。
while_loop(cond, func, loop_vars[, …]) 顾名思义,此函数运行一个 while 循环,其中包含用户定义的计算和循环条件。此函数模拟一个 while 循环,如果条件满足,则执行自定义计算。
cond(pred, then_func, else_func) 顾名思义,此函数使用用户定义的条件和计算运行 if-then-else。此函数模拟一个 if 类分支,根据指定条件选择执行两个自定义计算之一。
getnnz([data, axis, out, name]) 此函数为我们提供稀疏张量的存储值的数量。它还包括显式零。它仅支持 CPU 上的 CSR 矩阵。
requantize([data, min_range, max_range, …]) 此函数使用在运行时计算或从校准中计算出的最小和最大阈值,将以 int32 量化的给定数据和相应的阈值重新量化为 int8。
index_copy([old_tensor, index_vector, …]) 此函数通过按索引中给出的顺序选择索引,将 new_tensor 的元素复制到 old_tensor 中。该运算符的输出将是一个新的张量,其中包含旧张量的其余元素和新张量的复制元素
interleaved_matmul_encdec_qk([queries, …]) 该运算符计算多头注意力机制中查询和键的投影之间的矩阵乘法,用作编码器-解码器。条件是输入应为查询投影的张量,其布局如下:(seq_length, batch_size, num_heads*, head_dim)。

实施示例

在下面的示例中,我们将使用函数 rand_zipfian 从近似 Zipfian 分布中抽取随机样本 −

import mxnet as mx
true_cls = mx.sym.Variable('true_cls')
samples, exp_count_true, exp_count_sample = mx.sym.contrib.rand_zipfian(true_cls, 5, 6)
samples.eval(true_cls=mx.nd.array([3]))[0].asnumpy()

输出

您将看到以下输出 −

array([4, 0, 2, 1, 5], dtype=int64)

示例

exp_count_true.eval(true_cls=mx.nd.array([3]))[0].asnumpy()

输出

输出如下 −

array([0.57336551])

示例

exp_count_sample.eval(true_cls=mx.nd.array([3]))[0].asnumpy()

输出

您将看到以下输出 −

array([1.78103594, 0.46847373, 1.04183923, 0.57336551, 1.04183923])

在下面的例子中,我们将使用函数 while_loop 来运行 while 循环,用于用户定义的计算和循环条件 −

cond = lambda i, s: i <= 7
func = lambda i, s: ([i + s], [i + 1, s + i])
loop_vars = (mx.sym.var('i'), mx.sym.var('s'))
outputs, states = mx.sym.contrib.while_loop(cond, func, loop_vars, max_iterations=10)
print(outputs)

输出

输出如下所示:

[<Symbol _while_loop0>]

示例

Print(States)

输出

这将产生以下输出 −

[<Symbol _while_loop0>, <Symbol _while_loop0>]

在下面的例子中,我们将使用函数 index_copy 将 new_tensor 的元素复制到 old_tensor 中。

import mxnet as mx
a = mx.nd.zeros((6,3))
b = mx.nd.array([[1,2,3],[4,5,6],[7,8,9]])
index = mx.nd.array([0,4,2])
mx.nd.contrib.index_copy(a, index, b)

输出

执行上述代码时,您应该看到以下输出 −

[[1. 2. 3.]
[0. 0. 0.]
[7. 8. 9.]
[0. 0. 0.]
[4. 5. 6.]
[0. 0. 0.]]
<NDArray 6x3 @cpu(0)>

symbol.image

图像符号 API 在 symbol.image 包中定义。顾名思义,它通常用于图像及其特征。

函数及其参数

以下是 mxnet.symbol.image API 中涵盖的一些重要函数及其参数 −

函数及其参数 定义
adjust_lighting([data, alpha, out, name]) 顾名思义,此函数调整输入的照明级别。它遵循 AlexNet 风格。
crop([data, x, y, width, height, out, name]) 借助此函数,我们可以将形状为 (H x W x C) 或 (N x H x W x C) 的图像 NDArray 裁剪为用户指定的大小。
normalize([data, mean, std, out, name]) 它将使用 平均值标准差 (SD) 对形状为 (C x H x W) 或 (N x C x H x W) 的张量进行归一化。
random_crop([data, xrange, yrange, width, …]) 与 crop() 类似,它随机裁剪形状为 (H x W x C) 或 (N x H x W x C) 到用户指定的大小。如果 src 小于 size,它将对结果进行上采样。
random_lighting([data, alpha_std, out, name]) 顾名思义,此函数随机添加 PCA 噪声。它也遵循 AlexNet 风格。
random_resized_crop([data, xrange, yrange, …]) 它还会将形状为 (H x W x C) 或 (N x H x W x C) 的随机 NDArray 图像裁剪为给定的大小。如果 src 小于大小,它将对结果进行上采样。它还将随机化面积和纵横比。
resize([data, size, keep_ratio, interp, …]) 顾名思义,此函数将调整形状为 (H x W x C) 或 (N x H x W x C) 的图像 NDArray 的大小,使其符合用户指定的大小。
to_tensor([data, out, name]) 它将形状为 (H x W x C) 或 (N x H x W x C) 且值在 [0, 255] 范围内的图像 NDArray 转换为形状为 (C x H x W) 或 (N x C x H x W) 且值在 [0, 1] 范围内的张量 NDArray。

实现示例

在下面的示例中,我们将使用函数 to_tensor 将形状为 (H x W x C) 或 (N x H x W x C) 且值在 [0, 255] 范围内的图像 NDArray 转换为形状为 (C x H x W) 或 (N x C x H x W) 且值在 [0, 1] 范围内的张量 NDArray。

import numpy as np

img = mx.sym.random.uniform(0, 255, (4, 2, 3)).astype(dtype=np.uint8)

mx.sym.image.to_tensor(img)

输出

输出如下所示 −

<Symbol to_tensor4>

示例

img = mx.sym.random.uniform(0, 255, (2, 4, 2, 3)).astype(dtype=np.uint8)

mx.sym.image.to_tensor(img)

输出

输出如下:

<Symbol to_tensor5>

在下面的例子中,我们将使用函数 normalize() 来规范化形状为 (C x H x W) 或 (N x C x H x W) 的张量,其值为 平均值标准差 (SD)

img = mx.sym.random.uniform(0, 1, (3, 4, 2))

mx.sym.image.normalize(img, mean=(0, 1, 2), std=(3, 2, 1))

输出

下面给出了代码的输出 −

<Symbol normalize0>

示例

img = mx.sym.random.uniform(0, 1, (2, 3, 4, 2))

mx.sym.image.normalize(img, mean=(0, 1, 2), std=(3, 2, 1))

输出

输出如下所示 −

<Symbol normalize1>

symbol.random

随机符号 API 在 symbol.random 包中定义。顾名思义,它是 MXNet 的随机分布生成器 Symbol API。

函数及其参数

以下是 mxnet.symbol.random API 中涵盖的一些重要函数及其参数 −

函数及其参数 定义
uniform([low, high, shape, dtype, ctx, out]) 它从均匀分布中生成随机样本。
normal([loc, scale, shape, dtype, ctx, out]) 它从正态(高斯)中生成随机样本分布。
randn(*shape, **kwargs) 它从正态(高斯)分布中生成随机样本。
poisson([lam, shape, dtype, ctx, out]) 它从泊松分布中生成随机样本。
exponential([scale, shape, dtype, ctx, out]) 它从指数分布中生成样本。
gamma([alpha, beta, shape, dtype, ctx, out]) 它从伽马分布中生成随机样本。
multinomial(data[, shape, get_prob, out, dtype]) 它从多个多项分布中生成并发采样。
negative_binomial([k, p, shape, dtype, ctx, out]) 它从负二项分布中生成随机样本。
generalized_negative_binomial([mu, alpha, …]) 它从广义负二项分布中生成随机样本。
shuffle(data, **kwargs) 它随机打乱元素。
randint(low, high[, shape, dtype, ctx, out]) 它从离散均匀分布中生成随机样本。
exponential_like([data, lam, out, name]) 它根据输入数组形状从指数分布中生成随机样本。
gamma_like([data, alpha, beta, out, name]) 它根据输入数组形状从伽马分布中生成随机样本。
generalized_negative_binomial_like([data, …]) 它根据输入数组形状从广义负二项分布中生成随机样本。
negative_binomial_like([data, k, p, out, name]) 根据输入数组形状,从负二项分布生成随机样本。
normal_like([data, loc, scale, out, name]) 根据输入数组形状,从正态(高斯)分布生成随机样本。
poisson_like([data, lam, out, name]) 根据输入数组形状,从泊松分布生成随机样本。
uniform_like([data, low, high, out, name]) 根据输入数组形状,从均匀分布生成随机样本。

实施示例

在下面的示例中,我们将使用 shuffle() 函数随机打乱元素顺序。它将沿着第一个轴打乱数组顺序。

data = mx.nd.array([[0, 1, 2], [3, 4, 5], [6, 7, 8],[9,10,11]])
x = mx.sym.Variable('x')
y = mx.sym.random.shuffle(x)
y.eval(x=data)

输出

您将看到以下输出:

[
[[ 9. 10. 11.]
[ 0. 1. 2.]
[ 6. 7. 8.]
[ 3. 4. 5.]]
<NDArray 4x3 @cpu(0)>]

示例

y.eval(x=data)

输出

执行上述代码时,您应该看到以下输出 −

[
[[ 6. 7. 8.]
[ 0. 1. 2.]
[ 3. 4. 5.]
[ 9. 10. 11.]]
<NDArray 4x3 @cpu(0)>]

在下面的例子中,我们将从广义负二项分布中抽取随机样本。为此将使用函数 generalized_negative_binomial()

mx.sym.random.generalized_negative_binomial(10, 0.1)

输出

输出概要 −

<Symbol _random_generalized_negative_binomial0>

symbol.sparse

稀疏符号 API 在 mxnet.symbol.sparse 包中定义。顾名思义,它提供稀疏神经网络图和 CPU 上的自动微分。

函数及其参数

以下是 mxnet.symbol.sparse API 涵盖的一些重要函数(包括符号创建例程、符号操作例程、数学函数、三角函数、双曲函数、归约函数、舍入、幂、神经网络)及其参数 −

函数及其参数 定义
ElementWiseSum(*args, **kwargs) 此函数将按元素添加所有输入参数。例如,𝑎𝑑𝑑_𝑛(𝑎1,𝑎2,…𝑎𝑛=𝑎1+𝑎2+⋯+𝑎𝑛)。在这里,我们可以看到 add_n 可能比调用 add n 次更有效率。
Embedding([data, weight, input_dim, …]) 它将整数索引映射到向量表示,即嵌入。它实际上将单词映射到高维空间中的实值向量,这称为词嵌入。
LinearRegressionOutput([data, label, …]) 它计算并优化反向传播期间的平方损失,在正向传播期间仅提供输出数据。
LogisticRegressionOutput([data, label, …]) 将逻辑函数(也称为 S 型函数)应用于输入。该函数计算为 1/1+exp (−x)。
MAERegressionOutput([data, label, …]) 此运算符计算输入的平均绝对误差。 MAE实际上是一个对应于绝对误差期望值的风险度量。
abs([data, name, attr, out]) 顾名思义,此函数将返回输入的元素绝对值。
adagrad_update([weight, grad, history, lr, …]) 它是AdaGrad优化器的更新函数。
adam_update([weight, grad, mean, var, lr, …]) 它是Adam优化器的更新函数。
add_n(*args, **kwargs) 顾名思义,它将逐元素添加所有输入参数。
arccos([data, name, attr, out]) 此函数将返回输入数组的逐元素反余弦。
dot([lhs, rhs, transpose_a, transpose_b, …]) 顾名思义,它将给出两个数组的点积。它将取决于输入数组的维度: 1-D:向量的内积 2-D:矩阵乘法 N-D:第一个输入的最后一个轴与第二个输入的第一个轴的和积。
elemwise_add([lhs, rhs, name, attr, out]) 顾名思义,它将逐元素添加参数。
elemwise_div([lhs, rhs, name, attr, out]) 顾名思义,它将逐元素除以参数。
elemwise_mul([lhs, rhs, name, attr, out]) 顾名思义,它将乘以参数元素。
elemwise_sub([lhs, rhs, name, attr, out]) 顾名思义,它将逐个元素减去参数。
exp([data, name, attr, out]) 此函数将返回给定输入的元素指数值。
sgd_update([weight, grad, lr, wd, …]) 它充当随机梯度下降优化器的更新函数。
sigmoid([data, name, attr, out]) 顾名思义,它将计算 x 元素的 sigmoid
sign([data, name, attr, out]) 它将返回给定输入的元素符号。
sin([data, name, attr, out]) 顾名思义,此函数将计算给定输入数组的元素正弦。

实施示例

在下面的示例中,我们将使用 ElementWiseSum() 函数随机打乱元素。它将整数索引映射到向量表示,即词嵌入。

input_dim = 4
output_dim = 5

示例

/* Here every row in weight matrix y represents a word. So, y = (w0,w1,w2,w3)
y = [[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.]]
/* Here input array x represents n-grams(2-gram). So, x = [(w1,w3), (w0,w2)]
x = [[ 1., 3.],
[ 0., 2.]]
/* Now, Mapped input x to its vector representation y.
Embedding(x, y, 4, 5) = [[[ 5., 6., 7., 8., 9.],
[ 15., 16., 17., 18., 19.]],
[[ 0., 1., 2., 3., 4.],
[ 10., 11., 12., 13., 14.]]]