Manipulate Data with NDArray

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.

getting started

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

operations

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]
]

indexing

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.

converting between 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-2024 Eryk Wdowiak