view release on metacpan or search on metacpan
examples/char_lstm.pl view on Meta::CPAN
with optional inferred sampling (RNN generates Shakespeare like text)
=head1 SYNOPSIS
--num-layers number of stacked RNN layers, default=2
--num-hidden hidden layer size, default=256
--num-embed embed size, default=10
--num-seq sequence size, default=60
--gpus list of gpus to run, e.g. 0 or 0,2,5. empty means using cpu.
Increase batch size when using multiple gpus for best performance.
--kv-store key-value store type, default='device'
--num-epochs max num of epochs, default=25
--lr initial learning rate, default=0.01
--optimizer the optimizer type, default='adam'
--mom momentum for sgd, default=0.0
--wd weight decay for sgd, default=0.00001
--batch-size the batch size type, default=32
--bidirectional use bidirectional cell, default false (0)
--disp-batches show progress for every n batches, default=50
--chkp-prefix prefix for checkpoint files, default='lstm_'
--cell-mode RNN cell mode (LSTM, GRU, RNN, default=LSTM)
--sample-size a size of inferred sample text (default=10000) after each epoch
--chkp-epoch save checkpoint after this many epoch, default=1 (saving every checkpoint)
=cut
package AI::MXNet::RNN::IO::ASCIIIterator;
use Mouse;
extends AI::MXNet::DataIter;
has 'data' => (is => 'ro', isa => 'PDL', required => 1);
has 'seq_size' => (is => 'ro', isa => 'Int', required => 1);
has '+batch_size' => (is => 'ro', isa => 'Int', required => 1);
has 'data_name' => (is => 'ro', isa => 'Str', default => 'data');
has 'label_name' => (is => 'ro', isa => 'Str', default => 'softmax_label');
has 'dtype' => (is => 'ro', isa => 'Dtype', default => 'float32');
has [qw/nd counter seq_counter vocab_size
data_size provide_data provide_label idx/] => (is => 'rw', init_arg => undef);
sub BUILD
{
my $self = shift;
$self->data_size($self->data->nelem);
my $segments = int(($self->data_size-$self->seq_size)/($self->batch_size*$self->seq_size));
$self->idx([0..$segments-1]);
$self->vocab_size($self->data->uniq->shape->at(0));
$self->counter(0);
$self->seq_counter(0);
$self->nd(mx->nd->array($self->data, dtype => $self->dtype));
my $shape = [$self->batch_size, $self->seq_size];
$self->provide_data([
AI::MXNet::DataDesc->new(
name => $self->data_name,
shape => $shape,
dtype => $self->dtype
)
]);
$self->provide_label([
AI::MXNet::DataDesc->new(
name => $self->label_name,
shape => $shape,
dtype => $self->dtype
)
]);
$self->reset;
}
method reset()
{
$self->counter(0);
@{ $self->idx } = List::Util::shuffle(@{ $self->idx });
}
examples/char_lstm.pl view on Meta::CPAN
$self->counter($self->counter + 1);
$self->seq_counter(0);
}
return AI::MXNet::DataBatch->new(
data => [$data],
label => [$label],
provide_data => [
AI::MXNet::DataDesc->new(
name => $self->data_name,
shape => $data->shape,
dtype => $self->dtype
)
],
provide_label => [
AI::MXNet::DataDesc->new(
name => $self->label_name,
shape => $label->shape,
dtype => $self->dtype
)
],
);
}
package main;
my $file = "data/input.txt";
open(F, $file) or die "can't open $file: $!";
my $fdata;
{ local($/) = undef; $fdata = <F>; close(F) };
examples/char_lstm.pl view on Meta::CPAN
kvstore => $kv_store,
optimizer => $optimizer,
optimizer_params => {
learning_rate => $lr,
momentum => $mom,
wd => $wd,
clip_gradient => 5,
rescale_grad => 1/$batch_size,
lr_scheduler => AI::MXNet::FactorScheduler->new(step => 1000, factor => 0.99)
},
initializer => mx->init->Xavier(factor_type => "in", magnitude => 2.34),
num_epoch => $num_epoch,
batch_end_callback => mx->callback->Speedometer($batch_size, $disp_batches),
($chkp_epoch ? (epoch_end_callback => [mx->rnn->do_rnn_checkpoint($stack, $chkp_prefix, $chkp_epoch), \&sample]) : ())
);
sub sample {
return if not $sample_size;
$model->reshape(data_shapes=>[['data',[1, $seq_size]]], label_shapes=>[['softmax_label',[1, $seq_size]]]);
my $input = mx->nd->array($fdata->slice([0, $seq_size-1]))->reshape([1, $seq_size]);
$| = 1;
examples/cudnn_lstm_bucketing.pl view on Meta::CPAN
char_lstm.pl - Example of training char LSTM RNN on tiny shakespeare using high level RNN interface
=head1 SYNOPSIS
--test Whether to test or train (default 0)
--num-layers number of stacked RNN layers, default=2
--num-hidden hidden layer size, default=200
--num-seq sequence size, default=32
--gpus list of gpus to run, e.g. 0 or 0,2,5. empty means using cpu.
Increase batch size when using multiple gpus for best performance.
--kv-store key-value store type, default='device'
--num-epochs max num of epochs, default=25
--lr initial learning rate, default=0.01
--optimizer the optimizer type, default='adam'
--mom momentum for sgd, default=0.0
--wd weight decay for sgd, default=0.00001
--batch-size the batch size type, default=32
--disp-batches show progress for every n batches, default=50
--model-prefix prefix for checkpoint files for loading/saving, default='lstm_'
--load-epoch load from epoch
--stack-rnn stack rnn to reduce communication overhead (1,0 default 0)
--bidirectional whether to use bidirectional layers (1,0 default 0)
--dropout dropout probability (1.0 - keep probability), default 0
=cut
$bidirectional = $bidirectional ? 1 : 0;
$stack_rnn = $stack_rnn ? 1 : 0;
examples/cudnn_lstm_bucketing.pl view on Meta::CPAN
eval_data => $data_val,
eval_metric => mx->metric->Perplexity($invalid_label),
kvstore => $kv_store,
optimizer => $optimizer,
optimizer_params => {
learning_rate => $lr,
momentum => $mom,
wd => $wd,
},
begin_epoch => $load_epoch,
initializer => mx->init->Xavier(factor_type => "in", magnitude => 2.34),
num_epoch => $num_epoch,
batch_end_callback => mx->callback->Speedometer($batch_size, $disp_batches),
($model_prefix ? (epoch_end_callback => mx->rnn->do_rnn_checkpoint($cell, $model_prefix, 1)) : ())
);
};
my $test = sub {
assert($model_prefix, "Must specifiy path to load from");
my (undef, $data_val, $vocab) = get_data('NT');
my $stack;
examples/lstm_bucketing.pl view on Meta::CPAN
lstm_bucketing.pl - Example of training LSTM RNN on Penn Tree Bank data using high level RNN interface
=head1 SYNOPSIS
--num-layers number of stacked RNN layers, default=2
--num-hidden hidden layer size, default=200
--num-embed embedding layer size, default=200
--gpus list of gpus to run, e.g. 0 or 0,2,5. empty means using cpu.
Increase batch size when using multiple gpus for best performance.
--kv-store key-value store type, default='device'
--num-epochs max num of epochs, default=25
--lr initial learning rate, default=0.01
--optimizer the optimizer type, default='sgd'
--mom momentum for sgd, default=0.0
--wd weight decay for sgd, default=0.00001
--batch-size the batch size type, default=32
--disp-batches show progress for every n batches, default=50
--chkp-prefix prefix for checkpoint files, default='lstm_'
--chkp-epoch save checkpoint after this many epoch, default=0 (saving checkpoints is disabled)
=cut
func tokenize_text($fname, :$vocab=, :$invalid_label=-1, :$start_label=0)
{
open(F, $fname) or die "Can't open $fname: $!";
my @lines = map { my $l = [split(/ /)]; shift(@$l); $l } (<F>);
my $sentences;
examples/lstm_bucketing.pl view on Meta::CPAN
$data_train,
eval_data => $data_val,
eval_metric => mx->metric->Perplexity($invalid_label),
kvstore => $kv_store,
optimizer => $optimizer,
optimizer_params => {
learning_rate => $lr,
momentum => $mom,
wd => $wd,
},
initializer => mx->init->Xavier(factor_type => "in", magnitude => 2.34),
num_epoch => $num_epoch,
batch_end_callback => mx->callback->Speedometer($batch_size, $disp_batches),
($chkp_epoch ? (epoch_end_callback => mx->rnn->do_rnn_checkpoint($stack, $chkp_prefix, $chkp_epoch)) : ())
);
examples/mnist.pl view on Meta::CPAN
}
sub read_data {
my($label_url, $image_url) = @_;
my($magic, $num, $rows, $cols);
open my($flbl), '<:gzip', download_data($label_url);
read $flbl, my($buf), 8;
($magic, $num) = unpack 'N2', $buf;
my $label = PDL->new();
$label->set_datatype($PDL::Types::PDL_B);
$label->setdims([ $num ]);
read $flbl, ${$label->get_dataref}, $num;
$label->upd_data();
open my($fimg), '<:gzip', download_data($image_url);
read $fimg, $buf, 16;
($magic, $num, $rows, $cols) = unpack 'N4', $buf;
my $image = PDL->new();
$image->set_datatype($PDL::Types::PDL_B);
$image->setdims([ $rows, $cols, $num ]);
read $fimg, ${$image->get_dataref}, $num * $rows * $cols;
$image->upd_data();
return($label, $image);
}
my $path='http://yann.lecun.com/exdb/mnist/';
my($train_lbl, $train_img) = read_data(
"${path}train-labels-idx1-ubyte.gz", "${path}train-images-idx3-ubyte.gz");
examples/mnist.pl view on Meta::CPAN
# Epoch[9] Validation-accuracy=0.964600
my($data) = @_;
# Flatten the data from 4-D shape (batch_size, num_channel, width, height)
# into 2-D (batch_size, num_channel*width*height)
$data = mx->sym->Flatten(data => $data);
# The first fully-connected layer
# my $fc1 = mx->sym->FullyConnected(data => $data, name => 'fc1', num_hidden => 128);
# # Apply relu to the output of the first fully-connnected layer
# my $act1 = mx->sym->Activation(data => $fc1, name => 'relu1', act_type => "relu");
# The second fully-connected layer and the according activation function
my $fc2 = mx->sym->FullyConnected(data => $data, name => 'fc2', num_hidden => 64);
my $act2 = mx->sym->Activation(data => $fc2, name => 'relu2', act_type => "relu");
# The thrid fully-connected layer, note that the hidden size should be 10, which is the number of unique digits
my $fc3 = mx->sym->FullyConnected(data => $act2, name => 'fc3', num_hidden => 10);
# The softmax and loss layer
my $mlp = mx->sym->SoftmaxOutput(data => $fc3, name => 'softmax');
return $mlp;
}
sub nn_conv {
my($data) = @_;
# Epoch[9] Batch [200] Speed: 1625.07 samples/sec Train-accuracy=0.992090
# Epoch[9] Batch [400] Speed: 1630.12 samples/sec Train-accuracy=0.992850
# Epoch[9] Train-accuracy=0.991357
# Epoch[9] Time cost=36.817
# Epoch[9] Validation-accuracy=0.988100
my $conv1= mx->symbol->Convolution(data => $data, name => 'conv1', num_filter => 20, kernel => [5,5], stride => [2,2]);
my $bn1 = mx->symbol->BatchNorm(data => $conv1, name => "bn1");
my $act1 = mx->symbol->Activation(data => $bn1, name => 'relu1', act_type => "relu");
my $mp1 = mx->symbol->Pooling(data => $act1, name => 'mp1', kernel => [2,2], stride =>[1,1], pool_type=>'max');
my $conv2= mx->symbol->Convolution(data => $mp1, name => 'conv2', num_filter => 50, kernel=>[3,3], stride=>[2,2]);
my $bn2 = mx->symbol->BatchNorm(data => $conv2, name=>"bn2");
my $act2 = mx->symbol->Activation(data => $bn2, name=>'relu2', act_type=>"relu");
my $mp2 = mx->symbol->Pooling(data => $act2, name => 'mp2', kernel=>[2,2], stride=>[1,1], pool_type=>'max');
my $fl = mx->symbol->Flatten(data => $mp2, name=>"flatten");
my $fc1 = mx->symbol->FullyConnected(data => $fl, name=>"fc1", num_hidden=>100);
my $act3 = mx->symbol->Activation(data => $fc1, name=>'relu3', act_type=>"relu");
my $fc2 = mx->symbol->FullyConnected(data => $act3, name=>'fc2', num_hidden=>30);
my $act4 = mx->symbol->Activation(data => $fc2, name=>'relu4', act_type=>"relu");
my $fc3 = mx->symbol->FullyConnected(data => $act4, name=>'fc3', num_hidden=>10);
my $softmax = mx->symbol->SoftmaxOutput(data => $fc3, name => 'softmax');
return $softmax;
}
my $mlp = $ARGV[0] ? nn_conv($data) : nn_fc($data);
#We visualize the network structure with output size (the batch_size is ignored.)
#my $shape = { data => [ $batch_size, 1, 28, 28 ] };
#show_network(mx->viz->plot_network($mlp, shape => $shape));
examples/plot_network.pl view on Meta::CPAN
#!/usr/bin/perl
use strict;
use warnings;
use AI::MXNet qw(mx);
### model
my $data = mx->symbol->Variable('data');
my $conv1= mx->symbol->Convolution(data => $data, name => 'conv1', num_filter => 32, kernel => [3,3], stride => [2,2]);
my $bn1 = mx->symbol->BatchNorm(data => $conv1, name => "bn1");
my $act1 = mx->symbol->Activation(data => $bn1, name => 'relu1', act_type => "relu");
my $mp1 = mx->symbol->Pooling(data => $act1, name => 'mp1', kernel => [2,2], stride =>[2,2], pool_type=>'max');
my $conv2= mx->symbol->Convolution(data => $mp1, name => 'conv2', num_filter => 32, kernel=>[3,3], stride=>[2,2]);
my $bn2 = mx->symbol->BatchNorm(data => $conv2, name=>"bn2");
my $act2 = mx->symbol->Activation(data => $bn2, name=>'relu2', act_type=>"relu");
my $mp2 = mx->symbol->Pooling(data => $act2, name => 'mp2', kernel=>[2,2], stride=>[2,2], pool_type=>'max');
my $fl = mx->symbol->Flatten(data => $mp2, name=>"flatten");
my $fc1 = mx->symbol->FullyConnected(data => $fl, name=>"fc1", num_hidden=>30);
my $act3 = mx->symbol->Activation(data => $fc1, name=>'relu3', act_type=>"relu");
my $fc2 = mx->symbol->FullyConnected(data => $act3, name=>'fc2', num_hidden=>10);
my $softmax = mx->symbol->SoftmaxOutput(data => $fc2, name => 'softmax');
## creates the image file in working directory, you need GraphViz installed for this to work
mx->viz->plot_network($softmax, save_format => 'png')->render("network.png");
lib/AI/MXNet.pm view on Meta::CPAN
sub img { 'AI::MXNet::Image' }
sub contrib { 'AI::MXNet::Contrib' }
sub name { '$short_name' }
sub AttrScope { shift; AI::MXNet::Symbol::AttrScope->new(\@_) }
*AI::MXNet::Symbol::AttrScope::current = sub { \$${short_name}::AttrScope; };
\$${short_name}::AttrScope = AI::MXNet::Symbol::AttrScope->new;
sub Prefix { AI::MXNet::Symbol::Prefix->new(prefix => \$_[1]) }
*AI::MXNet::Symbol::NameManager::current = sub { \$${short_name}::NameManager; };
\$${short_name}::NameManager = AI::MXNet::Symbol::NameManager->new;
*AI::MXNet::Context::current_ctx = sub { \$${short_name}::Context; };
\$${short_name}::Context = AI::MXNet::Context->new(device_type => 'cpu', device_id => 0);
1;
EOP
eval $short_name_package;
}
}
}
1;
__END__
lib/AI/MXNet.pm view on Meta::CPAN
use AI::MXNet::TestUtils qw(GetMNIST_ubyte);
use Test::More tests => 1;
# symbol net
my $batch_size = 100;
### model
my $data = mx->symbol->Variable('data');
my $conv1= mx->symbol->Convolution(data => $data, name => 'conv1', num_filter => 32, kernel => [3,3], stride => [2,2]);
my $bn1 = mx->symbol->BatchNorm(data => $conv1, name => "bn1");
my $act1 = mx->symbol->Activation(data => $bn1, name => 'relu1', act_type => "relu");
my $mp1 = mx->symbol->Pooling(data => $act1, name => 'mp1', kernel => [2,2], stride =>[2,2], pool_type=>'max');
my $conv2= mx->symbol->Convolution(data => $mp1, name => 'conv2', num_filter => 32, kernel=>[3,3], stride=>[2,2]);
my $bn2 = mx->symbol->BatchNorm(data => $conv2, name=>"bn2");
my $act2 = mx->symbol->Activation(data => $bn2, name=>'relu2', act_type=>"relu");
my $mp2 = mx->symbol->Pooling(data => $act2, name => 'mp2', kernel=>[2,2], stride=>[2,2], pool_type=>'max');
my $fl = mx->symbol->Flatten(data => $mp2, name=>"flatten");
my $fc1 = mx->symbol->FullyConnected(data => $fl, name=>"fc1", num_hidden=>30);
my $act3 = mx->symbol->Activation(data => $fc1, name=>'relu3', act_type=>"relu");
my $fc2 = mx->symbol->FullyConnected(data => $act3, name=>'fc2', num_hidden=>10);
my $softmax = mx->symbol->SoftmaxOutput(data => $fc2, name => 'softmax');
# check data
GetMNIST_ubyte();
my $train_dataiter = mx->io->MNISTIter({
image=>"data/train-images-idx3-ubyte",
label=>"data/train-labels-idx1-ubyte",
data_shape=>[1, 28, 28],
lib/AI/MXNet/Base.pm view on Meta::CPAN
return wantarray ? @_ : $_[0];
}
=head2 build_param_doc
Builds argument docs in python style.
arg_names : array ref of str
Argument names.
arg_types : array ref of str
Argument type information.
arg_descs : array ref of str
Argument description information.
remove_dup : boolean, optional
Whether to remove duplication or not.
Returns
-------
docstr : str
Python docstring of parameter sections.
=cut
sub build_param_doc
{
my ($arg_names, $arg_types, $arg_descs, $remove_dup) = @_;
$remove_dup //= 1;
my %param_keys;
my @param_str;
zip(sub {
my ($key, $type_info, $desc) = @_;
return if exists $param_keys{$key} and $remove_dup;
$param_keys{$key} = 1;
my $ret = sprintf("%s : %s", $key, $type_info);
$ret .= "\n ".$desc if length($desc);
push @param_str, $ret;
},
$arg_names, $arg_types, $arg_descs
);
return sprintf("Parameters\n----------\n%s\n", join("\n", @param_str));
}
=head2 _notify_shutdown
Notify MXNet about shutdown.
=cut
sub _notify_shutdown
lib/AI/MXNet/Context.pm view on Meta::CPAN
package AI::MXNet::Context;
use strict;
use warnings;
use Mouse;
use AI::MXNet::Types;
use AI::MXNet::Function::Parameters;
use constant devtype2str => { 1 => 'cpu', 2 => 'gpu', 3 => 'cpu_pinned' };
use constant devstr2type => { cpu => 1, gpu => 2, cpu_pinned => 3 };
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
return $class->$orig(device_type => $_[0])
if @_ == 1 and $_[0] =~ /^(?:cpu|gpu|cpu_pinned)$/;
return $class->$orig(
device_type => $_[0]->device_type,
device_id => $_[0]->device_id
) if @_ == 1 and blessed $_[0];
return $class->$orig(device_type => $_[0], device_id => $_[0])
if @_ == 2 and $_[0] =~ /^(?:cpu|gpu|cpu_pinned)$/;
return $class->$orig(@_);
};
has 'device_type' => (
is => 'rw',
isa => enum([qw[cpu gpu cpu_pinned]]),
default => 'cpu'
);
has 'device_type_id' => (
is => 'rw',
isa => enum([1, 2, 3]),
default => sub { devstr2type->{ shift->device_type } },
lazy => 1
);
has 'device_id' => (
is => 'rw',
isa => 'Int',
default => 0
);
use overload
'==' => sub {
my ($self, $other) = @_;
return 0 unless blessed($other) and $other->isa(__PACKAGE__);
return "$self" eq "$other";
},
'""' => sub {
my ($self) = @_;
return sprintf("%s(%s)", $self->device_type, $self->device_id);
};
=head1 NAME
AI::MXNet::Context - A device context.
=cut
=head1 DESCRIPTION
This class governs the device context of AI::MXNet::NDArray objects.
=cut
=head2
Constructing a context.
Parameters
----------
device_type : {'cpu', 'gpu'} or Context.
String representing the device type
device_id : int (default=0)
The device id of the device, needed for GPU
=cut
=head2 cpu
Returns a CPU context.
Parameters
lib/AI/MXNet/Context.pm view on Meta::CPAN
This is included to make interface compatible with GPU.
Returns
-------
context : AI::MXNet::Context
The corresponding CPU context.
=cut
method cpu(Int $device_id=0)
{
return $self->new(device_type => 'cpu', device_id => $device_id);
}
=head2 gpu
Returns a GPU context.
Parameters
----------
device_id : int, optional
Returns
-------
context : AI::MXNet::Context
The corresponding GPU context.
=cut
method gpu(Int $device_id=0)
{
return $self->new(device_type => 'gpu', device_id => $device_id);
}
=head2 current_context
Returns the current context.
Returns
-------
$default_ctx : AI::MXNet::Context
=cut
method current_ctx()
{
return $AI::MXNet::current_ctx;
}
method deepcopy()
{
return __PACKAGE__->new(
device_type => $self->device_type,
device_id => $self->device_id
);
}
$AI::MXNet::current_ctx = __PACKAGE__->new(device_type => 'cpu', device_id => 0);
lib/AI/MXNet/Contrib/AutoGrad.pm view on Meta::CPAN
my @args = @_;
my @variables = @_;
if(defined $argnum)
{
my @argnum = ref $argnum ? @$argnum : ($argnum);
@variables = map { $_[$_] } @argnum;
}
map {
assert(
(blessed($_) and $_->isa('AI::MXNet::NDArray')),
"type of autograd input should NDArray")
} @variables;
my @grads = map { $_->zeros_like } @variables;
__PACKAGE__->mark_variables(\@variables, \@grads);
my $prev = __PACKAGE__->set_is_training(1);
my $outputs = $func->(@args);
__PACKAGE__->set_is_training(0) unless $prev;
__PACKAGE__->compute_gradient(ref $outputs eq 'ARRAY' ? $outputs : [$outputs]);
return (\@grads, $outputs);
};
}
lib/AI/MXNet/Executor.pm view on Meta::CPAN
>>> print $outputs->[0]->aspdl;
=cut
method forward(Int $is_train=0, %kwargs)
{
if(%kwargs)
{
my $arg_dict = $self->arg_dict;
while (my ($name, $array) = each %kwargs)
{
if(not find_type_constraint('AcceptableInput')->check($array))
{
confess('only accept keyword argument of NDArrays/PDLs/Perl Array refs');
}
if(not exists $arg_dict->{ $name })
{
confess("unknown argument $name");
}
if(not blessed($array) or not $array->isa('AI::MXNet::NDArray'))
{
$array = AI::MXNet::NDArray->array($array);
lib/AI/MXNet/Executor.pm view on Meta::CPAN
Maybe[HashRef[AI::MXNet::NDArray]] $aux_params=,
Maybe[Bool] $allow_extra_params=
)
{
my %arg_dict = %{ $self->arg_dict };
while (my ($name, $array) = each %{ $arg_params })
{
if(exists $arg_dict{ $name })
{
my $dst = $arg_dict{ $name };
$array->astype($dst->dtype)->copyto($dst);
}
elsif(not $allow_extra_params)
{
confess("Found name \"$name\" that is not in the arguments");
}
}
if(defined $aux_params)
{
my %aux_dict = %{ $self->aux_dict };
while (my ($name, $array) = each %{ $aux_params })
{
if(exists $aux_dict{ $name })
{
my $dst = $aux_dict{ $name };
$array->astype($dst->dtype)->copyto($dst);
}
elsif(not $allow_extra_params)
{
confess("Found name \"$name\" that is not in the arguments");
}
}
}
}
=head2 reshape
lib/AI/MXNet/Executor.pm view on Meta::CPAN
confess(
"New shape of arg:$name larger than original. "
."First making a big executor and then down sizing it "
."is more efficient than the reverse."
."If you really want to up size, set \$allow_up_sizing=1 "
."to enable allocation of new arrays."
) unless $allow_up_sizing;
$new_arg_dict{ $name } = AI::MXNet::NDArray->empty(
$new_shape,
ctx => $arr->context,
dtype => $arr->dtype
);
if(defined $darr)
{
$new_grad_dict{ $name } = AI::MXNet::NDArray->empty(
$new_shape,
ctx => $darr->context,
dtype => $arr->dtype
);
}
}
else
{
$new_arg_dict{ $name } = $arr->reshape($new_shape);
if(defined $darr)
{
$new_grad_dict{ $name } = $darr->reshape($new_shape);
}
lib/AI/MXNet/Executor.pm view on Meta::CPAN
confess(
"New shape of arg:$name larger than original. "
."First making a big executor and then down sizing it "
."is more efficient than the reverse."
."If you really want to up size, set \$allow_up_sizing=1 "
."to enable allocation of new arrays."
) unless $allow_up_sizing;
$new_aux_dict{ $name } = AI::MXNet::NDArray->empty(
$new_shape,
ctx => $arr->context,
dtype => $arr->dtype
);
}
else
{
$new_aux_dict{ $name } = $arr->reshape($new_shape);
}
}
else
{
confess(
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
-----
- This function will inplace update the NDArrays in arg_params and aux_params.
=cut
method get_params(HashRef[AI::MXNet::NDArray] $arg_params, HashRef[AI::MXNet::NDArray] $aux_params)
{
my $weight = 0;
zip(sub {
my ($name, $block) = @_;
my $weight = sum(map { $_->copyto(AI::MXNet::Context->cpu) } @{ $block }) / @{ $block };
$weight->astype($arg_params->{$name}->dtype)->copyto($arg_params->{$name});
}, $self->param_names, $self->_p->param_arrays);
zip(sub {
my ($name, $block) = @_;
my $weight = sum(map { $_->copyto(AI::MXNet::Context->cpu) } @{ $block }) / @{ $block };
$weight->astype($aux_params->{$name}->dtype)->copyto($aux_params->{$name});
}, $self->_p->aux_names, $self->_p->aux_arrays);
}
method get_states($merge_multi_context=1)
{
assert((not $merge_multi_context), "merge_multi_context=True is not supported for get_states yet.");
return $self->_p->state_arrays;
}
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
)
{
my $shared_exec = $shared_group ? $shared_group->_p->execs->[$i] : undef;
my $context = $self->contexts->[$i];
my $shared_data_arrays = $self->_p->shared_data_arrays->[$i];
my %input_shapes = map { $_->name => $_->shape } @{ $data_shapes };
if(defined $label_shapes)
{
%input_shapes = (%input_shapes, map { $_->name => $_->shape } @{ $label_shapes });
}
my %input_types = map { $_->name => $_->dtype } @{ $data_shapes };
my $executor = $self->symbol->simple_bind(
ctx => $context,
grad_req => $self->grad_req,
type_dict => \%input_types,
shared_arg_names => $self->param_names,
shared_exec => $shared_exec,
shared_buffer => $shared_data_arrays,
shapes => \%input_shapes
);
return $executor;
}
=head2 _sliced_shape
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
zip(sub {
my ($desc, $axis) = @_;
my @shape = @{ $desc->shape };
if($axis >= 0)
{
$shape[$axis] = $self->_p->slices->[$i]->[1] - $self->_p->slices->[$i]->[0];
}
push @sliced_shapes, AI::MXNet::DataDesc->new(
name => $desc->name,
shape => \@shape,
dtype => $desc->dtype,
layout => $desc->layout
);
}, $shapes, $major_axis);
return \@sliced_shapes;
}
=head2 install_monitor
Install monitor on all executors
lib/AI/MXNet/Function/Parameters.pm view on Meta::CPAN
use strict;
use warnings;
use Function::Parameters ();
use AI::MXNet::Types ();
sub import {
Function::Parameters->import(
{
func => {
defaults => 'function_strict',
runtime => 1,
reify_type => sub {
Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint($_[0])
}
},
method => {
defaults => 'method_strict',
runtime => 1,
reify_type => sub {
Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint($_[0])
}
},
}
);
}
{
no warnings 'redefine';
*Function::Parameters::_croak = sub {
local($Carp::CarpLevel) = 1;
lib/AI/MXNet/IO.pm view on Meta::CPAN
method DataDesc(@args) { AI::MXNet::DataDesc->new(@args) }
method DataBatch(@args) { AI::MXNet::DataBatch->new(@args) }
package AI::MXNet::DataDesc;
use Mouse;
use overload '""' => \&stringify,
'@{}' => \&to_nameshape;
has 'name' => (is => 'ro', isa => "Str", required => 1);
has 'shape' => (is => 'ro', isa => "Shape", required => 1);
has 'dtype' => (is => 'ro', isa => "Dtype", default => 'float32');
has 'layout' => (is => 'ro', isa => "Str", default => 'NCHW');
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
if(@_ >= 2 and ref $_[1] eq 'ARRAY')
{
my $name = shift;
my $shape = shift;
return $class->$orig(name => $name, shape => $shape, @_);
}
return $class->$orig(@_);
};
method stringify($other=, $reverse=)
{
sprintf(
"DataDesc[%s,%s,%s,%s]",
$self->name,
join('x', @{ $self->shape }),
$self->dtype,
$self->layout
);
}
method to_nameshape($other=, $reverse=)
{
[$self->name, $self->shape];
}
=head1 NAME
lib/AI/MXNet/IO.pm view on Meta::CPAN
return index($layout, 'N');
}
=head2 get_list
Coverts the input to an array ref AI::MXNet::DataDesc objects.
Parameters
----------
$shapes : HashRef[Shape]
$types= : Maybe[HashRef[Dtype]]
=cut
method get_list(HashRef[Shape] $shapes, Maybe[HashRef[Dtype]] $types=)
{
$types //= {};
return [
map {
AI::MXNet::DataDesc->new(
name => $_,
shape => $shapes->{$_},
(exists $types->{$_} ? (type => $types->{$_}) : ())
)
} keys %{ $shapes }
];
}
package AI::MXNet::DataBatch;
use Mouse;
=head1 NAME
lib/AI/MXNet/IO.pm view on Meta::CPAN
$self->num_data($num_data);
}
# The name and shape of data provided by this iterator
method provide_data()
{
return [map {
my ($k, $v) = @{ $_ };
my $shape = $v->shape;
$shape->[0] = $self->batch_size;
AI::MXNet::DataDesc->new(name => $k, shape => $shape, dtype => $v->dtype)
} @{ $self->data }];
}
# The name and shape of label provided by this iterator
method provide_label()
{
return [map {
my ($k, $v) = @{ $_ };
my $shape = $v->shape;
$shape->[0] = $self->batch_size;
AI::MXNet::DataDesc->new(name => $k, shape => $shape, dtype => $v->dtype)
} @{ $self->label }];
}
# Ignore roll over data and set to start
method hard_reset()
{
$self->cursor(-$self->batch_size);
}
method reset()
lib/AI/MXNet/IO.pm view on Meta::CPAN
sub BUILD
{
my $self = shift;
$self->first_batch($self->next);
my $data = $self->first_batch->data->[0];
$self->provide_data([
AI::MXNet::DataDesc->new(
name => $self->data_name,
shape => $data->shape,
dtype => $data->dtype
)
]);
my $label = $self->first_batch->label->[0];
$self->provide_label([
AI::MXNet::DataDesc->new(
name => $self->label_name,
shape => $label->shape,
dtype => $label->dtype
)
]);
$self->batch_size($data->shape->[0]);
}
sub DEMOLISH
{
check_call(AI::MXNetCAPI::DataIterFree(shift->handle));
}
lib/AI/MXNet/IO.pm view on Meta::CPAN
my %iter_meta;
method get_iter_meta()
{
return \%iter_meta;
}
# Create an io iterator by handle.
func _make_io_iterator($handle)
{
my ($iter_name, $desc,
$arg_names, $arg_types, $arg_descs
) = @{ check_call(AI::MXNetCAPI::DataIterGetIterInfo($handle)) };
my $param_str = build_param_doc($arg_names, $arg_types, $arg_descs);
my $doc_str = "$desc\n\n"
."$param_str\n"
."name : string, required.\n"
." Name of the resulting data iterator.\n\n"
."Returns\n"
."-------\n"
."iterator: DataIter\n"
." The result iterator.";
my $iter = sub {
my $class = shift;
lib/AI/MXNet/Image.pm view on Meta::CPAN
:$to_rgb : int
0 for BGR format (OpenCV default). 1 for RGB format (MXNet default).
:$out : NDArray
Output buffer. Do not specify for automatic allocation.
=cut
method imdecode(Str|PDL $buf, Int :$flag=1, Int :$to_rgb=1, Maybe[AI::MXNet::NDArray] :$out=)
{
if(not ref $buf)
{
my $pdl_type = PDL::Type->new(DTYPE_MX_TO_PDL->{'uint8'});
my $len; { use bytes; $len = length $buf; }
my $pdl = PDL->new_from_specification($pdl_type, $len);
${$pdl->get_dataref} = $buf;
$pdl->upd_data;
$buf = $pdl;
}
if(not (blessed $buf and $buf->isa('AI::MXNet::NDArray')))
{
$buf = AI::MXNet::NDArray->array($buf, dtype=>'uint8');
}
return AI::MXNet::NDArray->_cvimdecode($buf, { flag => $flag, to_rgb => $to_rgb, ($out ? (out => $out) : ()) });
}
=head2 scale_down
Scale down crop size if it's bigger than the image size.
Parameters:
-----------
lib/AI/MXNet/Image.pm view on Meta::CPAN
return $aug;
}
=head2 CastAug
Makes "Cast to float32" closure.
Returns:
--------
CodeRef that accepts AI::MXNet::NDArray $src as input
and returns [$src->astype('float32')]
=cut
method CastAug()
{
my $aug = sub { my $src = shift;
return [$src->astype('float32')]
};
return $aug;
}
=head2 CreateAugmenter
Create augumenter list
Parameters:
-----------
lib/AI/MXNet/Initializer.pm view on Meta::CPAN
else
{
$self->_init_default($name, $arr);
}
}
*slice = *call;
method _init_bilinear($name, $arr)
{
my $pdl_type = PDL::Type->new(DTYPE_MX_TO_PDL->{ 'float32' });
my $weight = pzeros(
PDL::Type->new(DTYPE_MX_TO_PDL->{ 'float32' }),
$arr->size
);
my $shape = $arr->shape;
my $size = $arr->size;
my $f = pceil($shape->[3] / 2)->at(0);
my $c = (2 * $f - 1 - $f % 2) / (2 * $f);
for my $i (0..($size-1))
{
lib/AI/MXNet/Initializer.pm view on Meta::CPAN
=head1 DESCRIPTION
Intialize weight as Orthogonal matrix
Parameters
----------
scale : float, optional
scaling factor of weight
rand_type: string optional
use "uniform" or "normal" random number to initialize weight
Reference
---------
Exact solutions to the nonlinear dynamics of learning in deep linear neural networks
arXiv preprint arXiv:1312.6120 (2013).
=cut
package AI::MXNet::Orthogonal;
use AI::MXNet::Base;
use Mouse;
use AI::MXNet::Types;
extends 'AI::MXNet::Initializer';
has "scale" => (is => "ro", isa => "Num", default => 1.414);
has "rand_type" => (is => "ro", isa => enum([qw/uniform normal/]), default => 'uniform');
method _init_weight(Str $name, AI::MXNet::NDArray $arr)
{
my @shape = @{ $arr->shape };
my $nout = $shape[0];
my $nin = AI::MXNet::NDArray->size([@shape[1..$#shape]]);
my $tmp = AI::MXNet::NDArray->zeros([$nout, $nin]);
if($self->rand_type eq 'uniform')
{
AI::MXNet::Random->uniform(-1, 1, { out => $tmp });
}
else
{
AI::MXNet::Random->normal(0, 1, { out => $tmp });
}
$tmp = $tmp->aspdl;
my ($u, $s, $v) = svd($tmp);
my $q;
lib/AI/MXNet/Initializer.pm view on Meta::CPAN
=head1 NAME
AI::MXNet::Xavier - Initialize the weight with Xavier or similar initialization scheme.
=cut
=head1 DESCRIPTION
Parameters
----------
rnd_type: str, optional
Use gaussian or uniform.
factor_type: str, optional
Use avg, in, or out.
magnitude: float, optional
The scale of the random number range.
=cut
package AI::MXNet::Xavier;
use Mouse;
use AI::MXNet::Types;
extends 'AI::MXNet::Initializer';
has "magnitude" => (is => "rw", isa => "Num", default => 3);
has "rnd_type" => (is => "ro", isa => enum([qw/uniform gaussian/]), default => 'uniform');
has "factor_type" => (is => "ro", isa => enum([qw/avg in out/]), default => 'avg');
method _init_weight(Str $name, AI::MXNet::NDArray $arr)
{
my @shape = @{ $arr->shape };
my $hw_scale = 1;
if(@shape > 2)
{
$hw_scale = AI::MXNet::NDArray->size([@shape[2..$#shape]]);
}
my ($fan_in, $fan_out) = ($shape[1] * $hw_scale, $shape[0] * $hw_scale);
my $factor;
if($self->factor_type eq "avg")
{
$factor = ($fan_in + $fan_out) / 2;
}
elsif($self->factor_type eq "in")
{
$factor = $fan_in;
}
else
{
$factor = $fan_out;
}
my $scale = sqrt($self->magnitude / $factor);
if($self->rnd_type eq "iniform")
{
AI::MXNet::Random->uniform(-$scale, $scale, { out => $arr });
}
else
{
AI::MXNet::Random->normal(0, $scale, { out => $arr });
}
}
__PACKAGE__->register;
lib/AI/MXNet/Initializer.pm view on Meta::CPAN
AI::MXNet::MSRAPrelu - Custom initialization scheme.
=cut
=head1 DESCRIPTION
Initialize the weight with initialization scheme from
Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification.
Parameters
----------
factor_type: str, optional
Use avg, in, or out.
slope: float, optional
initial slope of any PReLU (or similar) nonlinearities.
=cut
package AI::MXNet::MSRAPrelu;
use Mouse;
extends 'AI::MXNet::Xavier';
has '+rnd_type' => (default => "gaussian");
has '+factor_type' => (default => "avg");
has 'slope' => (is => 'ro', isa => 'Num', default => 0.25);
sub BUILD
{
my $self = shift;
my $magnitude = 2 / (1 + $self->slope ** 2);
$self->magnitude($magnitude);
$self->kwargs({ slope => $self->slope, factor_type => $self->factor_type });
}
__PACKAGE__->register;
package AI::MXNet::Bilinear;
use Mouse;
use AI::MXNet::Base;
extends 'AI::MXNet::Initializer';
method _init_weight($name, $arr)
{
my $pdl_type = PDL::Type->new(DTYPE_MX_TO_PDL->{ 'float32' });
my $weight = pzeros(
PDL::Type->new(DTYPE_MX_TO_PDL->{ 'float32' }),
$arr->size
);
my $shape = $arr->shape;
my $size = $arr->size;
my $f = pceil($shape->[3] / 2)->at(0);
my $c = (2 * $f - 1 - $f % 2) / (2 * $f);
for my $i (0..($size-1))
{
lib/AI/MXNet/KVStore.pm view on Meta::CPAN
Parameters
----------
optimizer : Optimizer
the optimizer
=cut
method set_optimizer(AI::MXNet::Optimizer $optimizer)
{
my $is_worker = check_call(AI::MXNetCAPI::KVStoreIsWorkerNode());
if($self->type eq 'dist' and $is_worker)
{
my $optim_str = MIME::Base64::encode_base64(Storable::freeze($optimizer), "");
$self->_send_command_to_servers(0, $optim_str);
}
else
{
$self->_updater(AI::MXNet::Optimizer->get_updater($optimizer));
$self->_set_updater(sub { &{$self->_updater}(@_) });
}
}
=head2 type
Get the type of this kvstore
Returns
-------
type : str
the string type
=cut
method type()
{
return scalar(check_call(AI::MXNetCAPI::KVStoreGetType($self->handle)));
}
=head2 rank
Get the rank of this worker node
Returns
-------
lib/AI/MXNet/KVStore.pm view on Meta::CPAN
);
}
=head2 create
Create a new KVStore.
Parameters
----------
name : {'local'}
The type of KVStore
- local works for multiple devices on a single machine (single process)
- dist works for multi-machines (multiple processes)
Returns
-------
kv : KVStore
The created AI::MXNet::KVStore
=cut
method create(Str $name='local')
{
lib/AI/MXNet/Metric.pm view on Meta::CPAN
}
method update(ArrayRef[AI::MXNet::NDArray] $labels, ArrayRef[AI::MXNet::NDArray] $preds)
{
AI::MXNet::Metric::check_label_shapes($labels, $preds);
zip(sub {
my ($label, $pred_label) = @_;
confess('Predictions should be no more than 2 dims')
unless @{ $pred_label->shape } <= 2;
$pred_label = $pred_label->aspdl->qsorti;
$label = $label->astype('int32')->aspdl;
AI::MXNet::Metric::check_label_shapes($label, $pred_label);
my $num_samples = $pred_label->shape->at(-1);
my $num_dims = $pred_label->ndims;
if($num_dims == 1)
{
my $sum = ($pred_label->flat == $label->flat)->sum;
$self->sum_metric($self->sum_metric + $sum);
}
elsif($num_dims == 2)
{
lib/AI/MXNet/Metric.pm view on Meta::CPAN
extends 'AI::MXNet::EvalMetric';
has '+name' => (default => 'f1');
method update(ArrayRef[AI::MXNet::NDArray] $labels, ArrayRef[AI::MXNet::NDArray] $preds)
{
AI::MXNet::Metric::check_label_shapes($labels, $preds);
zip(sub {
my ($label, $pred_label) = @_;
AI::MXNet::Metric::check_label_shapes($label, $pred_label);
$pred_label = $pred_label->aspdl->maximum_ind;
$label = $label->astype('int32')->aspdl;
confess("F1 currently only supports binary classification.")
if $label->uniq->shape->at(0) > 2;
my ($true_positives, $false_positives, $false_negatives) = (0,0,0);
zip(sub{
my ($y_pred, $y_true) = @_;
if($y_pred == 1 and $y_true == 1)
{
$true_positives += 1;
}
elsif($y_pred == 1 and $y_true == 0)
lib/AI/MXNet/Metric.pm view on Meta::CPAN
my ($loss, $num) = (0, 0);
zip(sub {
my ($label, $pred) = @_;
my $label_shape = $label->shape;
my $pred_shape = $pred->shape;
assert(
(product(@{ $label_shape }) == product(@{ $pred_shape })/$pred_shape->[-1]),
"shape mismatch: (@$label_shape) vs. (@$pred_shape)"
);
$label = $label->as_in_context($pred->context)->reshape([$label->size]);
$pred = AI::MXNet::NDArray->pick($pred, $label->astype('int32'), { axis => $self->axis });
if(defined $self->ignore_label)
{
my $ignore = ($label == $self->ignore_label);
$num -= $ignore->sum->asscalar;
$pred = $pred*(1-$ignore) + $ignore;
}
$loss -= $pred->maximum(1e-10)->log->sum->asscalar;
$num += $pred->size;
}, $labels, $preds);
$self->sum_metric($self->sum_metric + $loss);
lib/AI/MXNet/Module.pm view on Meta::CPAN
my $update_on_kvstore = 1;
my $kv;
if(defined $kvstore)
{
if(blessed $kvstore)
{
$kv = $kvstore;
}
else
{
# create kvstore using the string type
if($num_device == 1 and $kvstore !~ /dist/)
{
# no need to use kv for single device and single machine
}
else
{
$kv = AI::MXNet::KVStore->create($kvstore);
if($kvstore eq 'local')
{
# automatically select a proper local
lib/AI/MXNet/Module.pm view on Meta::CPAN
elsif($self->params_initialized)
{
# if the parameters are already initialized, we are re-binding
# so automatically copy the already initialized params
$self->_p->_exec_group->set_params($self->_p->_arg_params, $self->_p->_aux_params);
}
else
{
assert(not defined $self->_p->_arg_params and not $self->_p->_aux_params);
my @param_arrays = (
map { AI::MXNet::NDArray->zeros($_->[0]->shape, dtype => $_->[0]->dtype) }
@{ $self->_p->_exec_group->_p->param_arrays }
);
my %arg_params;
@arg_params{ @{ $self->_p->_param_names } } = @param_arrays;
$self->_p->_arg_params(\%arg_params);
my @aux_arrays = (
map { AI::MXNet::NDArray->zeros($_->[0]->shape, dtype => $_->[0]->dtype) }
@{ $self->_p->_exec_group->_p->aux_arrays }
);
my %aux_params;
@aux_params{ @{ $self->_p->_aux_names } } = @aux_arrays;
$self->_p->_aux_params(\%aux_params);
}
if($shared_module and $shared_module->optimizer_initialized)
{
$self->borrow_optimizer($shared_module)
}
lib/AI/MXNet/Module.pm view on Meta::CPAN
{
$self->_sync_params_from_devices;
}
my ($kvstore, $update_on_kvstore) = _create_kvstore(
$kvstore,
scalar(@{$self->_p->_context}),
$self->_p->_arg_params
);
my $batch_size = $self->_p->_exec_group->_p->batch_size;
if($kvstore and $kvstore->type =~ /dist/ and $kvstore->type =~ /_sync/)
{
$batch_size *= $kvstore->num_workers;
}
my $rescale_grad = 1/$batch_size;
if(not blessed $optimizer)
{
my %idx2name;
if($update_on_kvstore)
{
lib/AI/MXNet/Module.pm view on Meta::CPAN
if($data_batch->can('provide_data') and $data_batch->provide_data)
{
$new_dshape = $data_batch->provide_data;
}
else
{
$new_dshape = [];
zip(sub {
my ($i, $shape) = @_;
push @{ $new_dshape }, AI::MXNet::DataDesc->new(
$i->name, $shape, $i->dtype, $i->layout
);
}, $self->data_shapes, \@new_data_shapes);
}
my $new_lshape;
if($data_batch->can('provide_label') and $data_batch->provide_label)
{
$new_lshape = $data_batch->provide_label;
}
elsif($data_batch->can('label') and $data_batch->label)
{
$new_lshape = [];
zip(sub {
my ($i, $j) = @_;
push @{ $new_lshape }, AI::MXNet::DataDesc->new(
$i->name, $j->shape, $i->dtype, $i->layout
);
}, $self->label_shapes, $data_batch->label);
}
$self->reshape(data_shapes => $new_dshape, label_shapes => $new_lshape);
}
$self->_p->_exec_group->forward($data_batch, $is_train);
}
method backward(Maybe[AI::MXNet::NDArray|ArrayRef[AI::MXNet::NDArray]] $out_grads=)
{
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
func _as_list($obj)
{
return [$obj] if ((ref($obj)//'') ne 'ARRAY');
return $obj;
}
# Check that all input names are in symbol's argument
method _check_input_names(
AI::MXNet::Symbol $symbol,
ArrayRef[Str] $names,
Str $typename,
Bool $throw
)
{
my @candidates;
my %args = map {
push @candidates, $_ if not /_(?:weight|bias|gamma|beta)$/;
$_ => 1
} @{ $symbol->list_arguments };
for my $name (@$names)
{
my $msg;
if(not exists $args{$name} and $name ne 'softmax_label')
{
$msg = sprintf("\033[91mYou created Module with Module(..., %s_names=%s) but "
."input with name '%s' is not found in symbol.list_arguments(). "
."Did you mean one of:\n\t%s\033[0m",
$typename, "@$names", $name, join("\n\t", @candidates)
);
if($throw)
{
confess($msg);
}
else
{
AI::MXNet::Logging->warning($msg);
}
}
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
Path to input param file.
=cut
method load_params(Str $fname)
{
my %save_dict = %{ AI::MXNet::NDArray->load($fname) };
my %arg_params;
my %aux_params;
while(my ($k, $v) = each %save_dict)
{
my ($arg_type, $name) = split(/:/, $k, 2);
if($arg_type eq 'arg')
{
$arg_params{ $name } = $v;
}
elsif($arg_type eq 'aux')
{
$aux_params{ $name } = $v;
}
else
{
confess("Invalid param file $fname");
}
}
$self->set_params(\%arg_params, \%aux_params);
}
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
}
################################################################################
# misc
################################################################################
=head2 symbol
The symbol associated with this module.
Except for AI::MXNet::Module, for other types of modules (e.g. AI::MXNet::Module::Bucketing), this
property might not be a constant throughout its life time. Some modules might
not even be associated with any symbols.
=cut
method symbol()
{
return $self->_symbol;
}
1;
lib/AI/MXNet/Module/Bucketing.pm view on Meta::CPAN
$data_train,
eval_data => $data_val,
eval_metric => mx->metric->Perplexity($invalid_label),
kvstore => $kv_store,
optimizer => $optimizer,
optimizer_params => {
learning_rate => $lr,
momentum => $mom,
wd => $wd,
},
initializer => mx->init->Xavier(factor_type => "in", magnitude => 2.34),
num_epoch => $num_epoch,
batch_end_callback => mx->callback->Speedometer($batch_size, $disp_batches),
($chkp_epoch ? (epoch_end_callback => mx->rnn->do_rnn_checkpoint($stack, $chkp_prefix, $chkp_epoch)) : ())
);
=head1 DESCRIPTION
Implements the AI::MXNet::Module::Base API, and allows multiple
symbols to be used depending on the `bucket_key` provided by each different
mini-batch of data
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
}
method asscalar()
{
confess("ndarray size must be 1") unless $self->size == 1;
return $self->aspdl->at(0);
}
method _sync_copyfrom(ArrayRef|PDL|PDL::Matrix $source_array)
{
my $dtype = $self->dtype;
my $pdl_type = PDL::Type->new(DTYPE_MX_TO_PDL->{ $dtype });
if(not blessed($source_array))
{
$source_array = eval {
pdl($pdl_type, $source_array);
};
confess($@) if $@;
}
if($pdl_type->numval != $source_array->type->numval)
{
my $convert_func = $pdl_type->convertfunc;
$source_array = $source_array->$convert_func;
}
$source_array = pdl($pdl_type, [@{ $source_array->unpdl } ? $source_array->unpdl->[0] : 0 ])
unless @{ $source_array->shape->unpdl };
my $pdl_shape = $source_array->shape->unpdl;
my $pdl_shape_str = join(',', ref($source_array) eq 'PDL' ? reverse @{ $pdl_shape } : @{ $pdl_shape });
my $ndary_shape_str = join(',', @{ $self->shape });
if($pdl_shape_str ne $ndary_shape_str)
{
confess("Shape inconsistant: expected $ndary_shape_str vs got $pdl_shape_str")
}
my $perl_pack_type = DTYPE_MX_TO_PERL->{$dtype};
my $buf;
## special handling for float16
if($perl_pack_type eq 'S')
{
$buf = pack("S*", map { AI::MXNetCAPI::_float_to_half($_) } unpack ("f*", ${$source_array->get_dataref}));
}
else
{
$buf = ${$source_array->get_dataref};
}
check_call(AI::MXNetCAPI::NDArraySyncCopyFromCPU($self->handle, $buf, $self->size));
return $self;
}
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
Returns a copied PDL array of current array.
Returns
-------
array : PDL
A copy of the array content.
=cut
method aspdl()
{
my $dtype = $self->dtype;
my $pdl_type = PDL::Type->new(DTYPE_MX_TO_PDL->{ $dtype });
my $pdl = PDL->new_from_specification($pdl_type, reverse @{ $self->shape });
my $perl_pack_type = DTYPE_MX_TO_PERL->{$dtype};
my $buf = pack("$perl_pack_type*", (0)x$self->size);
check_call(AI::MXNetCAPI::NDArraySyncCopyToCPU($self->handle, $buf, $self->size));
## special handling for float16
if($perl_pack_type eq 'S')
{
$buf = pack("f*", map { AI::MXNetCAPI::_half_to_float($_) } unpack("S*", $buf));
}
${$pdl->get_dataref} = $buf;
$pdl->upd_data;
return $pdl;
}
=head2 asmpdl
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
Requires caller to "use PDL::Matrix" in user space.
Returns
-------
array : PDL::Matrix
A copy of array content.
=cut
method asmpdl()
{
my $dtype = $self->dtype;
my $pdl_type = PDL::Type->new(DTYPE_MX_TO_PDL->{ $dtype });
my $pdl = PDL::Matrix->new_from_specification($pdl_type, @{ $self->shape });
my $perl_pack_type = DTYPE_MX_TO_PERL->{$dtype};
my $buf = pack("$perl_pack_type*", (0)x$self->size);
check_call(AI::MXNetCAPI::NDArraySyncCopyToCPU($self->handle, $buf, $self->size));
## special handling for float16
if($perl_pack_type eq 'S')
{
$buf = pack("f*", map { AI::MXNetCAPI::_half_to_float($_) } unpack("S*", $buf));
}
${$pdl->get_dataref} = $buf;
$pdl->upd_data;
return $pdl;
}
=head2 _slice
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
The context of the NDArray.
Returns
-------
$context : AI::MXNet::Context
=cut
method context()
{
my ($dev_type_id, $dev_id) = check_call(
AI::MXNetCAPI::NDArrayGetContext($self->handle)
);
return AI::MXNet::Context->new(
device_type => AI::MXNet::Context::devtype2str->{ $dev_type_id },
device_id => $dev_id
);
}
=head2 dtype
The data type of current NDArray.
Returns
-------
a data type string ('float32', 'float64', 'float16', 'uint8', 'int32')
representing the data type of the ndarray.
'float32' is the default dtype for the ndarray class.
=cut
method dtype()
{
my $dtype = check_call(
AI::MXNetCAPI::NDArrayGetDType(
$self->handle
)
);
return DTYPE_MX_TO_STR->{ $dtype };
}
=head2 copyto
Copy the content of current array to another entity.
When another entity is the NDArray, the content is copied over.
When another entity is AI::MXNet::Context, a new NDArray in the context
will be created.
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
dst : NDArray
=cut
method copyto(AI::MXNet::Context|AI::MXNet::NDArray $other)
{
if(blessed($other) and $other->isa('AI::MXNet::Context'))
{
my $hret = __PACKAGE__->empty(
$self->shape,
ctx => $other,
dtype => $self->dtype
);
return __PACKAGE__->_copyto($self, { out => $hret });
}
else
{
if ($other->handle eq $self->handle)
{
Carp::cluck('copy an array to itself, is it intended?');
}
return __PACKAGE__->_copyto($self, { out => $other });
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
method T()
{
if (@{$self->shape} > 2)
{
confess('Only 2D matrix is allowed to be transposed');
}
return __PACKAGE__->transpose($self);
}
=head2 astype
Returns copied ndarray of current array with the specified type.
Parameters
----------
$dtype : Dtype
Returns
-------
$array : ndarray
A copy of the array content.
=cut
method astype(Dtype $dtype)
{
my $res = __PACKAGE__->empty($self->shape, ctx => $self->context, dtype => $dtype);
$self->copyto($res);
return $res;
}
=head2 as_in_context
Returns an NDArray in the target context.
If the array is already in that context, self is returned. Otherwise, a copy is
made.
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
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
-------
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
Creates an empty uninitialized NDArray, with the specified shape.
Parameters
----------
$shape : Shape
shape of the NDArray.
:$ctx : AI::MXNet::Context, optional
The context of the NDArray, defaults to current default context.
:$dtype : Dtype, optional
The dtype of the NDArray, defaults to 'float32'.
Returns
-------
out: Array
The created NDArray.
=cut
method empty(Shape $shape, AI::MXNet::Context :$ctx=AI::MXNet::Context->current_ctx, Dtype :$dtype='float32')
{
return __PACKAGE__->new(
handle => _new_alloc_handle(
$shape,
$ctx,
0,
DTYPE_STR_TO_MX->{$dtype}
)
);
}
=head2 zeros
Creates a new NDArray filled with 0, with specified shape.
Parameters
----------
$shape : Shape
shape of the NDArray.
:$ctx : AI::MXNet::Context, optional
The context of the NDArray, defaults to current default context.
:$dtype : Dtype, optional
The dtype of the NDArray, defaults to 'float32'.
Returns
-------
out: Array
The created NDArray.
=cut
method zeros(
Shape $shape,
AI::MXNet::Context :$ctx=AI::MXNet::Context->current_ctx,
Dtype :$dtype='float32',
Maybe[AI::MXNet::NDArray] :$out=
)
{
return __PACKAGE__->_zeros({ shape => $shape, ctx => "$ctx", dtype => $dtype, ($out ? (out => $out) : ()) });
}
=head2 ones
Creates a new NDArray filled with 1, with specified shape.
Parameters
----------
$shape : Shape
shape of the NDArray.
:$ctx : AI::MXNet::Context, optional
The context of the NDArray, defaults to current default context.
:$dtype : Dtype, optional
The dtype of the NDArray, defaults to 'float32'.
Returns
-------
out: Array
The created NDArray.
=cut
method ones(
Shape $shape,
AI::MXNet::Context :$ctx=AI::MXNet::Context->current_ctx,
Dtype :$dtype='float32',
Maybe[AI::MXNet::NDArray] :$out=
)
{
return __PACKAGE__->_ones({ shape => $shape, ctx => "$ctx", dtype => $dtype, ($out ? (out => $out) : ()) });
}
=head2 full
Creates a new NDArray filled with given value, with specified shape.
Parameters
----------
$shape : Shape
shape of the NDArray.
val : float or int
The value to be filled with.
:$ctx : AI::MXNet::Context, optional
The context of the NDArray, defaults to current default context.
:$dtype : Dtype, optional
The dtype of the NDArray, defaults to 'float32'.
Returns
-------
out: Array
The created NDArray.
=cut
method full(
Shape $shape, Num $val,
AI::MXNet::Context :$ctx=AI::MXNet::Context->current_ctx,
Dtype :$dtype='float32', Maybe[AI::MXNet::NDArray] :$out=
)
{
return __PACKAGE__->_set_value({ src => $val, out => $out ? $out : __PACKAGE__->empty($shape, ctx => $ctx, dtype => $dtype) });
}
=head2 array
Creates a new NDArray that is a copy of the source_array.
Parameters
----------
$source_array : AI::MXNet::NDArray PDL, PDL::Matrix, Array ref in PDL::pdl format
Source data to create NDArray from.
:$ctx : AI::MXNet::Context, optional
The context of the NDArray, defaults to current default context.
:$dtype : Dtype, optional
The dtype of the NDArray, defaults to 'float32'.
Returns
-------
out: Array
The created NDArray.
=cut
method array(PDL|PDL::Matrix|ArrayRef|AI::MXNet::NDArray $source_array, AI::MXNet::Context :$ctx=AI::MXNet::Context->current_ctx, Dtype :$dtype='float32')
{
if(blessed $source_array and $source_array->isa('AI::MXNet::NDArray'))
{
my $arr = __PACKAGE__->empty($source_array->shape, ctx => $ctx, dtype => $dtype);
$arr .= $source_array;
return $arr;
}
my $pdl_type = PDL::Type->new(DTYPE_MX_TO_PDL->{ $dtype });
if(not blessed($source_array))
{
$source_array = eval {
pdl($pdl_type, $source_array);
};
confess($@) if $@;
}
$source_array = pdl($pdl_type, [@{ $source_array->unpdl } ? $source_array->unpdl->[0] : 0 ]) unless @{ $source_array->shape->unpdl };
my $shape = $source_array->shape->unpdl;
my $arr = __PACKAGE__->empty([ref($source_array) eq 'PDL' ? reverse @{ $shape } : @{ $shape }], ctx => $ctx, dtype => $dtype );
$arr .= $source_array;
return $arr;
}
=head2 concatenate
Concatenates an array ref of NDArrays along the first dimension.
Parameters
----------
$arrays : array ref of NDArrays
Arrays to be concatenate. They must have identical shape except
for the first dimension. They also must have the same data type.
:$axis=0 : int
The axis along which to concatenate.
:$always_copy=1 : bool
Default is 1. When not 1, if the arrays only contain one
NDArray, that element will be returned directly, avoid copying.
Returns
-------
An NDArray in the same context as $arrays->[0]->context.
=cut
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
method concatenate(ArrayRef[AI::MXNet::NDArray] $arrays, Index :$axis=0, :$always_copy=1)
{
confess("no arrays provided") unless @$arrays > 0;
if(not $always_copy and @$arrays == 1)
{
return $arrays->[0];
}
my $shape_axis = $arrays->[0]->shape->[$axis];
my $shape_rest1 = [@{ $arrays->[0]->shape }[0..($axis-1)]];
my $shape_rest2 = [@{ $arrays->[0]->shape }[($axis+1)..(@{ $arrays->[0]->shape }-1)]];
my $dtype = $arrays->[0]->dtype;
my $i = 1;
for my $arr (@{ $arrays }[1..(@{ $arrays }-1)])
{
$shape_axis += $arr->shape->[$axis];
my $arr_shape_rest1 = [@{ $arr->shape }[0..($axis-1)]];
my $arr_shape_rest2 = [@{ $arr->shape }[($axis+1)..(@{ $arr->shape }-1)]];
confess("first array $arrays->[0] and $i array $arr do not match")
unless join(',',@$arr_shape_rest1) eq join(',',@$shape_rest1);
confess("first array $arrays->[0] and $i array $arr do not match")
unless join(',',@$arr_shape_rest2) eq join(',',@$shape_rest2);
confess("first array $arrays->[0] and $i array $arr dtypes do not match")
unless join(',',@$arr_shape_rest2) eq join(',',@$shape_rest2);
$i++;
}
my $ret_shape = [@$shape_rest1, $shape_axis, @$shape_rest2];
my $ret = __PACKAGE__->empty($ret_shape, ctx => $arrays->[0]->context, dtype => $dtype);
my $idx = 0;
my $begin = [(0)x@$ret_shape];
my $end = [@$ret_shape];
for my $arr (@$arrays)
{
if ($axis == 0)
{
$ret->slice([$idx,($idx+$arr->shape->[0]-1)]) .= $arr;
}
else
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
Start of interval. The interval includes this value. The default start value is 0.
$stop= : number, optional
End of interval. The interval does not include this value.
:$step=1 : number, optional
Spacing between the values
:$repeat=1 : number, optional
The repeating time of all elements.
E.g repeat=3, the element a will be repeated three times --> a, a, a.
:$ctx : Context, optional
The context of the NDArray, defaultw to current default context.
:$dtype : data type, optional
The value type of the NDArray, defaults to float32
Returns
-------
$out : NDArray
The created NDArray
=cut
method arange(Index :$start=0, Index :$stop=, Index :$step=1, Index :$repeat=1,
AI::MXNet::Context :$ctx=AI::MXNet::Context->current_ctx, Dtype :$dtype='float32')
{
return __PACKAGE__->_arange({
start => $start,
(defined $stop ? (stop => $stop) : ()),
step => $step,
repeat => $repeat,
dtype => $dtype,
ctx => "$ctx"
});
}
=head2 load
Loads ndarrays from a binary file.
You can also use Storable to do the job if you only work with Perl.
The advantage of load/save is the file is language agnostic.
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
Returns a new handle with specified shape and context.
Empty handle is only used to hold results
Returns
-------
a new empty ndarray handle
=cut
func _new_alloc_handle($shape, $ctx, $delay_alloc, $dtype)
{
my $hdl = check_call(AI::MXNetCAPI::NDArrayCreateEx(
$shape,
scalar(@$shape),
$ctx->device_type_id,
$ctx->device_id,
$delay_alloc,
$dtype)
);
return $hdl;
}
=head2 waitall
Wait for all async operations to finish in MXNet.
This function is used for benchmarks only.
=cut
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
[$self->handle],
[defined $out_grad ? $out_grad->handle : undef],
$retain_graph
)
)
}
method CachedOp(@args) { AI::MXNet::CachedOp->new(@args) }
my $lvalue_methods = join "\n", map {"use attributes 'AI::MXNet::NDArray', \\&AI::MXNet::NDArray::$_, 'lvalue';"}
qw/at slice aspdl asmpdl reshape copy sever T astype as_in_context copyto empty zero ones full
array/;
eval << "EOV" if ($^V and $^V >= 5.006007);
{
no warnings qw(misc);
$lvalue_methods
}
EOV
__PACKAGE__->meta->make_immutable;
lib/AI/MXNet/NDArray/Base.pm view on Meta::CPAN
}
method function_meta_hash()
{
return \%function_meta;
}
func _make_ndarray_function($handle, $func_name)
{
my ($real_name, $desc, $arg_names,
$arg_types, $arg_descs, $key_var_num_args,
$ret_type) = @{ check_call(AI::MXNetCAPI::SymbolGetAtomicSymbolInfo($handle)) };
$ret_type //= '';
my $doc_str = build_doc($func_name,
$desc,
$arg_names,
$arg_types,
$arg_descs,
$key_var_num_args,
$ret_type
);
my @arguments;
for my $i (0..(@$arg_names-1))
{
if(not $arg_types->[$i] =~ /^(?:NDArray|Symbol|ndarray\-or\-symbol)/)
{
push @arguments, $arg_names->[$i];
}
}
my $generic_ndarray_function = sub
{
my $class = shift;
my (@args, %kwargs);
if(@_ and ref $_[-1] eq 'HASH')
{
lib/AI/MXNet/NDArray/Doc.pm view on Meta::CPAN
=head2
Build docstring for imperative functions.
=cut
sub build_doc
{
my ($func_name,
$desc,
$arg_names,
$arg_types,
$arg_desc,
$key_var_num_args,
$ret_type) = @_;
my $param_str = build_param_doc($arg_names, $arg_types, $arg_desc);
if($key_var_num_args)
{
$desc .= "\nThis function support variable length of positional input."
}
my $doc_str = sprintf("%s\n\n" .
"%s\n" .
"out : NDArray, optional\n" .
" The output NDArray to hold the result.\n\n".
"Returns\n" .
"-------\n" .
lib/AI/MXNet/Optimizer.pm view on Meta::CPAN
if($self->clip_gradient)
{
$self->kwargs->{clip_gradient} = $self->clip_gradient;
}
}
method create_state(Index $index, AI::MXNet::NDArray $weight)
{
my $momentum;
my $weight_master_copy;
if($self->multi_precision and $weight->dtype eq 'float16')
{
my $weight_master_copy = AI::MXNet::NDArray->array($weight, ctx => $weight->context, dtype => 'float32');
if($self->momentum != 0)
{
$momentum = AI::MXNet::NDArray->zeros($weight->shape, ctx => $weight->context, dtype => 'float32');
}
return [$momentum, $weight_master_copy];
}
if($weight->dtype eq 'float16' and not $self->multi_precision)
{
AI::MXNet::Logging->warning(
"Accumulating with float16 in optimizer can lead to ".
"poor accuracy or slow convergence. ".
"Consider using multi_precision=True option of the ".
"SGD optimizer"
);
}
if($self->momentum != 0)
{
$momentum = AI::MXNet::NDArray->zeros($weight->shape, ctx => $weight->context, dtype => $weight->dtype);
}
return $momentum;
}
method update(
Index $index,
AI::MXNet::NDArray $weight,
AI::MXNet::NDArray $grad,
Maybe[AI::MXNet::NDArray|ArrayRef[Maybe[AI::MXNet::NDArray]]] $state
)
lib/AI/MXNet/Optimizer.pm view on Meta::CPAN
sub BUILD
{
my $self = shift;
$self->weight_previous({});
}
method create_state(Index $index, AI::MXNet::NDArray $weight)
{
return [
$self->momentum ? AI::MXNet::NDArray->zeros(
$weight->shape, ctx => $weight->context, dtype => $weight->dtype
) : undef,
$weight->copy
];
}
method update(
Index $index,
AI::MXNet::NDArray $weight,
AI::MXNet::NDArray $grad,
Maybe[AI::MXNet::NDArray] $state
lib/AI/MXNet/Optimizer.pm view on Meta::CPAN
{
$self->kwargs->{clip_gradient} = $self->clip_gradient;
}
}
method create_state(Index $index, AI::MXNet::NDArray $weight)
{
return [AI::MXNet::NDArray->zeros(
$weight->shape,
ctx => $weight->context,
dtype => $weight->dtype
), # mean
AI::MXNet::NDArray->zeros(
$weight->shape,
ctx => $weight->context,
dtype => $weight->dtype
) # variance
];
}
method update(
Index $index,
AI::MXNet::NDArray $weight,
AI::MXNet::NDArray $grad,
ArrayRef[AI::MXNet::NDArray] $state
)
lib/AI/MXNet/Optimizer.pm view on Meta::CPAN
has '+learning_rate' => (default => 0.002);
has 'beta1' => (is => "ro", isa => "Num", default => 0.9);
has 'beta2' => (is => "ro", isa => "Num", default => 0.999);
method create_state(Index $index, AI::MXNet::NDArray $weight)
{
return [
AI::MXNet::NDArray->zeros(
$weight->shape,
ctx => $weight->context,
dtype => $weight->dtype
), # mean
AI::MXNet::NDArray->zeros(
$weight->shape,
ctx => $weight->context,
dtype => $weight->dtype
) # variance
];
}
method update(
Index $index,
AI::MXNet::NDArray $weight,
AI::MXNet::NDArray $grad,
ArrayRef[AI::MXNet::NDArray] $state
)
lib/AI/MXNet/Optimizer.pm view on Meta::CPAN
has 'epsilon' => (is => "ro", isa => "Num", default => 1e-8);
has 'schedule_decay' => (is => "ro", isa => "Num", default => 0.004);
has 'm_schedule' => (is => "rw", default => 1, init_arg => undef);
method create_state(Index $index, AI::MXNet::NDArray $weight)
{
return [
AI::MXNet::NDArray->zeros(
$weight->shape,
ctx => $weight->context,
dtype => $weight->dtype
), # mean
AI::MXNet::NDArray->zeros(
$weight->shape,
ctx => $weight->context,
dtype => $weight->dtype
) # variance
];
}
method update(
Index $index,
AI::MXNet::NDArray $weight,
AI::MXNet::NDArray $grad,
ArrayRef[AI::MXNet::NDArray] $state
)
lib/AI/MXNet/RNN/Cell.pm view on Meta::CPAN
Parameters
----------
:$func : sub ref, default is AI::MXNet::Symbol->can('zeros')
Function for creating initial state.
Can be AI::MXNet::Symbol->can('zeros'),
AI::MXNet::Symbol->can('uniform'), AI::MXNet::Symbol->can('Variable') etc.
Use AI::MXNet::Symbol->can('Variable') if you want to directly
feed the input as states.
@kwargs :
more keyword arguments passed to func. For example
mean, std, dtype, etc.
Returns
-------
$states : ArrayRef[AI::MXNet::Symbol]
starting states for first RNN step
=cut
method begin_state(CodeRef :$func=AI::MXNet::Symbol->can('zeros'), @kwargs)
{
assert(
lib/AI/MXNet/RNN/Cell.pm view on Meta::CPAN
@$outputs = map { AI::MXNet::Symbol->expand_dims($_, axis => $axis) } @$outputs;
$outputs = AI::MXNet::Symbol->Concat(@$outputs, dim => $axis);
}
return($outputs, $states);
}
method _get_activation($inputs, $activation, @kwargs)
{
if(not ref $activation)
{
return AI::MXNet::Symbol->Activation($inputs, act_type => $activation, @kwargs);
}
else
{
return &{$activation}($inputs, @kwargs);
}
}
method _cells_state_shape($cells)
{
return [map { @{ $_->state_shape } } @$cells];
lib/AI/MXNet/RNN/Cell.pm view on Meta::CPAN
=head1 DESCRIPTION
Simple recurrent neural network cell
Parameters
----------
num_hidden : int
number of units in output symbol
activation : str or Symbol, default 'tanh'
type of activation function
prefix : str, default 'rnn_'
prefix for name of layers
(and name of weight if params is undef)
params : AI::MXNet::RNNParams or undef
container for weight sharing between cells.
created if undef.
=cut
has '_num_hidden' => (is => 'ro', init_arg => 'num_hidden', isa => 'Int', required => 1);
has 'forget_bias' => (is => 'ro', isa => 'Num');
lib/AI/MXNet/RNN/Cell.pm view on Meta::CPAN
weight => $self->_hW,
bias => $self->_hB,
num_hidden => $self->_num_hidden*4,
name => "${name}h2h"
);
my $gates = $i2h + $h2h;
my @slice_gates = @{ AI::MXNet::Symbol->SliceChannel(
$gates, num_outputs => 4, name => "${name}slice"
) };
my $in_gate = AI::MXNet::Symbol->Activation(
$slice_gates[0], act_type => "sigmoid", name => "${name}i"
);
my $forget_gate = AI::MXNet::Symbol->Activation(
$slice_gates[1], act_type => "sigmoid", name => "${name}f"
);
my $in_transform = AI::MXNet::Symbol->Activation(
$slice_gates[2], act_type => "tanh", name => "${name}c"
);
my $out_gate = AI::MXNet::Symbol->Activation(
$slice_gates[3], act_type => "sigmoid", name => "${name}o"
);
my $next_c = AI::MXNet::Symbol->_plus(
$forget_gate * $states[1], $in_gate * $in_transform,
name => "${name}state"
);
my $next_h = AI::MXNet::Symbol->_mul(
$out_gate,
AI::MXNet::Symbol->Activation(
$next_c, act_type => "tanh"
),
name => "${name}out"
);
return ($next_h, [$next_h, $next_c]);
}
package AI::MXNet::RNN::GRUCell;
use Mouse;
use AI::MXNet::Base;
lib/AI/MXNet/RNN/Cell.pm view on Meta::CPAN
);
my ($i2h_r, $i2h_z);
($i2h_r, $i2h_z, $i2h) = @{ AI::MXNet::Symbol->SliceChannel(
$i2h, num_outputs => 3, name => "${name}_i2h_slice"
) };
my ($h2h_r, $h2h_z);
($h2h_r, $h2h_z, $h2h) = @{ AI::MXNet::Symbol->SliceChannel(
$h2h, num_outputs => 3, name => "${name}_h2h_slice"
) };
my $reset_gate = AI::MXNet::Symbol->Activation(
$i2h_r + $h2h_r, act_type => "sigmoid", name => "${name}_r_act"
);
my $update_gate = AI::MXNet::Symbol->Activation(
$i2h_z + $h2h_z, act_type => "sigmoid", name => "${name}_z_act"
);
my $next_h_tmp = AI::MXNet::Symbol->Activation(
$i2h + $reset_gate * $h2h, act_type => "tanh", name => "${name}_h_act"
);
my $next_h = AI::MXNet::Symbol->_plus(
(1 - $update_gate) * $next_h_tmp, $update_gate * $prev_state_h,
name => "${name}out"
);
return ($next_h, [$next_h]);
}
package AI::MXNet::RNN::FusedCell;
use Mouse;
lib/AI/MXNet/RNN/Cell.pm view on Meta::CPAN
{
my $self = shift;
if(not $self->_prefix)
{
$self->_prefix($self->_mode.'_');
}
if(not defined $self->initializer)
{
$self->initializer(
AI::MXNet::Xavier->new(
factor_type => 'in',
magnitude => 2.34
)
);
}
if(not $self->initializer->isa('AI::MXNet::FusedRNN'))
{
$self->initializer(
AI::MXNet::FusedRNN->new(
init => $self->initializer,
num_hidden => $self->_num_hidden,
lib/AI/MXNet/RNN/Cell.pm view on Meta::CPAN
method pack_weights(HashRef[AI::MXNet::NDArray] $args)
{
my %args = %{ $args };
my $b = @{ $self->_directions };
my $m = $self->_num_gates;
my @c = @{ $self->_gate_names };
my $h = $self->_num_hidden;
my $w0 = $args{ sprintf('%sl0_i2h%s_weight', $self->_prefix, $c[0]) };
my $num_input = $w0->shape->[1];
my $total = ($num_input+$h+2)*$h*$m*$b + ($self->_num_layers-1)*$m*$h*($h+$b*$h+2)*$b;
my $arr = AI::MXNet::NDArray->zeros([$total], ctx => $w0->context, dtype => $w0->dtype);
my %nargs = $self->_slice_weights($arr, $num_input, $h);
while(my ($name, $nd) = each %nargs)
{
$nd .= delete $args{ $name };
}
$args{ $self->_parameter->name } = $arr;
return \%args;
}
method call(AI::MXNet::Symbol $inputs, SymbolOrArrayOfSymbols $states)
lib/AI/MXNet/RNN/Cell.pm view on Meta::CPAN
Dilation of Convolution operator in state-to-state transitions.
i2h_kernel : array ref of int, default (3, 3)
Kernel of Convolution operator in input-to-state transitions.
i2h_stride : array ref of int, default (1, 1)
Stride of Convolution operator in input-to-state transitions.
i2h_pad : array ref of int, default (1, 1)
Pad of Convolution operator in input-to-state transitions.
i2h_dilate : array ref of int, default (1, 1)
Dilation of Convolution operator in input-to-state transitions.
activation : str or Symbol,
default functools.partial(symbol.LeakyReLU, act_type='leaky', slope=0.2)
Type of activation function.
prefix : str, default 'ConvRNN_'
Prefix for name of layers (and name of weight if params is None).
params : RNNParams, default None
Container for weight sharing between cells. Created if None.
conv_layout : str, , default 'NCHW'
Layout of ConvolutionOp
=cut
has '+_h2h_kernel' => (default => sub { [3, 3] });
has '+_h2h_dilate' => (default => sub { [1, 1] });
has '+_i2h_kernel' => (default => sub { [3, 3] });
has '+_i2h_stride' => (default => sub { [1, 1] });
has '+_i2h_dilate' => (default => sub { [1, 1] });
has '+_i2h_pad' => (default => sub { [1, 1] });
has '+_prefix' => (default => 'ConvRNN_');
has '+_activation' => (default => sub { sub { AI::MXNet::Symbol->LeakyReLU(@_, act_type => 'leaky', slope => 0.2) } });
has '+i2h_bias_initializer' => (default => 'zeros');
has '+h2h_bias_initializer' => (default => 'zeros');
has 'forget_bias' => (is => 'ro', isa => 'Num');
has [qw/_iW _iB
_hW _hB/] => (is => 'rw', init_arg => undef);
sub BUILD
{
my $self = shift;
lib/AI/MXNet/RNN/Cell.pm view on Meta::CPAN
my ($i2h, $h2h) = $self->_conv_forward($inputs, $states, $name);
my $gates = $i2h + $h2h;
my @slice_gates = @{ AI::MXNet::Symbol->SliceChannel(
$gates,
num_outputs => 4,
axis => index($self->_conv_layout, 'C'),
name => "${name}slice"
) };
my $in_gate = AI::MXNet::Symbol->Activation(
$slice_gates[0],
act_type => "sigmoid",
name => "${name}i"
);
my $forget_gate = AI::MXNet::Symbol->Activation(
$slice_gates[1],
act_type => "sigmoid",
name => "${name}f"
);
my $in_transform = $self->_get_activation(
$slice_gates[2],
$self->_activation,
name => "${name}c"
);
my $out_gate = AI::MXNet::Symbol->Activation(
$slice_gates[3],
act_type => "sigmoid",
name => "${name}o"
);
my $next_c = AI::MXNet::Symbol->_plus(
$forget_gate * @{$states}[1],
$in_gate * $in_transform,
name => "${name}state"
);
my $next_h = AI::MXNet::Symbol->_mul(
$out_gate, $self->_get_activation($next_c, $self->_activation),
name => "${name}out"
lib/AI/MXNet/RNN/Cell.pm view on Meta::CPAN
method call(AI::MXNet::Symbol $inputs, AI::MXNet::Symbol|ArrayRef[AI::MXNet::Symbol] $states)
{
$self->_counter($self->_counter + 1);
my $name = sprintf('%st%d_', $self->_prefix, $self->_counter);
my ($i2h, $h2h) = $self->_conv_forward($inputs, $states, $name);
my ($i2h_r, $i2h_z, $h2h_r, $h2h_z);
($i2h_r, $i2h_z, $i2h) = @{ AI::MXNet::Symbol->SliceChannel($i2h, num_outputs => 3, name => "${name}_i2h_slice") };
($h2h_r, $h2h_z, $h2h) = @{ AI::MXNet::Symbol->SliceChannel($h2h, num_outputs => 3, name => "${name}_h2h_slice") };
my $reset_gate = AI::MXNet::Symbol->Activation(
$i2h_r + $h2h_r, act_type => "sigmoid",
name => "${name}_r_act"
);
my $update_gate = AI::MXNet::Symbol->Activation(
$i2h_z + $h2h_z, act_type => "sigmoid",
name => "${name}_z_act"
);
my $next_h_tmp = $self->_get_activation($i2h + $reset_gate * $h2h, $self->_activation, name => "${name}_h_act");
my $next_h = AI::MXNet::Symbol->_plus(
(1 - $update_gate) * $next_h_tmp, $update_gate * @{$states}[0],
name => "${name}out"
);
return ($next_h, [$next_h]);
}
lib/AI/MXNet/RNN/IO.pm view on Meta::CPAN
=head2 new
Parameters
----------
sentences : array ref of array refs of int
encoded sentences
batch_size : int
batch_size of data
invalid_label : int, default -1
key for invalid label, e.g. <end-of-sentence>
dtype : str, default 'float32'
data type
buckets : array ref of int
size of data buckets. Automatically generated if undef.
data_name : str, default 'data'
name of data
label_name : str, default 'softmax_label'
name of label
layout : str
format of data and label. 'NT' means (batch_size, length)
and 'TN' means (length, batch_size).
=cut
use Mouse;
use AI::MXNet::Base;
use List::Util qw(shuffle max);
extends 'AI::MXNet::DataIter';
has 'sentences' => (is => 'ro', isa => 'ArrayRef[ArrayRef]', required => 1);
has '+batch_size' => (is => 'ro', isa => 'Int', required => 1);
has 'invalid_label' => (is => 'ro', isa => 'Int', default => -1);
has 'data_name' => (is => 'ro', isa => 'Str', default => 'data');
has 'label_name' => (is => 'ro', isa => 'Str', default => 'softmax_label');
has 'dtype' => (is => 'ro', isa => 'Dtype', default => 'float32');
has 'layout' => (is => 'ro', isa => 'Str', default => 'NT');
has 'buckets' => (is => 'rw', isa => 'Maybe[ArrayRef[Int]]');
has [qw/data nddata ndlabel
major_axis default_bucket_key
provide_data provide_label
idx curr_idx
/] => (is => 'rw', init_arg => undef);
sub BUILD
{
lib/AI/MXNet/RNN/IO.pm view on Meta::CPAN
{
my $buck = bisect_left($self->buckets, scalar(@{ $self->sentences->[$i] }));
if($buck == @{ $self->buckets })
{
$ndiscard += 1;
next;
}
my $buff = AI::MXNet::NDArray->full(
[$self->buckets->[$buck]],
$self->invalid_label,
dtype => $self->dtype
)->aspdl;
$buff->slice([0, @{ $self->sentences->[$i] }-1]) .= pdl($self->sentences->[$i]);
push @{ $self->data->[$buck] }, $buff;
}
$self->data([map { pdl(PDL::Type->new(DTYPE_MX_TO_PDL->{$self->dtype}), $_) } @{$self->data}]);
AI::MXNet::Logging->warning("discarded $ndiscard sentences longer than the largest bucket.")
if $ndiscard;
$self->nddata([]);
$self->ndlabel([]);
$self->major_axis(index($self->layout, 'N'));
$self->default_bucket_key(max(@{ $self->buckets }));
my $shape;
if($self->major_axis == 0)
{
$shape = [$self->batch_size, $self->default_bucket_key];
lib/AI/MXNet/RNN/IO.pm view on Meta::CPAN
$shape = [$self->default_bucket_key, $self->batch_size];
}
else
{
confess("Invalid layout ${\ $self->layout }: Must by NT (batch major) or TN (time major)");
}
$self->provide_data([
AI::MXNet::DataDesc->new(
name => $self->data_name,
shape => $shape,
dtype => $self->dtype,
layout => $self->layout
)
]);
$self->provide_label([
AI::MXNet::DataDesc->new(
name => $self->label_name,
shape => $shape,
dtype => $self->dtype,
layout => $self->layout
)
]);
$self->idx([]);
enumerate(sub {
my ($i, $buck) = @_;
my $buck_len = $buck->shape->at(-1);
for my $j (0..($buck_len - $self->batch_size))
{
if(not $j%$self->batch_size)
lib/AI/MXNet/RNN/IO.pm view on Meta::CPAN
$self->curr_idx(0);
@{ $self->idx } = shuffle(@{ $self->idx });
$self->nddata([]);
$self->ndlabel([]);
for my $buck (@{ $self->data })
{
$buck = pdl_shuffle($buck);
my $label = $buck->zeros;
$label->slice([0, -2], 'X') .= $buck->slice([1, -1], 'X');
$label->slice([-1, -1], 'X') .= $self->invalid_label;
push @{ $self->nddata }, AI::MXNet::NDArray->array($buck, dtype => $self->dtype);
push @{ $self->ndlabel }, AI::MXNet::NDArray->array($label, dtype => $self->dtype);
}
}
method next()
{
return undef if($self->curr_idx == @{ $self->idx });
my ($i, $j) = @{ $self->idx->[$self->curr_idx] };
$self->curr_idx($self->curr_idx + 1);
my ($data, $label);
if($self->major_axis == 1)
lib/AI/MXNet/RNN/IO.pm view on Meta::CPAN
}
return AI::MXNet::DataBatch->new(
data => [$data],
label => [$label],
bucket_key => $self->buckets->[$i],
pad => 0,
provide_data => [
AI::MXNet::DataDesc->new(
name => $self->data_name,
shape => $data->shape,
dtype => $self->dtype,
layout => $self->layout
)
],
provide_label => [
AI::MXNet::DataDesc->new(
name => $self->label_name,
shape => $label->shape,
dtype => $self->dtype,
layout => $self->layout
)
],
);
}
1;
lib/AI/MXNet/RecordIO.pm view on Meta::CPAN
method unpack(Str $s)
{
my $h;
my $h_size = 24;
($h, $s) = (substr($s, 0, $h_size), substr($s, $h_size));
my $header = AI::MXNet::IRHeader->new(unpack('IfQQ', $h));
if($header->flag > 0)
{
my $label;
($label, $s) = (substr($s, 0, 4*$header->flag), substr($s, 4*$header->flag));
my $pdl_type = PDL::Type->new(DTYPE_MX_TO_PDL->{float32});
my $pdl = PDL->new_from_specification($pdl_type, $header->flag);
${$pdl->get_dataref} = $label;
$pdl->upd_data;
$header->label($pdl);
}
return ($header, $s)
}
=head2 pack
pack a string into MXImageRecord
lib/AI/MXNet/RecordIO.pm view on Meta::CPAN
method pack(AI::MXNet::IRHeader|ArrayRef $header, Str $s)
{
$header = AI::MXNet::IRHeader->new(@$header) unless blessed $header;
if(not ref $header->label)
{
$header->flag(0);
}
else
{
my $label = AI::MXNet::NDArray->array($header->label, dtype=>'float32')->aspdl;
$header->label(0);
$header->flag($label->nelem);
my $buf = ${$label->get_dataref};
$s = "$buf$s";
}
$s = pack('IfQQ', @{ $header }) . $s;
return $s;
}
package AI::MXNet::IndexedRecordIO;
lib/AI/MXNet/RecordIO.pm view on Meta::CPAN
AI::MXNet::IndexedRecordIO - Read/write RecordIO format data supporting random access.
=cut
=head2 new
Parameters
----------
idx_path : str
Path to index file
uri : str
Path to record file. Only support file types that are seekable.
flag : str
'w' for write or 'r' for read
=cut
has 'idx_path' => (is => 'ro', isa => 'Str', required => 1);
has [qw/idx
keys fidx/] => (is => 'rw', init_arg => undef);
method open()
{
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
method call(@args)
{
my $s = $self->deepcopy();
$s->_compose(@args);
return $s;
}
method slice(Str|Index $index)
{
## __getitem__ tie needs to die
if(not find_type_constraint('Index')->check($index))
{
my $i = 0;
my $idx;
for my $name (@{ $self->list_outputs() })
{
if($name eq $index)
{
if(defined $idx)
{
confess(qq/There are multiple outputs with name "$index"/);
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
Examples
--------
>>> my $bn = mx->sym->BatchNorm(name=>'bn');
=cut
method list_inputs()
{
return scalar(check_call(AI::NNVMCAPI::SymbolListInputNames($self->handle, 0)));
}
=head2 infer_type
Infer the type of outputs and arguments of given known types of arguments.
User can either pass in the known types in positional way or keyword argument way.
Tuple of Nones is returned if there is not enough information passed in.
An error will be raised if there is inconsistency found in the known types passed in.
Parameters
----------
args : Array
Provide type of arguments in a positional way.
Unknown type can be marked as None
kwargs : Hash ref, must ne ssupplied as as sole argument to the method.
Provide keyword arguments of known types.
Returns
-------
arg_types : array ref of Dtype or undef
List of types of arguments.
The order is in the same order as list_arguments()
out_types : array ref of Dtype or undef
List of types of outputs.
The order is in the same order as list_outputs()
aux_types : array ref of Dtype or undef
List of types of outputs.
The order is in the same order as list_auxiliary()
=cut
method infer_type(Str|Undef @args)
{
my ($positional_arguments, $kwargs, $kwargs_order) = _parse_arguments("Dtype", @args);
my $sdata = [];
my $keys = [];
if(@$positional_arguments)
{
@{ $sdata } = map { defined($_) ? DTYPE_STR_TO_MX->{ $_ } : -1 } @{ $positional_arguments };
}
else
{
@{ $keys } = @{ $kwargs_order };
@{ $sdata } = map { DTYPE_STR_TO_MX->{ $_ } } @{ $kwargs }{ @{ $kwargs_order } };
}
my ($arg_type, $out_type, $aux_type, $complete) = check_call(AI::MXNetCAPI::SymbolInferType(
$self->handle,
scalar(@{ $sdata }),
$keys,
$sdata
)
);
if($complete)
{
return (
[ map { DTYPE_MX_TO_STR->{ $_ } } @{ $arg_type }],
[ map { DTYPE_MX_TO_STR->{ $_ } } @{ $out_type }],
[ map { DTYPE_MX_TO_STR->{ $_ } } @{ $aux_type }]
);
}
else
{
return (undef, undef, undef);
}
}
=head2 infer_shape
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
push @$arg_handles, defined($tmp{ $name }) ? $tmp{ $name }->handle : undef;
push @$arg_arrays, defined($tmp{ $name }) ? $tmp{ $name } : undef;
}
}
return ($arg_handles, $arg_arrays);
}
=head2 simple_bind
Bind current symbol to get an executor, allocate all the ndarrays needed.
Allows specifying data types.
This function will ask user to pass in ndarray of position
they like to bind to, and it will automatically allocate the ndarray
for arguments and auxiliary states that user did not specify explicitly.
Parameters
----------
:$ctx : AI::MXNet::Context
The device context the generated executor to run on.
:$grad_req: string
{'write', 'add', 'null'}, or list of str or dict of str to str, optional
Specifies how we should update the gradient to the args_grad.
- 'write' means everytime gradient is write to specified args_grad NDArray.
- 'add' means everytime gradient is add to the specified NDArray.
- 'null' means no action is taken, the gradient may not be calculated.
:$type_dict : hash ref of str->Dtype
Input type map, name->dtype
:$group2ctx : hash ref of string to AI::MXNet::Context
The mapping of the ctx_group attribute to the context assignment.
:$shapes : hash ref of str->Shape
Input shape map, name->shape
:$shared_arg_names : Maybe[ArrayRef[Str]]
The argument names whose 'NDArray' of shared_exec can be reused for initializing
the current executor.
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
Returns
-------
$executor : AI::MXNet::Executor
The generated Executor
=cut
method simple_bind(
AI::MXNet::Context :$ctx=AI::MXNet::Context->current_ctx,
GradReq|ArrayRef[GradReq]|HashRef[GradReq] :$grad_req='write',
Maybe[HashRef[Shape]] :$shapes=,
Maybe[HashRef[Dtype]] :$type_dict=,
Maybe[HashRef[AI::MXNet::Context]] :$group2ctx=,
Maybe[ArrayRef[Str]] :$shared_arg_names=,
Maybe[AI::MXNet::Executor] :$shared_exec=,
Maybe[HashRef[AI::MXNet::NDArray]] :$shared_buffer=
)
{
my $num_provided_arg_types;
my @provided_arg_type_names;
my @provided_arg_type_data;
if(defined $type_dict)
{
while(my ($k, $v) = each %{ $type_dict })
{
push @provided_arg_type_names, $k;
push @provided_arg_type_data, DTYPE_STR_TO_MX->{$v};
}
$num_provided_arg_types = @provided_arg_type_names;
}
my @provided_arg_shape_data;
# argument shape index in sdata,
# e.g. [sdata[indptr[0]], sdata[indptr[1]]) is the shape of the first arg
my @provided_arg_shape_idx = (0);
my @provided_arg_shape_names;
while(my ($k, $v) = each %{ $shapes//{} })
{
push @provided_arg_shape_names, $k;
push @provided_arg_shape_data, @{ $v };
push @provided_arg_shape_idx, scalar(@provided_arg_shape_data);
}
$num_provided_arg_types = @provided_arg_type_names;
my $provided_req_type_list_len = 0;
my @provided_grad_req_types;
my @provided_grad_req_names;
if(defined $grad_req)
{
if(not ref $grad_req)
{
push @provided_grad_req_types, $grad_req;
}
elsif(ref $grad_req eq 'ARRAY')
{
assert((@{ $grad_req } != 0), 'grad_req in simple_bind cannot be an empty list');
@provided_grad_req_types = @{ $grad_req };
$provided_req_type_list_len = @provided_grad_req_types;
}
elsif(ref $grad_req eq 'HASH')
{
assert((keys %{ $grad_req } != 0), 'grad_req in simple_bind cannot be an empty hash');
while(my ($k, $v) = each %{ $grad_req })
{
push @provided_grad_req_names, $k;
push @provided_grad_req_types, $v;
}
$provided_req_type_list_len = @provided_grad_req_types;
}
}
my $num_ctx_map_keys = 0;
my @ctx_map_keys;
my @ctx_map_dev_types;
my @ctx_map_dev_ids;
if(defined $group2ctx)
{
while(my ($k, $v) = each %{ $group2ctx })
{
push @ctx_map_keys, $k;
push @ctx_map_dev_types, $v->device_type_id;
push @ctx_map_dev_ids, $v->device_id;
}
$num_ctx_map_keys = @ctx_map_keys;
}
my @shared_arg_name_list;
if(defined $shared_arg_names)
{
@shared_arg_name_list = @{ $shared_arg_names };
}
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
$arg_grad_handles,
$aux_state_handles,
$exe_handle
);
eval {
($updated_shared_data, $in_arg_handles, $arg_grad_handles, $aux_state_handles, $exe_handle)
=
check_call(
AI::MXNetCAPI::ExecutorSimpleBind(
$self->handle,
$ctx->device_type_id,
$ctx->device_id,
$num_ctx_map_keys,
\@ctx_map_keys,
\@ctx_map_dev_types,
\@ctx_map_dev_ids,
$provided_req_type_list_len,
\@provided_grad_req_names,
\@provided_grad_req_types,
scalar(@provided_arg_shape_names),
\@provided_arg_shape_names,
\@provided_arg_shape_data,
\@provided_arg_shape_idx,
$num_provided_arg_types,
\@provided_arg_type_names,
\@provided_arg_type_data,
scalar(@shared_arg_name_list),
\@shared_arg_name_list,
defined $shared_buffer ? \%shared_data : undef,
$shared_exec_handle
)
);
};
if($@)
{
confess(
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
Bind current symbol to get an executor.
Parameters
----------
:$ctx : AI::MXNet::Context
The device context the generated executor to run on.
:$args : HashRef[AI::MXNet::NDArray]|ArrayRef[AI::MXNet::NDArray]
Input arguments to the symbol.
- If type is array ref of NDArray, the position is in the same order of list_arguments.
- If type is hash ref of str to NDArray, then it maps the name of arguments
to the corresponding NDArray.
- In either case, all the arguments must be provided.
:$args_grad : Maybe[HashRef[AI::MXNet::NDArray]|ArrayRef[AI::MXNet::NDArray]]
When specified, args_grad provide NDArrays to hold
the result of gradient value in backward.
- If type is array ref of NDArray, the position is in the same order of list_arguments.
- If type is hash ref of str to NDArray, then it maps the name of arguments
to the corresponding NDArray.
- When the type is hash ref of str to NDArray, users only need to provide the dict
for needed argument gradient.
Only the specified argument gradient will be calculated.
:$grad_req : {'write', 'add', 'null'}, or array ref of str or hash ref of str to str, optional
Specifies how we should update the gradient to the args_grad.
- 'write' means everytime gradient is write to specified args_grad NDArray.
- 'add' means everytime gradient is add to the specified NDArray.
- 'null' means no action is taken, the gradient may not be calculated.
:$aux_states : array ref of NDArray, or hash ref of str to NDArray, optional
Input auxiliary states to the symbol, only need to specify when
list_auxiliary_states is not empty.
- If type is array ref of NDArray, the position is in the same order of list_auxiliary_states
- If type is hash ref of str to NDArray, then it maps the name of auxiliary_states
to the corresponding NDArray,
- In either case, all the auxiliary_states need to be provided.
:$group2ctx : hash ref of string to AI::MXNet::Context
The mapping of the ctx_group attribute to the context assignment.
:$shared_exec : AI::MXNet::Executor
Executor to share memory with. This is intended for runtime reshaping, variable length
sequences, etc. The returned executor shares state with shared_exec, and should not be
used in parallel with it.
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
push @{ $req_array }, $req_map->{ $grad_req->{ $name } };
}
else
{
push @{ $req_array }, 0;
}
}
}
my $ctx_map_keys = [];
my $ctx_map_dev_types = [];
my $ctx_map_dev_ids = [];
if(defined $group2ctx)
{
while(my ($key, $val) = each %{ $group2ctx })
{
push @{ $ctx_map_keys } , $key;
push @{ $ctx_map_dev_types }, $val->device_type_id;
push @{ $ctx_map_dev_ids }, $val->device_id;
}
}
my $shared_handle = $shared_exec->handle if $shared_exec;
my $handle = check_call(AI::MXNetCAPI::ExecutorBindEX(
$self->handle,
$ctx->device_type_id,
$ctx->device_id,
scalar(@{ $ctx_map_keys }),
$ctx_map_keys,
$ctx_map_dev_types,
$ctx_map_dev_ids,
scalar(@{ $args }),
$args_handle,
$args_grad_handle,
$req_array,
scalar(@{ $aux_states }),
$aux_args_handle,
$shared_handle
)
);
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
Eval allows simpler syntax for less cumbersome introspection.
Parameters
----------
:$ctx : Context
The device context the generated executor to run on.
Optional, defaults to cpu(0)
:$args array ref of NDArray or hash ref of NDArray
- If the type is an array ref of NDArray, the position is in the same order of list_arguments.
- If the type is a hash of str to NDArray, then it maps the name of the argument
to the corresponding NDArray.
- In either case, all arguments must be provided.
Returns
----------
result : an array ref of NDArrays corresponding to the values
taken by each symbol when evaluated on given args.
When called on a single symbol (not a group),
the result will be an array ref with one element.
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
attr : hash ref of string -> string
Additional attributes to set on the variable.
shape : array ref of positive integers
Optionally, one can specify the shape of a variable. This will be used during
shape inference. If user specified a different shape for this variable using
keyword argument when calling shape inference, this shape information will be ignored.
lr_mult : float
Specify learning rate muliplier for this variable.
wd_mult : float
Specify weight decay muliplier for this variable.
dtype : Dtype
Similar to shape, we can specify dtype for this variable.
init : initializer (mx->init->*)
Specify initializer for this variable to override the default initializer
kwargs : hash ref
other additional attribute variables
Returns
-------
variable : Symbol
The created variable symbol.
=cut
method Variable(
Str $name,
HashRef[Str] :$attr={},
Maybe[Shape] :$shape=,
Maybe[Num] :$lr_mult=,
Maybe[Num] :$wd_mult=,
Maybe[Dtype] :$dtype=,
Maybe[Initializer] :$init=,
HashRef[Str] :$kwargs={},
Maybe[Str] :$__layout__=
)
{
my $handle = check_call(AI::MXNetCAPI::SymbolCreateVariable($name));
my $ret = __PACKAGE__->new(handle => $handle);
$attr = AI::MXNet::Symbol::AttrScope->current->get($attr);
$attr->{__shape__} = "(".join(',', @{ $shape }).")" if $shape;
$attr->{__lr_mult__} = $lr_mult if defined $lr_mult;
$attr->{__wd_mult__} = $wd_mult if defined $wd_mult;
$attr->{__dtype__} = DTYPE_STR_TO_MX->{ $dtype } if $dtype;
$attr->{__init__} = "$init" if defined $init;
$attr->{__layout__} = $__layout__ if defined $__layout__;
while(my ($k, $v) = each %{ $kwargs })
{
if($k =~ /^__/ and $k =~ /__$/)
{
$attr->{$k} = "$v";
}
else
{
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
--------
AI::MXNet::Symbol->tojson : Used to save symbol into json string.
=cut
method load_json(Str $json)
{
my $handle = check_call(AI::MXNetCAPI::SymbolCreateFromJSON($json));
return __PACKAGE__->new(handle => $handle);
}
method zeros(Shape :$shape, Dtype :$dtype='float32', Maybe[Str] :$name=, Maybe[Str] :$__layout__=)
{
return __PACKAGE__->_zeros({ shape => $shape, dtype => $dtype, name => $name, ($__layout__ ? (__layout__ => $__layout__) : ()) });
}
method ones(Shape :$shape, Dtype :$dtype='float32', Maybe[Str] :$name=, Maybe[Str] :$__layout__=)
{
return __PACKAGE__->_ones({ shape => $shape, dtype => $dtype, name => $name, ($__layout__ ? (__layout__ => $__layout__) : ()) });
}
=head2 arange
Simlar function in the MXNet ndarray as numpy.arange
See Also https://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html.
Parameters
----------
start : number
Start of interval. The interval includes this value. The default start value is 0.
stop : number, optional
End of interval. The interval does not include this value.
step : number, optional
Spacing between values
repeat : int, optional
"The repeating time of all elements.
E.g repeat=3, the element a will be repeated three times --> a, a, a.
dtype : type, optional
The value type of the NDArray, default to np.float32
Returns
-------
out : Symbol
The created Symbol
=cut
method arange(Index :$start=0, Index :$stop=, Num :$step=1.0, Index :$repeat=1, Maybe[Str] :$name=, Dtype :$dtype='float32')
{
return __PACKAGE__->_arange({
start => $start, (defined $stop ? (stop => $stop) : ()),
step => $step, repeat => $repeat, name => $name, dtype => $dtype
});
}
sub _parse_arguments
{
my $type = shift;
my @args = @_;
my $type_c = find_type_constraint($type);
my $str_c = find_type_constraint("Str");
my @positional_arguments;
my %kwargs;
my @kwargs_order;
my $only_dtypes_and_undefs = (@args == grep { not defined($_) or $type_c->check($_) } @args);
my $only_dtypes_and_strs = (@args == grep { $type_c->check($_) or $str_c->check($_) } @args);
if(@args % 2 and $only_dtypes_and_undefs)
{
@positional_arguments = @args;
}
else
{
if($only_dtypes_and_undefs)
{
@positional_arguments = @args;
}
elsif($only_dtypes_and_strs)
{
my %tmp = @args;
if(values(%tmp) == grep { $type_c->check($_) } values(%tmp))
{
%kwargs = %tmp;
my $i = 0;
@kwargs_order = grep { $i ^= 1 } @args;
}
else
{
confess("Argument need to be of type $type");
}
}
else
{
confess("Argument need to be one type $type");
}
}
return (\@positional_arguments, \%kwargs, \@kwargs_order);
}
sub _ufunc_helper
{
my ($lhs, $rhs, $fn_symbol, $lfn_scalar, $rfn_scalar, $reverse) = @_;
($rhs, $lhs) = ($lhs, $rhs) if $reverse and $rfn_scalar;
if(not ref $lhs)
lib/AI/MXNet/Symbol/Base.pm view on Meta::CPAN
AI::NNVMCAPI::SymbolCompose(
$self->handle, $name, $num_args, $keys, $args
)
);
}
# Create an atomic symbol function by handle and funciton name
func _make_atomic_symbol_function($handle, $name)
{
my ($real_name, $desc, $arg_names,
$arg_types, $arg_descs, $key_var_num_args,
$ret_type) = @{ check_call(AI::MXNetCAPI::SymbolGetAtomicSymbolInfo($handle)) };
$ret_type //= '';
my $func_name = $name;
my $doc_str = build_doc($func_name,
$desc,
$arg_names,
$arg_types,
$arg_descs,
$key_var_num_args,
$ret_type
);
my $creator = sub {
my $class = shift;
my (@args, %kwargs);
if(
@_
and
ref $_[-1] eq 'HASH'
and
not (@_ >= 2 and not blessed $_[-2] and $_[-2] eq 'attr')
lib/AI/MXNet/Symbol/Doc.pm view on Meta::CPAN
my $s_outputs = $sym->infer_shape(%input_shapes);
my %ret;
@ret{ @{ $sym->list_outputs() } } = @$s_outputs;
return bless \%ret, 'AI::MXNet::Util::Printable';
}
func build_doc(
Str $func_name,
Str $desc,
ArrayRef[Str] $arg_names,
ArrayRef[Str] $arg_types,
ArrayRef[Str] $arg_desc,
Str $key_var_num_args=,
Str $ret_type=
)
{
my $param_str = build_param_doc($arg_names, $arg_types, $arg_desc);
if($key_var_num_args)
{
$desc .= "\nThis function support variable length of positional input."
}
my $doc_str = sprintf("%s\n\n" .
"%s\n" .
"name : string, optional.\n" .
" Name of the resulting symbol.\n\n" .
"Returns\n" .
"-------\n" .