AI-MXNet
view release on metacpan or search on metacpan
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
- forward(data_batch): forward operation.
- backward(out_grads=): backward operation.
- update(): update parameters according to installed optimizer.
- get_outputs(): get outputs of the previous forward operation.
- get_input_grads(): get the gradients with respect to the inputs computed
in the previous backward operation.
- update_metric(metric, labels): update performance metric for the previous forward
computed results.
- other properties (mostly for backward compatability)
- 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);
################################################################################
# High Level API
################################################################################
=head2 forward_backward
A convenient function that calls both forward and backward.
=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.
Returns
-------
When $merge_batches is 1 (by default), the return value will be an array ref
[$out1, $out2, $out3] where each element is concatenation of the outputs for
all the mini-batches. If $always_output_list` also is 0 (by default),
then in the case of a single output, $out1 is returned in stead of [$out1].
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)
{
confess('Cannot merge batches, as num of outputs is not the same '
.'in mini-batches. Maybe bucketing is used?');
}
}
my @output_list2;
for my $i (0..$num_outputs-1)
{
push @output_list2,
AI::MXNet::NDArray->concatenate([map { $_->[$i] } @output_list]);
}
if($num_outputs == 1 and not $always_output_list)
{
return $output_list2[0];
}
return @output_list2;
}
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.
:$allow_missing=0 : Bool
Default is 0. Indicates whether we allow missing parameters when $arg_params
and $aux_params are not undefined. If this is 1, then the missing parameters
will be initialized via the $initializer.
:$force_rebind=0 : Bool
Default is 0. Whether to force rebinding the executors if already binded.
:$force_init=0 : Bool
Default is 0. Indicates whether we should force initialization even if the
parameters are already initialized.
:$begin_epoch=0 : Int
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=
)
{
$self->bind(
data_shapes => $train_data->provide_data,
label_shapes => $train_data->provide_label,
for_training => 1,
force_rebind => $force_rebind
);
if($monitor)
{
$self->install_monitor($monitor);
}
$self->init_params(
initializer => $initializer,
arg_params => $arg_params,
aux_params => $aux_params,
allow_missing => $allow_missing,
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;
( run in 0.714 second using v1.01-cache-2.11-cpan-39bf76dae61 )