- "Manipulate Data with NDArray" by MXNet
- YouTube video by Thom Lane (AWS AI)
- using AI::MXNet by Sergey Kolychev

As an introduction to MXNet, this page discusses NDArray, the primary tool for storing and transforming data in MXNet.

First, we must use the module in our Perl script:

use AI::MXNet qw(mx);

which imports the AI::MXNet::NDArray module, so it is not necessary to list it separately.

To begin, let's create a two-dimensional array (better known as a "matrix"), with values: [1, 2, 3] and [5, 6, 7].

my $ndarray = nd->array([[1,2,3],[5,6,7]]);

print $ndarray->aspdl;

which yields:

[

[1 2 3]

[5 6 7]

]

Next, let's create a matrix of the same shape (two rows and three columns), but fill it with ones:

my $xx = nd->ones([2,3]);

print $xx->aspdl;

which yields:

[

[1 1 1]

[1 1 1]

]

And let's create an array and populate it with randomly sampled values. In the case below, we create an array of the same shape and populate it with uniformly distributed values between -1 and 1.

my $yy = nd->random->uniform(-1,1,[2,3]);

print $yy->aspdl;

which yields:

[

[0.097627 0.185689 0.430379]

[0.688532 0.205527 0.715891]

]

Finally, let's create one more array of the same shape and fill it with a particular value:

my $zz = nd->full([2,3],2);

print $zz->aspdl;

which yields:

[

[2 2 2]

[2 2 2]

]

To access the dimensions of each NDArray, we can call the shape method. The size method return the product of the shape components. And the dtype method returns the data type of the stored values.

print "shape: ". '['. join(",", @{$ndarray->shape}) .']'."\n";

print "size: ". $ndarray->size ."\n";

print "dtype: ". $ndarray->dtype ."\n";

which yields:

shape: [2,3]

size: 6

dtype: float32

In this section, we'll explore NDArray's support for standard mathematical operations.

We can perform element-wise multiplication:

my $zy = $zz * $yy;

print $zy->aspdl;

which yields:

[

[0.195254 0.371378 0.860757]

[ 1.37706 0.411053 1.43178]

]

Exponentiation:

my $ye = $yy->exp;

print $ye->aspdl;

which yields:

[

[1.10255 1.20405 1.53784]

[1.99079 1.22817 2.04601]

]

And we can transpose a matrix to compute a matrix-matrix product.

my $zyt = nd->dot($zz,$yy->T);

print $zyt->aspdl;

which yields:

[

[1.42739 3.2199]

[1.42739 3.2199]

]

MXNet NDArrays support slicing, so that you can access particular parts of your data. As a first example, let's return a one-dimensional array containing the element in the last row, last column:

print $yy->slice(1,2)->aspdl;

which yields:

[

[0.715891]

]

We can change that element:

$yy->slice(1,2) .= 7;

print $yy->aspdl;

which yields:

[

[0.097627 0.185689 0.430379]

[0.688532 0.205527 7]

]

We can change every value in a row:

$yy->slice(0,) .= 14;

print $yy->aspdl;

which yields:

[

[ 14
14
14]

[0.688532 0.205527
7]

]

While preparing these notes, I was unable to change every value in a column and I was unable to select a range of rows or columns. Hopefully, this bug will be fixed in a future release. In the meantime, we can work around the issue by converting betweeen NDArray and PDL.

The one thing that you must remember when working with the
Perl Data Language
is that it's **column-major**.
So instead of reading elements row-by-row into a matrix,
it reads them in column-by-column.

What this means in practice is that matrices appear transposed, so to access the second and third columns (i.e. columns 1 and 2), you would write 1:2 and follow it with a comma, so that:

print $yy->aspdl->slice('1:2,:');

returns:

[

[ 14 14]

[0.205527 7]

]

So to change the value of the second and third columns, we can convert to PDL and then back to NDArray:

{ my $tmp = $yy->aspdl;

$tmp->slice('1:2,:') .= 21;

$yy = nd->array($tmp);

}

print $yy->aspdl;

which yields:

[

[ 14
21
21]

[0.688532
21
21]

]

And similarly, we can change the values in the first two columns of the second row:

{ my $tmp = $yy->aspdl;

$tmp->slice('0:1,1') .= 42;

$yy = nd->array($tmp);

}

print $yy->aspdl;

which yields:

[

[14 21 21]

[42 42 21]

]

Copyright © 2002-2023 Eryk Wdowiak