AI-MXNet
view release on metacpan or search on metacpan
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
Returns a reshaped NDArray that shares the memory with current one.
One shape dimension can be -1. In this case, the value is inferred
from the length of the array and remaining dimensions.
Parameters
----------
new_shape : Shape
new shape of NDArray
=cut
method reshape(ArrayRef[Int] $new_shape)
{
my $i = -1;
my @inferred = map { $i++; $_ == -1 ? ($i) : () } @$new_shape;
assert((@inferred <= 1), 'Only one dimension can be inferred.');
if(@inferred)
{
$new_shape->[$inferred[0]] = product(@{ $self->shape })/product(map { abs($_) } @{ $new_shape });
}
my $handle = check_call(
AI::MXNetCAPI::NDArrayReshape(
$self->handle,
scalar(@$new_shape),
$new_shape
)
);
return __PACKAGE__->new(handle => $handle, writable => $self->writable);
}
=head2 ndim
Returns the number of dimensions of this array.
=cut
method ndim()
{
scalar(@{ $self->shape });
}
=head2 moveaxis
Moves the 'source' axis into the 'destination' position
while leaving the other axes in their original order
Parameters
----------
source : int
Original position of the axes to move.
destination : int
Destination position for each of the original axes.
Returns
-------
result :NDArray
Array with moved axes.
Examples
--------
> $X = mx->nd->array([[1, 2, 3],
[4, 5, 6]]);
> print Dumper($X->moveaxis(0, 1)->shape)
> [3, 2]
=cut
method moveaxis(Int $source, Int $dest)
{
my @axes = 0..$self->ndim-1;
$source += @axes if $source < 0;
$dest += @axes if $dest < 0;
assert($source < @axes);
assert($dest < @axes);
my ($to_move) = splice(@axes, $source, 1);
splice(@axes, $dest, 0, $to_move);
return __PACKAGE__->transpose($self, \@axes);
}
=head2 broadcast_to
Broadcasting the current NDArray into the given shape.
Parameters
---------
Shape $shape : the shape to broadcast
=cut
method broadcast_to(Shape $shape)
{
my $cur_shape = $self->shape;
my $err_str = "operands could not be broadcast together with remapped shapes"
."[original->remapped]: [@$cur_shape] and requested shape [@$shape]";
if(@$shape < @$cur_shape)
{
confess($err_str);
}
@$cur_shape = ((1)x(@$shape - @$cur_shape), @$cur_shape);
my $cur_shape_arr = pdl($cur_shape);
my $broadcasting_axes = ($cur_shape_arr != pdl($shape))->which->unpdl;
if (grep { $cur_shape->[$_] != 1 } @$broadcasting_axes)
{
confess($err_str);
}
if(join(',',@$cur_shape) ne join(',',@{ $self->shape }))
{
return __PACKAGE__->SUPER::broadcast_to($self->reshape($cur_shape),{ shape => $shape });
}
else
{
return __PACKAGE__->SUPER::broadcast_to($self, { shape => $shape });
}
}
=head2 wait_to_read
Block until all pending write operations on the NDArray are finished.
This function will return when all the pending writes to the current
NDArray are finished. There can be pending reads going on when the
function returns.
=cut
method wait_to_read()
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
{
return __PACKAGE__->_onehot_encode($indices, $out, { out => $out });
}
=head2 _ufunc_helper(lhs, rhs, fn_array, lfn_scalar, rfn_scalar):
Helper function for element-wise operation
The function will perform numpy-like broadcasting if needed and call different functions
Parameters
----------
lhs : NDArray or numeric value
left hand side operand
rhs : NDArray or numeric value
right hand side operand
fn_array : function
function to be called if both lhs and rhs are of NDArray type
lfn_scalar : function
function to be called if lhs is NDArray while rhs is numeric value
rfn_scalar : function
function to be called if lhs is numeric value while rhs is NDArray;
if none is provided, then the function is commutative, so rfn_scalar is equal to lfn_scalar
Returns
-------
out: NDArray
result array
=cut
sub _ufunc_helper
{
my ($lhs, $rhs, $fn_array, $lfn_scalar, $rfn_scalar, $reverse) = @_;
($rhs, $lhs) = ($lhs, $rhs) if $reverse and $rfn_scalar;
if(not ref $lhs)
{
if(not $rfn_scalar)
{
return __PACKAGE__->can($lfn_scalar)->(__PACKAGE__, $rhs, $lhs);
}
else
{
return __PACKAGE__->can($rfn_scalar)->(__PACKAGE__, $rhs, $lhs);
}
}
elsif(not ref $rhs)
{
return __PACKAGE__->can($lfn_scalar)->(__PACKAGE__, $lhs, $rhs);
}
else
{
return __PACKAGE__->can($fn_array)->(__PACKAGE__, $lhs, $rhs);
}
}
method stringify($other=, $reverse=)
{
sprintf("<%s %s @%s>", ref($self), join('x', @{ $self->shape }), $self->context);
}
method iadd(AI::MXNet::NDArray|Num $other, $reverse=)
{
confess('trying to add to a readonly NDArray') unless $self->writable;
return ref $other
? __PACKAGE__->broadcast_add($self, $other, { out => $self })
: __PACKAGE__->_plus_scalar($self, $other, { out => $self })
}
method add(AI::MXNet::NDArray|Num $other, $reverse=)
{
return _ufunc_helper(
$self,
$other,
qw/broadcast_add _plus_scalar/
);
}
method subtract(AI::MXNet::NDArray|Num $other, $reverse=)
{
return _ufunc_helper(
$self,
$other,
qw/broadcast_sub _minus_scalar _rminus_scalar/,
$reverse
);
}
method isubtract(AI::MXNet::NDArray|Num $other, $reverse=)
{
confess('trying to add to a readonly NDArray') unless $self->writable;
return ref $other
? __PACKAGE__->broadcast_sub($self, $other, { out => $self })
: __PACKAGE__->_minus_scalar($self, $other, { out => $self })
}
method multiply(AI::MXNet::NDArray|Num $other, $reverse=)
{
return _ufunc_helper(
$self,
$other,
qw/broadcast_mul _mul_scalar/
);
}
method imultiply(AI::MXNet::NDArray|Num $other, $reverse=)
{
confess('trying to add to a readonly NDArray') unless $self->writable;
return ref $other
? __PACKAGE__->broadcast_mul($self, $other, { out => $self })
: __PACKAGE__->_mul_scalar($self, $other, { out => $self })
}
method divide(AI::MXNet::NDArray|Num $other, $reverse=)
{
return _ufunc_helper(
$self,
$other,
( run in 0.709 second using v1.01-cache-2.11-cpan-39bf76dae61 )