Skip to content

Apache MXNet - Python API gluon

The MXNet Gluon API provides a user-friendly, imperative interface for designing, training, and deploying deep learning models. It combines the ease of use of dynamic frameworks with the performance of symbolic execution through its hybrid capabilities.

This chapter explores key modules within the mxnet.gluon package.

The mxnet.gluon.nn module is central to model building, offering a rich collection of pre-defined neural network layers.

Some important classes in gluon.nn:

Class NameDescription
Block([prefix, params])The base class for all neural network layers and models in Gluon. Custom models are built by subclassing Block.
HybridBlock([prefix, params])A subclass of Block that supports both imperative execution and symbolic graph compilation (hybridization) for performance optimization.
Sequential([prefix, params])A container for stacking layers sequentially. HybridSequential is its hybrid counterpart.
Dense(units, activation=None, use_bias=True, ...)A standard fully connected (dense) layer.
Conv1D, Conv2D, Conv3D1D, 2D, and 3D convolution layers, respectively. Parameters include channels, kernel_size, strides, padding, activation.
Conv*DTransposeTransposed convolution layers (often called deconvolution layers) for upsampling.
Activation(activation_type)Applies a specified activation function (e.g., ‘relu’, ‘sigmoid’, ‘tanh’).
BatchNorm([axis, momentum, epsilon, ...])Batch normalization layer to stabilize training and improve generalization.
Dropout(rate, axes=())Applies dropout regularization to prevent overfitting.
Embedding(input_dim, output_dim, ...)A lookup table that maps integer indices (e.g., word IDs) to dense vector embeddings.
Flatten()Flattens the input into a 2D array by collapsing all dimensions except the first (batch dimension).
Pool*D (e.g., MaxPool2D, AvgPool2D)Pooling layers (max, average) for downsampling feature maps.
GlobalPool*D (e.g., GlobalAvgPool2D)Global pooling layers that reduce each feature map to a single value.

Implementation Examples: Block and HybridBlock

Section titled “Implementation Examples: Block and HybridBlock”

Defining a custom model using gluon.nn.Block:

import mxnet as mx
from mxnet import nd, gluon
from mxnet.gluon import nn
class SimpleModel(nn.Block):
def __init__(self, **kwargs):
super(SimpleModel, self).__init__(**kwargs)
with self.name_scope(): # Organizes parameter names
self.dense0 = nn.Dense(20)
self.dense1 = nn.Dense(20)
def forward(self, x):
x = nd.relu(self.dense0(x))
return nd.relu(self.dense1(x))
model_block = SimpleModel()
model_block.initialize(ctx=mx.cpu()) # Initialize parameters
output_block = model_block(nd.zeros((5, 10), ctx=mx.cpu())) # Pass dummy data
print("Output from SimpleModel (Block):")
print(output_block.asnumpy())

Output (all zeros due to ReLU and likely zero-init or small init for first pass):

Output from SimpleModel (Block):
[[0. 0. ... 0. 0.]
[0. 0. ... 0. 0.]
...
[0. 0. ... 0. 0.]
[0. 0. ... 0. 0.]] (Shape: 5x20)

Defining a custom model using gluon.nn.HybridBlock for potential symbolic optimization:

class HybridSimpleModel(nn.HybridBlock):
def __init__(self, **kwargs):
super(HybridSimpleModel, self).__init__(**kwargs)
with self.name_scope():
self.dense0 = nn.Dense(30)
self.dense1 = nn.Dense(30)
def hybrid_forward(self, F, x):
# F is mx.nd or mx.sym depending on whether hybridized
x = F.relu(self.dense0(x))
return F.relu(self.dense1(x))
model_hybrid = HybridSimpleModel()
model_hybrid.initialize(ctx=mx.cpu())
# Run imperatively first
output_hybrid_imperative = model_hybrid(nd.zeros((5, 15), ctx=mx.cpu()))
print("\nOutput from HybridSimpleModel (imperative):")
print(output_hybrid_imperative.asnumpy())
# Hybridize the model (convert to symbolic graph for subsequent calls)
model_hybrid.hybridize()
output_hybrid_symbolic = model_hybrid(nd.zeros((5, 15), ctx=mx.cpu()))
print("\nOutput from HybridSimpleModel (hybridized/symbolic):")
print(output_hybrid_symbolic.asnumpy())

Output (shapes 5x30, values likely zeros):

Output from HybridSimpleModel (imperative):
[[0. 0. ... 0. 0.]
...
[0. 0. ... 0. 0.]]
Output from HybridSimpleModel (hybridized/symbolic):
[[0. 0. ... 0. 0.]
...
[0. 0. ... 0. 0.]]

gluon.rnn: Recurrent Neural Network Layers

Section titled “gluon.rnn: Recurrent Neural Network Layers”

The mxnet.gluon.rnn module provides layers for building recurrent neural networks (RNNs), suitable for sequence data processing.

