view release on metacpan or search on metacpan
Makefile.PL view on Meta::CPAN
my %FallbackPrereqs = (
"AI::MXNetCAPI" => "1.0102",
"AI::NNVMCAPI" => "1.01",
"Function::Parameters" => "1.0705",
"Mouse" => "v2.1.0",
"PDL" => "2.007",
"GraphViz" => "2.14"
);
unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
delete $WriteMakefileArgs{TEST_REQUIRES};
delete $WriteMakefileArgs{BUILD_REQUIRES};
$WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
}
delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
unless eval { ExtUtils::MakeMaker->VERSION(6.52) };
WriteMakefile(%WriteMakefileArgs);
examples/calculator.pl view on Meta::CPAN
my($batch_size, $func) = @_;
# get samples
my $n = 16384;
## creates a pdl with $n rows and two columns with random
## floats in the range between 0 and 1
my $data = PDL->random(2, $n);
## creates the pdl with $n rows and one column with labels
## labels are floats that either sum or product, etc of
## two random values in each corresponding row of the data pdl
my $label = $func->($data->slice('0,:'), $data->slice('1,:'));
# partition into train/eval sets
my $edge = int($n / 8);
my $validation_data = $data->slice(":,0:@{[ $edge - 1 ]}");
my $validation_label = $label->slice(":,0:@{[ $edge - 1 ]}");
my $train_data = $data->slice(":,$edge:");
my $train_label = $label->slice(":,$edge:");
# build iterators around the sets
return(mx->io->NDArrayIter(
batch_size => $batch_size,
data => $train_data,
label => $train_label,
examples/calculator.pl view on Meta::CPAN
$wide,
num_hidden => 1
);
return mx->sym->MAERegressionOutput(data => $fc, name => 'softmax');
}
sub learn_function {
my(%args) = @_;
my $func = $args{func};
my $batch_size = $args{batch_size}//128;
my($train_iter, $eval_iter) = samples($batch_size, $func);
my $sym = nn_fc();
## call as ./calculator.pl 1 to just print model and exit
if($ARGV[0]) {
my @dsz = @{$train_iter->data->[0][1]->shape};
my @lsz = @{$train_iter->label->[0][1]->shape};
my $shape = {
data => [ $batch_size, splice @dsz, 1 ],
softmax_label => [ $batch_size, splice @lsz, 1 ],
};
print mx->viz->plot_network($sym, shape => $shape)->graph->as_png;
exit;
}
my $model = mx->mod->Module(
symbol => $sym,
context => mx->cpu(),
);
$model->fit($train_iter,
eval_data => $eval_iter,
optimizer => 'adam',
optimizer_params => {
learning_rate => $args{lr}//0.01,
rescale_grad => 1/$batch_size,
lr_scheduler => AI::MXNet::FactorScheduler->new(
step => 100,
factor => 0.99
)
},
eval_metric => 'mse',
num_epoch => $args{epoch}//25,
);
# refit the model for calling on 1 sample at a time
my $iter = mx->io->NDArrayIter(
batch_size => 1,
data => PDL->pdl([[ 0, 0 ]]),
label => PDL->pdl([[ 0 ]]),
);
$model->reshape(
examples/char_lstm.pl view on Meta::CPAN
{
$contexts = mx->cpu(0);
}
my $model = mx->mod->Module(
symbol => $net,
context => $contexts
);
$model->fit(
$data_iter,
eval_metric => mx->metric->Perplexity,
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)
},
examples/cudnn_lstm_bucketing.pl view on Meta::CPAN
);
my ($arg_params, $aux_params);
if($load_epoch)
{
(undef, $arg_params, $aux_params) = mx->rnn->load_rnn_checkpoint(
$cell, $model_prefix, $load_epoch);
}
$model->fit(
$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,
},
begin_epoch => $load_epoch,
initializer => mx->init->Xavier(factor_type => "in", magnitude => 2.34),
num_epoch => $num_epoch,
examples/lstm_bucketing.pl view on Meta::CPAN
}
my $model = mx->mod->BucketingModule(
sym_gen => $sym_gen,
default_bucket_key => $data_train->default_bucket_key,
context => $contexts
);
$model->fit(
$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),
examples/mnist.pl view on Meta::CPAN
#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));
my $model = mx->mod->Module(
symbol => $mlp, # network structure
);
$model->fit(
$train_iter, # training data
num_epoch => 10, # number of data passes for training
eval_data => $val_iter, # validation data
batch_end_callback => mx->callback->Speedometer($batch_size, 200), # output progress for each 200 data batches
optimizer => 'adam',
);
lib/AI/MXNet.pm view on Meta::CPAN
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__
=encoding UTF-8
=head1 NAME
lib/AI/MXNet.pm view on Meta::CPAN
my $val_dataiter = mx->io->MNISTIter({
image=>"data/t10k-images-idx3-ubyte",
label=>"data/t10k-labels-idx1-ubyte",
data_shape=>[1, 28, 28],
batch_size=>$batch_size, shuffle=>1, flat=>0, silent=>0});
my $n_epoch = 1;
my $mod = mx->mod->new(symbol => $softmax);
$mod->fit(
$train_dataiter,
eval_data => $val_dataiter,
optimizer_params=>{learning_rate=>0.01, momentum=> 0.9},
num_epoch=>$n_epoch
);
my $res = $mod->score($val_dataiter, mx->metric->create('acc'));
ok($res->{accuracy} > 0.8);
=head1 DESCRIPTION
Perl interface to MXNet machine learning library.
lib/AI/MXNet/Callback.pm view on Meta::CPAN
my ($iter_no, $sym, $arg, $aux) = @_;
if(($iter_no + 1) % $period == 0)
{
$mod->save_checkpoint($prefix, $iter_no + 1, $save_optimizer_states);
}
}
}
=head2 log_train_metric
Callback to log the training evaluation result every period.
Parameters
----------
$period : Int
The number of batches after which to log the training evaluation metric.
$auto_reset : Bool
Whether to reset the metric after the logging.
Returns
-------
$callback : sub ref
The callback function that can be passed as iter_epoch_callback to fit.
=cut
method log_train_metric(Int $period, Int $auto_reset=0)
{
return sub {
my ($param) = @_;
if($param->nbatch % $period == 0 and defined $param->eval_metric)
{
my $name_value = $param->eval_metric->get_name_value;
while(my ($name, $value) = each %{ $name_value })
{
AI::MXNet::Logging->info(
"Iter[%d] Batch[%d] Train-%s=%f",
$param->epoch, $param->nbatch, $name, $value
);
}
$param->eval_metric->reset if $auto_reset;
}
}
}
package AI::MXNet::Speedometer;
use Mouse;
use Time::HiRes qw/time/;
extends 'AI::MXNet::Callback';
=head1 NAME
lib/AI/MXNet/Callback.pm view on Meta::CPAN
{
$self->init(0);
}
$self->last_count($count);
if($self->init)
{
if(($count % $self->frequent) == 0)
{
my $speed = $self->frequent * $self->batch_size / (time - $self->tic);
if(defined $param->eval_metric)
{
my $name_value = $param->eval_metric->get_name_value;
$param->eval_metric->reset if $self->auto_reset;
while(my ($name, $value) = each %{ $name_value })
{
AI::MXNet::Logging->info(
"Epoch[%d] Batch [%d]\tSpeed: %.2f samples/sec\tTrain-%s=%f",
$param->epoch, $count, $speed, $name, $value
);
}
}
else
{
lib/AI/MXNet/Callback.pm view on Meta::CPAN
{
my $count = $param->nbatch;
my $filled_len = int(0.5 + $self->length * $count / $self->total);
my $percents = int(100.0 * $count / $self->total) + 1;
my $prog_bar = ('=' x $filled_len) . ('-' x ($self->length - $filled_len));
print "[$prog_bar] $percents%\r";
}
*slice = \&call;
# Just logs the eval metrics at the end of an epoch.
package AI::MXNet::LogValidationMetricsCallback;
use Mouse;
extends 'AI::MXNet::Callback';
=head1 NAME
AI::MXNet::LogValidationMetricsCallback - A callback to log the eval metrics at the end of an epoch.
=cut
method call(AI::MXNet::BatchEndParam $param)
{
return unless defined $param->eval_metric;
my $name_value = $param->eval_metric->get_name_value;
while(my ($name, $value) = each %{ $name_value })
{
AI::MXNet::Logging->info(
"Epoch[%d] Validation-%s=%f",
$param->epoch, $name, $value
);
}
}
package AI::MXNet::Callback;
lib/AI/MXNet/Executor.pm view on Meta::CPAN
];
}
=head2 forward
Calculate the outputs specified by the bound symbol.
Parameters
----------
$is_train=0: bool, optional
whether this forward is for evaluation purpose. If True,
a backward call is expected to follow. Otherwise following
backward is invalid.
%kwargs
Additional specification of input arguments.
Examples
--------
>>> # doing forward by specifying data
>>> $texec->forward(1, data => $mydata);
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
{
push @out_grads_slice, $grad->copyto($self->contexts->[$i]);
}
}, $out_grads, $self->_p->output_layouts);
$exec->backward(\@out_grads_slice);
}, [0..@{ $self->_p->execs }-1], $self->_p->execs, $self->_p->slices);
}
=head2 update_metric
Accumulate the performance according to eval_metric on all devices.
Parameters
----------
eval_metric : AI::MXNet::EvalMetric
The metric used for evaluation.
labels : array ref of NDArray
Typically comes from label of AI::MXNet::DataBatch.
=cut
method update_metric(AI::MXNet::EvalMetric $eval_metric, ArrayRef[AI::MXNet::NDArray] $labels)
{
zip(sub {
my ($texec, $islice) = @_;
my @labels_slice;
zip(sub {
my ($label, $axis) = @_;
if($axis == 0)
{
# slicing NDArray along axis 0 can avoid copying
push @labels_slice, $label->slice([$islice->[0], $islice->[1]-1]);
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
begin => $islice->[0],
end => $islice->[1]
})->as_in_context($label->context);
push @labels_slice, $label_my_slice;
}
else
{
push @labels_slice, $label;
}
}, $labels, $self->_p->label_layouts);
$eval_metric->update(\@labels_slice, $texec->outputs);
}, $self->_p->execs, $self->_p->slices);
}
method _bind_ith_exec(
Int $i,
ArrayRef[AI::MXNet::DataDesc] $data_shapes,
Maybe[ArrayRef[AI::MXNet::DataDesc]] $label_shapes,
Maybe[AI::MXNet::DataParallelExecutorGroup] $shared_group
)
{
lib/AI/MXNet/Initializer.pm view on Meta::CPAN
num_layers/] => (is => 'ro', isa => 'Int', required => 1);
has 'mode' => (is => 'ro', isa => 'Str', required => 1);
has 'bidirectional' => (is => 'ro', isa => 'Bool', default => 0);
sub BUILD
{
my $self = shift;
if(not blessed $self->init)
{
my ($klass, $kwargs);
eval {
($klass, $kwargs) = @{ decode_json($self->init) };
};
confess("FusedRNN failed to init $@") if $@;
$self->init($self->get_init_registry->{ lc $klass }->new(%$kwargs));
}
}
method _init_weight($name, $arr)
{
my $cell = AI::MXNet::RNN::FusedCell->new(
lib/AI/MXNet/Metric.pm view on Meta::CPAN
package AI::MXNet::Metric;
use strict;
use warnings;
use AI::MXNet::Function::Parameters;
use Scalar::Util qw/blessed/;
=head1 NAME
AI::MXNet::Metric - Online evaluation metric module.
=cut
# Check to see if the two arrays are the same size.
sub _calculate_shape
{
my $input = shift;
my ($shape);
if(blessed($input))
{
if($input->isa('PDL'))
lib/AI/MXNet/Metric.pm view on Meta::CPAN
{
my ($label_shape, $pred_shape) = (_calculate_shape($labels), _calculate_shape($preds));
Carp::confess(
"Shape of labels $label_shape does not "
."match shape of predictions $pred_shape"
) unless $pred_shape == $label_shape;
}
=head1 DESCRIPTION
Base class of all evaluation metrics.
=cut
package AI::MXNet::EvalMetric;
use Mouse;
use overload '""' => sub {
return "EvalMetric: "
.Data::Dumper->new(
[shift->get_name_value()]
)->Purity(1)->Deepcopy(1)->Terse(1)->Dump
}, fallback => 1;
lib/AI/MXNet/Metric.pm view on Meta::CPAN
$self->sum_metric
+
((($label-$label_mean)*($pred-$pred_mean))->sum/$label->nelem)/(($label_stdv*$pred_stdv)->at(0))
);
$self->num_inst($self->num_inst + 1);
}, $labels, $preds);
}
=head1 DESCRIPTION
Custom evaluation metric that takes a sub ref.
Parameters
----------
eval_function : subref
Customized evaluation function.
name : str, optional
The name of the metric
allow_extra_outputs : bool
If true, the prediction outputs can have extra outputs.
This is useful in RNN, where the states are also produced
in outputs for forwarding.
=cut
package AI::MXNet::CustomMetric;
use Mouse;
use AI::MXNet::Base;
extends 'AI::MXNet::EvalMetric';
has 'eval_function' => (is => 'ro', isa => 'CodeRef');
has 'allow_extra_outputs' => (is => 'ro', isa => 'Int', default => 0);
method update(ArrayRef[AI::MXNet::NDArray] $labels, ArrayRef[AI::MXNet::NDArray] $preds)
{
AI::MXNet::Metric::check_label_shapes($labels, $preds)
unless $self->allow_extra_outputs;
zip(sub {
my ($label, $pred) = @_;
$label = $label->aspdl;
$pred = $pred->aspdl;
my $value = $self->eval_function->($label, $pred);
my $sum_metric = ref $value ? $value->[0] : $value;
my $num_inst = ref $value ? $value->[1] : 1;
$self->sum_metric($self->sum_metric + $sum_metric);
$self->num_inst($self->num_inst + $num_inst);
}, $labels, $preds);
}
package AI::MXNet::Metric;
=head2 create
Create an evaluation metric.
Parameters
----------
metric : str or sub ref
The name of the metric, or a function
providing statistics given pred, label NDArray.
=cut
my %metrics = qw/
acc AI::MXNet::Accuracy
lib/AI/MXNet/Metric.pm view on Meta::CPAN
{
my $composite_metric = AI::MXNet::CompositeEvalMetric->new();
for my $child_metric (@{ $metric })
{
$composite_metric->add(__PACKAGE__->create($child_metric, %kwargs))
}
return $composite_metric;
}
else
{
return AI::MXNet::CustomMetric->new(eval_function => $metric, %kwargs);
}
}
else
{
if(not exists $metrics{ lc($metric) })
{
my @metrics = keys %metrics;
Carp::confess("Metric must be either subref or one of [@metrics]");
}
return $metrics{ lc($metric) }->new(%kwargs);
lib/AI/MXNet/Module.pm view on Meta::CPAN
return $self->_p->_exec_group->get_states($merge_multi_context);
}
method set_states(:$states=, :$value=)
{
assert($self->binded and $self->params_initialized);
return $self->_p->_exec_group->set_states($states, $value);
}
method update_metric(
AI::MXNet::EvalMetric $eval_metric,
ArrayRef[AI::MXNet::NDArray] $labels
)
{
$self->_p->_exec_group->update_metric($eval_metric, $labels);
}
=head2 _sync_params_from_devices
Synchronize parameters from devices to CPU. This function should be called after
calling 'update' that updates the parameters on the devices, before one can read the
latest parameters from $self->_arg_params and $self->_aux_params.
=cut
method _sync_params_from_devices()
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
package AI::MXNet::BatchEndParam;
use Mouse;
use AI::MXNet::Function::Parameters;
has [qw/epoch nbatch/] => (is => 'rw', isa => 'Int');
has 'eval_metric' => (is => 'rw', isa => 'AI::MXNet::EvalMetric');
package AI::MXNet::Module::Base;
use Mouse;
use AI::MXNet::Base;
use Time::HiRes qw(time);
=head1 NAME
AI::MXNet::Module::Base - Base class for AI::MXNet::Module and AI::MXNet::Module::Bucketing
=cut
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
- symbol: the underlying symbolic graph for this module (if any)
This property is not necessarily constant. For example, for AI::MXNet::Module::Bucketing,
this property is simply the *current* symbol being used. For other modules,
this value might not be well defined.
When those intermediate-level API are implemented properly, the following
high-level API will be automatically available for a module:
- fit: train the module parameters on a data set
- predict: run prediction on a data set and collect outputs
- score: run prediction on a data set and evaluate performance
=cut
has 'logger' => (is => 'rw', default => sub { AI::MXNet::Logging->get_logger });
has '_symbol' => (is => 'rw', init_arg => 'symbol', isa => 'AI::MXNet::Symbol');
has [
qw/binded for_training inputs_need_grad
params_initialized optimizer_initialized/
] => (is => 'rw', isa => 'Bool', init_arg => undef, default => 0);
################################################################################
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
=cut
method forward_backward(AI::MXNet::DataBatch $data_batch)
{
$self->forward($data_batch, is_train => 1);
$self->backward();
}
=head2 score
Run prediction on eval_data and evaluate the performance according to
eval_metric.
Parameters
----------
$eval_data : AI::MXNet::DataIter
$eval_metric : AI::MXNet::EvalMetric
:$num_batch= : Maybe[Int]
Number of batches to run. Default is undef, indicating run until the AI::MXNet::DataIter
finishes.
:$batch_end_callback= : Maybe[Callback]
Could also be a array ref of functions.
:$reset=1 : Bool
Default 1, indicating whether we should reset $eval_data before starting
evaluating.
$epoch=0 : Int
Default is 0. For compatibility, this will be passed to callbacks (if any). During
training, this will correspond to the training epoch number.
=cut
method score(
AI::MXNet::DataIter $eval_data,
EvalMetric $eval_metric,
Maybe[Int] :$num_batch=,
Maybe[Callback]|ArrayRef[Callback] :$batch_end_callback=,
Maybe[Callback]|ArrayRef[Callback] :$score_end_callback=,
Bool :$reset=1,
Int :$epoch=0
)
{
assert($self->binded and $self->params_initialized);
$eval_data->reset if $reset;
if(not blessed $eval_metric or not $eval_metric->isa('AI::MXNet::EvalMetric'))
{
$eval_metric = AI::MXNet::Metric->create($eval_metric);
}
$eval_metric->reset();
my $actual_num_batch = 0;
my $nbatch = 0;
while(my $eval_batch = <$eval_data>)
{
last if (defined $num_batch and $nbatch == $num_batch);
$self->forward($eval_batch, is_train => 0);
$self->update_metric($eval_metric, $eval_batch->label);
if (defined $batch_end_callback)
{
my $batch_end_params = AI::MXNet::BatchEndParam->new(
epoch => $epoch,
nbatch => $nbatch,
eval_metric => $eval_metric
);
for my $callback (@{ _as_list($batch_end_callback) })
{
&{$callback}($batch_end_params);
}
}
$actual_num_batch++;
$nbatch++
}
if($score_end_callback)
{
my $params = AI::MXNet::BatchEndParam->new(
epoch => $epoch,
nbatch => $actual_num_batch,
eval_metric => $eval_metric,
);
for my $callback (@{ _as_list($score_end_callback) })
{
&{callback}($params);
}
}
return $eval_metric->get_name_value;
}
=head2 iter_predict
Iterate over predictions.
Parameters
----------
$eval_data : AI::MXNet::DataIter
:$num_batch= : Maybe[Int]
Default is undef, indicating running all the batches in the data iterator.
:$reset=1 : bool
Default is 1, indicating whether we should reset the data iter before start
doing prediction.
=cut
method iter_predict(AI::MXNet::DataIter $eval_data, Maybe[Int] :$num_batch=, Bool :$reset=1)
{
assert($self->binded and $self->params_initialized);
if($reset)
{
$eval_data->reset;
}
my $nbatch = 0;
my @out;
while(my $eval_batch = <$eval_data>)
{
last if defined $num_batch and $nbatch == $num_batch;
$self->forward($eval_batch, is_train => 0);
my $pad = $eval_batch->pad;
my $outputs = [
map { $_->slice([0, $_->shape->[0] - ($pad//0) - 1]) } @{ $self->get_outputs() }
];
push @out, [$outputs, $nbatch, $eval_batch];
$nbatch++;
}
return @out;
}
=head2 predict
Run prediction and collect the outputs.
Parameters
----------
$eval_data : AI::MXNet::DataIter
:$num_batch= : Maybe[Int]
Default is undef, indicating running all the batches in the data iterator.
:$merge_batches=1 : Bool
Default is 1.
:$reset=1 : Bool
Default is 1, indicating whether we should reset the data iter before start
doing prediction.
:$always_output_list=0 : Bool
Default is 0, see the doc for return values.
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
When $merge_batches is 0, the return value will be a nested array ref like
[[$out1_batch1, $out2_batch1], [$out1_batch2], ...]. This mode is useful because
in some cases (e.g. bucketing), the module does not necessarily produce the same
number of outputs.
The objects in the results are AI::MXNet::NDArray`s. If you need to work with pdl array,
just call ->aspdl() on each AI::MXNet::NDArray.
=cut
method predict(
AI::MXNet::DataIter $eval_data,
Maybe[Int] :$num_batch=, Bool :$merge_batches=1, Bool :$reset=1, Bool :$always_output_list=0
)
{
assert($self->binded and $self->params_initialized);
$eval_data->reset() if $reset;
my @output_list;
my $nbatch = 0;
while(my $eval_batch = <$eval_data>)
{
last if defined $num_batch and $nbatch == $num_batch;
$self->forward($eval_batch, is_train => 0);
my $pad = $eval_batch->pad;
my $outputs = [map { $_->slice([0, $_->shape->[0]-($pad//0)-1])->copy } @{ $self->get_outputs }];
push @output_list, $outputs;
}
return () unless @output_list;
if($merge_batches)
{
my $num_outputs = @{ $output_list[0] };
for my $out (@output_list)
{
unless(@{ $out } == $num_outputs)
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
return @output_list;
}
=head2 fit
Train the module parameters.
Parameters
----------
$train_data : AI::MXNet::DataIter
:$eval_data= : Maybe[AI::MXNet::DataIter]
If not undef, it will be used as a validation set to evaluate the performance
after each epoch.
:$eval_metric='acc' : str or AI::MXNet::EvalMetric subclass object.
Default is 'accuracy'. The performance measure used to display during training.
Other possible predefined metrics are:
'ce' (CrossEntropy), 'f1', 'mae', 'mse', 'rmse', 'top_k_accuracy'
:$epoch_end_callback= : Maybe[Callback]|ArrayRef[Callback] function or array ref of functions.
Each callback will be called with the current $epoch, $symbol, $arg_params
and $aux_params.
:$batch_end_callback= : Maybe[Callback]|ArrayRef[Callback] function or array ref of functions.
Each callback will be called with a AI::MXNet::BatchEndParam.
:$kvstore='local' : str or AI::MXNet::KVStore
Default is 'local'.
:$optimizer : str or AI::MXNet::Optimizer
Default is 'sgd'
:$optimizer_params : hash ref
Default { learning_rate => 0.01 }.
The parameters for the optimizer constructor.
:$eval_end_callback= : Maybe[Callback]|ArrayRef[Callback] function or array ref of functions
These will be called at the end of each full evaluation, with the metrics over
the entire evaluation set.
:$eval_batch_end_callback : Maybe[Callback]|ArrayRef[Callback] function or array ref of functions
These will be called at the end of each minibatch during evaluation
:$initializer= : Initializer
Will be called to initialize the module parameters if not already initialized.
:$arg_params= : hash ref
Default undef, if not undef, must be an existing parameters from a trained
model or loaded from a checkpoint (previously saved model). In this case,
the value here will be used to initialize the module parameters, unless they
are already initialized by the user via a call to init_params or fit.
$arg_params have higher priority than the $initializer.
:$aux_params= : hash ref
Default is undef. This is similar to the $arg_params, except for auxiliary states.
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
Default is 0. Indicates the starting epoch. Usually, if we are resuming from a
checkpoint saved at a previous training phase at epoch N, then we should specify
this value as N+1.
:$num_epoch : Int
Number of epochs for the training.
=cut
method fit(
AI::MXNet::DataIter $train_data,
Maybe[AI::MXNet::DataIter] :$eval_data=,
EvalMetric :$eval_metric='acc',
Maybe[Callback]|ArrayRef[Callback] :$epoch_end_callback=,
Maybe[Callback]|ArrayRef[Callback] :$batch_end_callback=,
Str :$kvstore='local',
Optimizer :$optimizer='sgd',
HashRef :$optimizer_params={ learning_rate => 0.01 },
Maybe[Callback]|ArrayRef[Callback] :$eval_end_callback=,
Maybe[Callback]|ArrayRef[Callback] :$eval_batch_end_callback=,
AI::MXNet::Initializer :$initializer=AI::MXNet::Initializer->Uniform(scale => 0.01),
Maybe[HashRef[AI::MXNet::NDArray]] :$arg_params=,
Maybe[HashRef[AI::MXNet::NDArray]] :$aux_params=,
Bool :$allow_missing=0,
Bool :$force_rebind=0,
Bool :$force_init=0,
Int :$begin_epoch=0,
Int :$num_epoch,
Maybe[EvalMetric] :$validation_metric=,
Maybe[AI::MXNet::Monitor] :$monitor=
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
force_init => $force_init
);
$self->init_optimizer(
kvstore => $kvstore,
optimizer => $optimizer,
optimizer_params => $optimizer_params
);
if(not defined $validation_metric)
{
$validation_metric = $eval_metric;
}
$eval_metric = AI::MXNet::Metric->create($eval_metric)
unless blessed $eval_metric;
################################################################################
# training loop
################################################################################
for my $epoch ($begin_epoch..$num_epoch-1)
{
my $tic = time;
$eval_metric->reset;
my $nbatch = 0;
my $end_of_batch = 0;
my $next_data_batch = <$train_data>;
while(not $end_of_batch)
{
my $data_batch = $next_data_batch;
$monitor->tic if $monitor;
$self->forward_backward($data_batch);
$self->update;
$next_data_batch = <$train_data>;
if(defined $next_data_batch)
{
$self->prepare($next_data_batch);
}
else
{
$end_of_batch = 1;
}
$self->update_metric($eval_metric, $data_batch->label);
$monitor->toc_print if $monitor;
if(defined $batch_end_callback)
{
my $batch_end_params = AI::MXNet::BatchEndParam->new(
epoch => $epoch,
nbatch => $nbatch,
eval_metric => $eval_metric
);
for my $callback (@{ _as_list($batch_end_callback) })
{
&{$callback}($batch_end_params);
}
}
$nbatch++;
}
# one epoch of training is finished
my $name_value = $eval_metric->get_name_value;
while(my ($name, $val) = each %{ $name_value })
{
$self->logger->info('Epoch[%d] Train-%s=%f', $epoch, $name, $val);
}
my $toc = time;
$self->logger->info('Epoch[%d] Time cost=%.3f', $epoch, ($toc-$tic));
# sync aux params across devices
my ($arg_params, $aux_params) = $self->get_params;
$self->set_params($arg_params, $aux_params);
if($epoch_end_callback)
{
for my $callback (@{ _as_list($epoch_end_callback) })
{
&{$callback}($epoch, $self->get_symbol, $arg_params, $aux_params);
}
}
#----------------------------------------
# evaluation on validation set
if(defined $eval_data)
{
my $res = $self->score(
$eval_data,
$validation_metric,
score_end_callback => $eval_end_callback,
batch_end_callback => $eval_batch_end_callback,
epoch => $epoch
);
#TODO: pull this into default
while(my ($name, $val) = each %{ $res })
{
$self->logger->info('Epoch[%d] Validation-%s=%f', $epoch, $name, $val);
}
}
# end of 1 epoch, reset the data-iter for another epoch
$train_data->reset;
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
=head2 update
Update parameters according to the installed optimizer and the gradients computed
in the previous forward-backward batch.
=cut
method update() { confess("NotImplemented") }
=head2 update_metric
Evaluate and accumulate evaluation metric on outputs of the last forward computation.
Parameters
----------
$eval_metric : EvalMetric
$labels : ArrayRef[AI::MXNet::NDArray]
Typically $data_batch->label.
=cut
method update_metric(EvalMetric $eval_metric, ArrayRef[AI::MXNet::NDArray] $labels)
{
confess("NotImplemented")
}
################################################################################
# module setup
################################################################################
=head2 bind
lib/AI/MXNet/Module/Bucketing.pm view on Meta::CPAN
}
my $model = mx->mod->BucketingModule(
sym_gen => $sym_gen,
default_bucket_key => $data_train->default_bucket_key,
context => $contexts
);
$model->fit(
$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),
lib/AI/MXNet/Module/Bucketing.pm view on Meta::CPAN
return $self->_curr_module->get_outputs($merge_multi_context);
}
method get_input_grads(Bool $merge_multi_context=1)
{
assert($self->binded and $self->params_initialized and $self->inputs_need_grad);
return $self->_curr_module->get_input_grads($merge_multi_context);
}
method update_metric(
AI::MXNet::EvalMetric $eval_metric,
ArrayRef[AI::MXNet::NDArray] $labels
)
{
assert($self->binded and $self->params_initialized);
$self->_curr_module->update_metric($eval_metric, $labels);
}
method symbol()
{
assert($self->binded);
return $self->_curr_module->symbol;
}
method get_symbol()
{
lib/AI/MXNet/Monitor.pm view on Meta::CPAN
);
has 'pattern' => (is => 'ro', isa => 'Str', default => '.*');
has '_sort' => (is => 'ro', isa => 'Bool', init_arg => 'sort', default => 0);
has [qw/queue exes/] => (is => 'rw', init_arg => undef, default => sub { [] });
has [qw/step activated/] => (is => 'rw', init_arg => undef, default => 0);
has 're_pattern' => (
is => 'ro',
init_arg => undef,
default => sub {
my $pattern = shift->pattern;
my $re = eval { qr/$pattern/ };
confess("pattern $pattern failed to compile as a regexp $@")
if $@;
return $re;
},
lazy => 1
);
has 'stat_helper' => (
is => 'ro',
init_arg => undef,
default => sub {
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
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 ])
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
{
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;
}
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
$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/Symbol.pm view on Meta::CPAN
zip(sub {
my ($name, $shape) = @_;
if(not ref $shape or not @$shape or not product(@$shape))
{
if(@unknowns >= 10)
{
$unknowns[10] = '...';
}
else
{
my @shape = eval { @$shape };
push @unknowns, "$name @shape";
}
}
}, $arg_names, $arg_shapes);
AI::MXNet::Logging->warning(
"Cannot decide shape for the following arguments "
."(0s in shape means unknown dimensions). "
."Consider providing them as input:\n\t"
."\n\t"
.join(", ", @unknowns)
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
}
}
my $shared_exec_handle = defined $shared_exec ? $shared_exec->handle : undef;
my (
$updated_shared_data,
$in_arg_handles,
$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,
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
ctx => $ctx,
grad_req => $grad_req,
group2ctx => $group2ctx
);
$executor->arg_arrays($args);
$executor->grad_arrays($args_grad);
$executor->aux_arrays($aux_states);
return $executor;
}
=head2 eval
Evaluate a symbol given arguments
The `eval` method combines a call to `bind` (which returns an executor)
with a call to `forward` (executor method).
For the common use case, where you might repeatedly evaluate with same arguments,
eval is slow.
In that case, you should call `bind` once and then repeatedly call forward.
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.
Examples:
my $result = $symbol->eval(ctx => mx->gpu, args => {data => mx->nd->ones([5,5])});
my $result = $symbol->eval(args => {data => mx->nd->ones([5,5])});
=cut
method eval(:$ctx=AI::MXNet::Context->cpu, HashRef[AI::MXNet::NDArray]|ArrayRef[AI::MXNet::NDArray] :$args)
{
return $self->bind(ctx => $ctx, args => $args)->forward;
}
=head2 grad
Get the autodiff of current symbol.
This function can only be used if current symbol is a loss function.
Parameters
lib/AI/MXNet/TestUtils.pm view on Meta::CPAN
{
$array1 -= 1;
return 0
}
$array1 -= 1;
return same($array1->aspdl, $array2->aspdl);
}
func dies_like($code, $regexp)
{
eval { $code->() };
if($@ =~ $regexp)
{
return 1;
}
else
{
warn $@;
return 0;
}
}
lib/AI/MXNet/Visualization.pm view on Meta::CPAN
method plot_network(
AI::MXNet::Symbol $symbol,
Str :$title='plot',
Str :$save_format='ps',
Maybe[HashRef[Shape]] :$shape=,
HashRef[Str] :$node_attrs={},
Bool :$hide_weights=1
)
{
eval { require GraphViz; };
Carp::confess("plot_network requires GraphViz module") if $@;
my $draw_shape;
my %shape_dict;
if(defined $shape)
{
$draw_shape = 1;
my $interals = $symbol->get_internals;
my (undef, $out_shapes, undef) = $interals->infer_shape(%{ $shape });
Carp::confess("Input shape is incomplete")
unless defined $out_shapes;
t/test_conv.t view on Meta::CPAN
my $val_dataiter = mx->io->MNISTIter({
image=>"data/t10k-images-idx3-ubyte",
label=>"data/t10k-labels-idx1-ubyte",
data_shape=>[1, 28, 28],
batch_size=>$batch_size, shuffle=>1, flat=>0, silent=>0});
my $n_epoch = 1;
my $mod = mx->mod->new(symbol => $softmax, ($gpu_present ? (context => mx->gpu(0)) : ()));
$mod->fit(
$train_dataiter,
eval_data => $val_dataiter,
optimizer_params=>{learning_rate=>0.01, momentum=> 0.9},
num_epoch=>$n_epoch
);
my $res = $mod->score($val_dataiter, mx->metric->create('acc'));
ok($res->{accuracy} > 0.8);
t/test_infer_shape.t view on Meta::CPAN
);
_test_shapes($out, $arg_shapes, %true_shapes);
}
sub test_mlp2_infer_error
{
# Test shape inconsistent case
my $out = mlp2();
my $weight_shape = [1, 100];
my $data_shape = [100, 100];
eval { $out->infer_shape(data=>$data_shape, fc1_weight=>$weight_shape) };
like($@, qr/Shape inconsistent/);
}
sub test_backward_infer
{
my $w = mx->sym->Variable("weight");
my $wshift = mx->sym->Variable("wshift", shape=>[1]);
my $data = mx->sym->Variable("data");
# broadcast add here, not being able to deduce shape correctly
my $wt = mx->sym->broadcast_add($w, $wshift);
t/test_module.t view on Meta::CPAN
$mod->forward($data_batch);
is_deeply($mod->get_outputs->[0]->shape, [$lshape->[0], $num_class]);
$mod->backward();
$mod->update();
#Test score
my $dataset_shape1 = [30, 3, 30, 30];
my $dataset_shape2 = [30, 3, 20, 40];
my $labelset_shape = [30];
my $eval_dataiter = mx->io->NDArrayIter(data=>[mx->nd->random_uniform(0, 9, $dataset_shape1),
mx->nd->random_uniform(15, 25, $dataset_shape2)],
label=>[mx->nd->ones($labelset_shape)],
batch_size=>5);
ok(keys %{ $mod->score($eval_dataiter, 'acc') } == 1);
#Test prediction
$dshape1 = [1, 3, 30, 30];
$dshape2 = [1, 3, 20, 40];
$dataset_shape1 = [10, 3, 30, 30];
$dataset_shape2 = [10, 3, 20, 40];
my $pred_dataiter = mx->io->NDArrayIter(data=>[mx->nd->random_uniform(0, 9, $dataset_shape1),
mx->nd->random_uniform(15, 25, $dataset_shape2)]);
$mod->bind(data_shapes=>[['data1', $dshape1], ['data2', $dshape2]],
t/test_rnn.t view on Meta::CPAN
[sort keys %{ $cell->params->_params }],
['rnn_h2h_bias', 'rnn_h2h_weight', 'rnn_i2h_bias', 'rnn_i2h_weight']
);
is_deeply(
$outputs->list_outputs,
['rnn_t0_out_plus_residual_output', 'rnn_t1_out_plus_residual_output']
);
my (undef, $outs) = $outputs->infer_shape(rnn_t0_data=>[10, 50], rnn_t1_data=>[10, 50]);
is_deeply($outs, [[10, 50], [10, 50]]);
$outputs = $outputs->eval(args => {
rnn_t0_data=>mx->nd->ones([10, 50]),
rnn_t1_data=>mx->nd->ones([10, 50]),
rnn_i2h_weight=>mx->nd->zeros([150, 50]),
rnn_i2h_bias=>mx->nd->zeros([150]),
rnn_h2h_weight=>mx->nd->zeros([150, 50]),
rnn_h2h_bias=>mx->nd->zeros([150])
});
my $expected_outputs = mx->nd->ones([10, 50])->aspdl;
same(@{$outputs}[0]->aspdl, $expected_outputs);
same(@{$outputs}[1]->aspdl, $expected_outputs);
t/test_rnn.t view on Meta::CPAN
['rnn_l_h2h_bias', 'rnn_l_h2h_weight', 'rnn_l_i2h_bias', 'rnn_l_i2h_weight',
'rnn_r_h2h_bias', 'rnn_r_h2h_weight', 'rnn_r_i2h_bias', 'rnn_r_i2h_weight']
);
is_deeply(
$outputs->list_outputs,
['bi_t0_plus_residual_output', 'bi_t1_plus_residual_output']
);
my (undef, $outs) = $outputs->infer_shape(rnn_t0_data=>[10, 50], rnn_t1_data=>[10, 50]);
is_deeply($outs, [[10, 50], [10, 50]]);
$outputs = $outputs->eval(args => {
rnn_t0_data=>mx->nd->ones([10, 50])+5,
rnn_t1_data=>mx->nd->ones([10, 50])+5,
rnn_l_i2h_weight=>mx->nd->zeros([75, 50]),
rnn_l_i2h_bias=>mx->nd->zeros([75]),
rnn_l_h2h_weight=>mx->nd->zeros([75, 25]),
rnn_l_h2h_bias=>mx->nd->zeros([75]),
rnn_r_i2h_weight=>mx->nd->zeros([75, 50]),
rnn_r_i2h_bias=>mx->nd->zeros([75]),
rnn_r_h2h_weight=>mx->nd->zeros([75, 25]),
rnn_r_h2h_bias=>mx->nd->zeros([75])