Class NameDescription
RNNCell (Base class)Abstract base class for RNN cells.
RNN(hidden_size, num_layers, activation='relu', ...)A multi-layer Elman RNN. activation can be ‘tanh’ or ‘relu’.
LSTMCell(hidden_size, ...)A Long Short-Term Memory (LSTM) cell.
LSTM(hidden_size, num_layers, ...)A multi-layer LSTM network.
GRUCell(hidden_size, ...)A Gated Recurrent Unit (GRU) cell.
GRU(hidden_size, num_layers, ...)A multi-layer GRU network.
BidirectionalCell(l_cell, r_cell)Wraps two cells to create a bidirectional recurrent layer.
DropoutCell(rate, ...)Applies dropout to the inputs or outputs of a recurrent cell.

Using gluon.rnn.GRU:

gru_layer = gluon.rnn.GRU(hidden_size=100, num_layers=2)
gru_layer.initialize()
# Input sequence: (sequence_length, batch_size, input_feature_dim)
input_seq_gru = nd.random.uniform(shape=(5, 3, 10))
# Forward pass without initial state (defaults to zeros)
output_seq_gru, last_states_gru = gru_layer(input_seq_gru)
print("GRU Output sequence shape:", output_seq_gru.shape)
print("GRU Last hidden states shape:", last_states_gru[0].shape) # GRU state is a list containing one tensor

Output:

GRU Output sequence shape: (5, 3, 100)
GRU Last hidden states shape: (2, 3, 100) (num_layers, batch_size, hidden_size)

Using gluon.rnn.LSTM:

lstm_layer = gluon.rnn.LSTM(hidden_size=120, num_layers=1)
lstm_layer.initialize()
input_seq_lstm = nd.random.uniform(shape=(8, 4, 20))
# LSTM requires a list of initial states: [initial_hidden_state, initial_cell_state]
# Shapes: (num_layers, batch_size, hidden_size)
initial_h_lstm = nd.zeros((1, 4, 120))
initial_c_lstm = nd.zeros((1, 4, 120))
initial_states_lstm = [initial_h_lstm, initial_c_lstm]
output_seq_lstm, last_states_lstm_tuple = lstm_layer(input_seq_lstm, initial_states_lstm)
print("\nLSTM Output sequence shape:", output_seq_lstm.shape)
print("LSTM Last hidden state shape:", last_states_lstm_tuple[0].shape)
print("LSTM Last cell state shape:", last_states_lstm_tuple[1].shape)

Output:

LSTM Output sequence shape: (8, 4, 120)
LSTM Last hidden state shape: (1, 4, 120)
LSTM Last cell state shape: (1, 4, 120)

Modules essential for the training process in Gluon:

The mxnet.gluon.loss (often aliased as gloss) module provides various predefined loss functions used to evaluate model performance and compute gradients for training.

Class NameDescription
Loss (Base class)Base class for all loss functions.
L2Loss()Calculates Mean Squared Error (MSE): 0.5 * sum((pred - label)^2) / N. The 0.5 factor is common for convenience in derivatives.
L1Loss()Calculates Mean Absolute Error (MAE): sum(|pred - label|) / N.
SigmoidBinaryCrossEntropyLoss()Computes cross-entropy loss for binary classification problems. Applies sigmoid to predictions first if from_sigmoid=False (default).
SoftmaxCrossEntropyLoss()Computes cross-entropy loss for multi-class classification. Applies softmax to predictions by default.
KLDivLoss()Computes Kullback-Leibler divergence loss.
CTCLoss()Connectionist Temporal Classification loss, used in sequence-to-sequence tasks like speech recognition.
HuberLoss()A robust loss function that is quadratic for small errors and linear for large errors (less sensitive to outliers than L2Loss).

For example, L2Loss (Mean Squared Error) is calculated as the average of the squared differences between predictions (pred) and true labels (label). A common formulation is L = (1/N) * sum_i (pred_i - label_i)^2, where N is the number of samples or elements. Gluon’s L2Loss might use 0.5 * sum(...) / batch_size by default.

mxnet.gluon.Parameter is a container class that holds the learnable parameters (weights and biases) of Blocks. It manages their data, gradients, initialization, and context (CPU/GPU).

MethodDescription
data(ctx=None)Returns the parameter’s data NDArray on the specified context (or default context).
grad(ctx=None)Returns the parameter’s gradient NDArray on the specified context.
initialize(init=None, ctx=None, default_init=init.Uniform(), force_reinit=False)Initializes the parameter’s data and gradient arrays on specified context(s).
list_data()Returns a list of data NDArrays, one for each context the parameter is initialized on.
list_grad()Returns a list of gradient NDArrays, one for each context.
zero_grad()Sets the gradient buffers on all contexts to zero. Called before backward() in a typical training loop if gradients accumulate.

Example: Creating and initializing a parameter.

weight_param = gluon.Parameter('my_weight', shape=(2, 2), init=mx.init.Normal(0.1))
weight_param.initialize(ctx=mx.cpu(0))
print("Initialized weight_param data:")
print(weight_param.data().asnumpy())
print("\nInitialized weight_param grad (should be zeros):")
print(weight_param.grad().asnumpy())

Output (data values random, grads zero):

Initialized weight_param data:
[[-0.09423235 0.04523997]
[-0.00682008 0.10888068]]
Initialized weight_param grad (should be zeros):
[[0. 0.]
[0. 0.]]

The mxnet.gluon.Trainer class simplifies the process of updating model parameters using an optimizer (e.g., SGD, Adam) and computed gradients.

MethodDescription
Trainer(params, optimizer, optimizer_params=None, kvstore=None, ...)Constructor. params is a collection of parameters (e.g., from net.collect_params()). optimizer is the name of an optimizer (e.g., ‘sgd’, ‘adam’) or an mx.optimizer.Optimizer instance.
step(batch_size, ignore_stale_grad=False)Performs one step of parameter update. This should be called after loss.backward() and outside an autograd.record() scope. It scales gradients by 1.0/batch_size before applying the optimizer update.
set_learning_rate(lr)Updates the learning rate of the optimizer.
save_states(fname) / load_states(fname)Saves/loads the trainer’s state (e.g., optimizer moments), useful for resuming training.

A typical training loop snippet:

# net = SimpleModel() or HybridSimpleModel()
# net.initialize()
# loss_fn = gluon.loss.L2Loss()
# trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': 0.1})
# x_batch, y_batch = ... # get a batch of data
# with autograd.record():
# predictions = net(x_batch)
# loss_value = loss_fn(predictions, y_batch)
# loss_value.backward() # Compute gradients
# trainer.step(batch_size) # Update parameters

Gluon provides utilities for loading and managing datasets efficiently.

The mxnet.gluon.data module offers tools for creating, transforming, and loading data in mini-batches.

Class NameDescription
Dataset (Abstract class)Base class for datasets. Custom datasets should inherit from this.
ArrayDataset(*args)A dataset created from one or more NDArrays or NumPy arrays. Each argument is treated as a component of a sample (e.g., data, label).
Sampler (Base class)Base class for strategies to sample indices from a dataset.
SequentialSampler(length)Samples elements sequentially from 0 to length-1.
RandomSampler(length)Samples elements randomly without replacement.
BatchSampler(sampler, batch_size, last_batch='keep')Wraps another sampler to yield mini-batches of indices.
DataLoader(dataset, batch_size=None, shuffle=False, sampler=None, batch_sampler=None, num_workers=0, ...)Loads data from a Dataset in mini-batches. Handles shuffling, parallel loading using num_workers.

Example: Using ArrayDataset and DataLoader:

num_samples = 100
features = nd.random.normal(shape=(num_samples, 10))
labels = nd.random.uniform(shape=(num_samples, 1))
# Create a dataset from features and labels
dataset = gluon.data.ArrayDataset(features, labels)
# Create a DataLoader to iterate over mini-batches
batch_size = 10
data_loader = gluon.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)
# Iterate over the data_loader in a training loop
# for i, (data_batch, label_batch) in enumerate(data_loader):
# print(f"Batch {i}: data shape {data_batch.shape}, label shape {label_batch.shape}")
# if i == 1: break # Show first two batches
print(f"DataLoader created for {len(dataset)} samples with batch_size {batch_size}.")

gluon.data.vision.datasets: Vision Datasets

Section titled “gluon.data.vision.datasets: Vision Datasets”

This module provides convenient access to common computer vision datasets.

Class NameDescription
MNIST([root, train, transform])MNIST handwritten digits dataset.
FashionMNIST([root, train, transform])Fashion-MNIST dataset (drop-in replacement for MNIST).
CIFAR10([root, train, transform])CIFAR-10 image classification dataset (10 classes).
CIFAR100([root, fine_label, train, transform])CIFAR-100 image classification dataset (100 classes).
ImageRecordDataset(filename, ...)Dataset from images stored in MXNet’s RecordIO (.rec) format.
ImageFolderDataset(root, ...)Dataset from images stored in a folder structure (e.g., root/class_name/image.jpg).
ImageListDataset(root, imglistfile, ...)Dataset from images specified in a list file (.lst).

Example of ImageListDataset file format (.lst): Each line typically index\tlabel\tpath_to_image

# Example content of an image_list.lst file:
# 0<tab>0<tab>path/to/cat_image_001.jpg
# 1<tab>0<tab>path/to/cat_image_002.jpg
# 2<tab>1<tab>path/to/dog_image_001.jpg
# ... (index, label, image_path)

Gluon also includes utility functions for various tasks.

The mxnet.gluon.utils module contains helper functions, particularly for data parallelism and file handling.

FunctionDescription
split_data(data, num_slice, batch_axis=0, ...)Splits an NDArray (or list of NDArrays) into num_slice slices along batch_axis. Does not move data to contexts.
split_and_load(data, ctx_list, batch_axis=0, ...)Splits data similar to split_data and then loads each slice onto a corresponding context in ctx_list. Essential for multi-GPU training on a single machine.
clip_global_norm(arrays, max_norm, ...)Rescales a list of NDArrays (typically gradients) so that their total L2 norm is less than or equal to max_norm. Helps prevent exploding gradients.
download(url, path=None, overwrite=False, sha1_hash=None, ...)Downloads a file from a URL. Can verify integrity using sha1_hash.