view release on metacpan or search on metacpan
examples/cudnn_lstm_bucketing.pl view on Meta::CPAN
if($load_epoch)
{
(undef, $arg_params, $aux_params) = mx->rnn->load_rnn_checkpoint(
$stack, $model_prefix, $load_epoch);
}
my $model = mx->mod->BucketingModule(
sym_gen => $sym_gen,
default_bucket_key => $data_val->default_bucket_key,
context => $contexts
);
$model->bind(
data_shapes => $data_val->provide_data,
label_shapes => $data_val->provide_label,
for_training => 0,
force_rebind => 0
);
$model->set_params($arg_params, $aux_params);
my $score = $model->score($data_val,
mx->metric->Perplexity($invalid_label),
batch_end_callback=>mx->callback->Speedometer($batch_size, 5)
);
};
if($num_layers >= 4 and split(/,/,$gpus) >= 4 and not $stack_rnn)
{
lib/AI/MXNet/Executor.pm view on Meta::CPAN
_aux_dict
_output_dict
outputs
_output_dirty/] => (is => 'rw', init_arg => undef);
=head1 NAME
AI::MXNet::Executor - The actual executing object of MXNet.
=head2 new
Constructor, used by AI::MXNet::Symbol->bind and by AI::MXNet::Symbol->simple_bind.
Parameters
----------
handle: ExecutorHandle
ExecutorHandle is generated by calling bind.
See Also
--------
AI::MXNet::Symbol->bind : how to create the AI::MXNet::Executor.
=cut
sub BUILD
{
my $self = shift;
my ($symbol, $ctx, $grad_req, $group2ctx)
=
($self->_symbol, $self->_ctx, $self->_grad_req, $self->_group2ctx);
$symbol = $symbol->deepcopy;
$ctx = $ctx->deepcopy;
lib/AI/MXNet/Executor.pm view on Meta::CPAN
}
=head2 backward
Do a backward pass to get the gradient of the arguments.
Parameters
----------
out_grads : NDArray or an array ref of NDArrays or hash ref of NDArrays, optional.
The gradient on the outputs to be propagated back.
This parameter is only needed when bind is called
on outputs that are not a loss function.
=cut
method backward(Maybe[AI::MXNet::NDArray|ArrayRef[AI::MXNet::NDArray]|HashRef[AI::MXNet::NDArray]] $out_grads=)
{
$out_grads //= [];
if(blessed $out_grads)
{
$out_grads = [$out_grads];
}
lib/AI/MXNet/Executor.pm view on Meta::CPAN
{
confess(
"Shape of unspecified array aux:$name changed. "
."This can cause the new executor to not share parameters "
."with the old one. Please check for error in network."
."If this is intended, set partial_shaping=True to suppress this warning."
);
}
$i++;
}
return $self->_symbol->bind(
ctx => $self->_ctx,
args => \%new_arg_dict,
args_grad => \%new_grad_dict,
grad_req => $self->_grad_req,
aux_states => \%new_aux_dict,
group2ctx => $self->_group2ctx,
shared_exec => $self
);
}
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
data_shapes : ArrayRef[NameShape|AI::MXNet::DataDesc]
Should be a array ref of [name, shape] array refs, for the shapes of data. Note the order is
important and should be the same as the order that the `DataIter` provide the data.
label_shapes : Maybe[ArrayRef[NameShape|AI::MXNet::DataDesc]]
Should be a array ref of [$name, $shape] array refs, for the shapes of label. Note the order is
important and should be the same as the order that the `DataIter` provide the label.
param_names : ArrayRef[Str]
A array ref of strings, indicating the names of parameters (e.g. weights, filters, etc.)
in the computation graph.
for_training : Bool
Indicate whether the executors should be bind for training. When not doing training,
the memory for gradients will not be allocated.
inputs_need_grad : Bool
Indicate whether the gradients for the input data should be computed. This is currently
not used. It will be useful for implementing composition of modules.
shared_group : AI::MXNet::DataParallelExecutorGroup
Default is undef. This is used in bucketing. When not undef, it should be a executor
group corresponding to a different bucket. In other words, it will correspond to a different
symbol with the same set of parameters (e.g. unrolled RNNs with different lengths).
In this case the memory regions of the parameters will be shared.
logger : Logger
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
}
else
{
$self->_p->shared_data_arrays([map { +{} } 0..@{ $self->contexts }-1]);
}
$self->_p->output_layouts([
map {
AI::MXNet::DataDesc->get_batch_axis($self->symbol->slice($_)->attr('__layout__'))
} @{ $self->symbol->list_outputs }
]);
$self->bind_exec($self->data_shapes, $self->label_shapes, $self->shared_group);
}
=decide_slices
Decide the slices for each context according to the workload.
Parameters
----------
$data_shapes : ArrayRef[AI::MXNet::DataDesc]
=cut
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
{
my @tmp;
for my $exec (@{ $self->_p->execs })
{
push @tmp, $exec->aux_arrays->[$i];
}
push @{ $self->_p->aux_arrays }, \@tmp;
}
}
=head2 bind_exec
Bind executors on their respective devices.
Parameters
----------
$data_shapes : ArrayRef[AI::MXNet::DataDesc]
$label_shapes : Maybe[ArrayRef[AI::MXNet::DataDesc]]
$shared_group : Maybe[AI::MXNet::DataParallelExecutorGroup]
$reshape : Bool
=cut
method bind_exec(
ArrayRef[AI::MXNet::DataDesc] $data_shapes,
Maybe[ArrayRef[AI::MXNet::DataDesc]] $label_shapes=,
Maybe[AI::MXNet::DataParallelExecutorGroup] $shared_group=,
Bool $reshape=0
)
{
assert($reshape or not @{ $self->_p->execs });
$self->_p->batch_size(undef);
# calculate workload and bind executors
$self->_p->data_layouts($self->decide_slices($data_shapes));
# call it to make sure labels has the same batch size as data
if(defined $label_shapes)
{
$self->_p->label_layouts($self->decide_slices($label_shapes));
}
for my $i (0..@{ $self->contexts }-1)
{
my $data_shapes_i = $self->_sliced_shape($data_shapes, $i, $self->_p->data_layouts);
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
if($reshape)
{
my %combined_hash = map { $_->name => $_->shape } (@{ $data_shapes_i }, @{ $label_shapes_i });
$self->_p->execs->[$i] = $self->_p->_default_execs->[$i]->reshape(
\%combined_hash,
allow_up_sizing => 1,
);
}
else
{
push @{ $self->_p->execs }, $self->_bind_ith_exec($i, $data_shapes_i, $label_shapes_i, $shared_group);
}
}
$self->data_shapes($data_shapes);
$self->label_shapes($label_shapes);
$self->_collect_arrays;
}
=head2 reshape
Reshape executors.
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
method reshape(
ArrayRef[AI::MXNet::DataDesc] $data_shapes,
Maybe[ArrayRef[AI::MXNet::DataDesc]] $label_shapes=
)
{
return if($data_shapes eq $self->data_shapes and $label_shapes eq $self->label_shapes);
if (not defined $self->_p->_default_execs)
{
$self->_p->_default_execs([@{ $self->_p->execs }]);
}
$self->bind_exec($data_shapes, $label_shapes, undef, 1);
}
=head2 set_params
Assign, i.e. copy parameters to all the executors.
Parameters
----------
$arg_params : HashRef[AI::MXNet::NDArray]
A dictionary of name to AI::MXNet::NDArray parameter mapping.
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
=head2 backward
Run backward on all devices. A backward should be called after
a call to the forward function. Backward cannot be called unless
$self->for_training is 1.
Parameters
----------
out_grads : NDArray or array ref of NDArray, optional
Gradient on the outputs to be propagated back.
This parameter is only needed when bind is called
on outputs that are not a loss function.
=cut
method backward(Maybe[AI::MXNet::NDArray|ArrayRef[AI::MXNet::NDArray]] $out_grads=)
{
confess('re-bind with for_training=1 to run backward') unless $self->for_training;
$out_grads //= [];
zip(sub {
my ($i, $exec, $islice) = @_;
my @out_grads_slice;
zip(sub{
my ($grad, $axis) = @_;
if($axis >= 0)
{
my $og_my_slice = $grad->slice_axis({
axis => $axis,
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
}
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
)
{
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;
}
lib/AI/MXNet/Module.pm view on Meta::CPAN
{
if(defined $symbol)
{
$symbol->save("$prefix-symbol.json");
}
my $param_name = sprintf('%s-%04d.params', $prefix, $epoch);
$self->save_params($param_name, $arg_params, $aux_params);
AI::MXNet::Logging->info('Saved checkpoint to "%s"', $param_name);
}
# Internal function to reset binded state.
method _reset_bind()
{
$self->binded(0);
$self->_p->_exec_group(undef);
$self->_p->_data_shapes(undef);
$self->_p->_label_shapes(undef);
}
method data_names()
{
return $self->_p->_data_names;
}
lib/AI/MXNet/Module.pm view on Meta::CPAN
return $self->_p->_label_names;
}
method output_names()
{
return $self->_p->_output_names;
}
method data_shapes()
{
assert($self->binded);
return $self->_p->_data_shapes;
}
method label_shapes()
{
assert($self->binded);
return $self->_p->_label_shapes;
}
method output_shapes()
{
assert($self->binded);
return $self->_p->_exec_group->get_output_shapes;
}
method get_params()
{
assert($self->binded and $self->params_initialized);
if($self->_p->_params_dirty)
{
$self->_sync_params_from_devices();
}
return ($self->_p->_arg_params, $self->_p->_aux_params);
}
method init_params(
Maybe[AI::MXNet::Initializer] :$initializer=AI::MXNet::Initializer->Uniform(scale => 0.01),
Maybe[HashRef[AI::MXNet::NDArray]] :$arg_params=,
lib/AI/MXNet/Module.pm view on Meta::CPAN
)
{
if($self->params_initialized and not $force_init)
{
AI::MXNet::Logging->warning(
"Parameters already initialized and force_init=0. "
."init_params call ignored."
);
return;
}
assert($self->binded, 'call bind before initializing the parameters');
my $_impl = sub {
my ($name, $arr, $cache) = @_;
# Internal helper for parameter initialization
if(defined $cache)
{
if(exists $cache->{$name})
{
my $cache_arr = $cache->{$name};
# just in case the cached array is just the target itself
if($cache_arr->handle ne $arr->handle)
lib/AI/MXNet/Module.pm view on Meta::CPAN
"Parameters already initialized and force_init=False. "
."set_params call ignored."
);
return;
}
$self->_p->_exec_group->set_params($arg_params, $aux_params, $allow_extra);
$self->_p->_params_dirty(1);
$self->params_initialized(1);
}
=head2 bind
Bind the symbols to construct executors. This is necessary before one
can perform computation with the module.
Parameters
----------
:$data_shapes : ArrayRef[AI::MXNet::DataDesc|NameShape]
Typically is $data_iter->provide_data.
:$label_shapes : Maybe[ArrayRef[AI::MXNet::DataDesc|NameShape]]
Typically is $data_iter->provide_label.
:$for_training : bool
Default is 1. Whether the executors should be bind for training.
:$inputs_need_grad : bool
Default is 0. Whether the gradients to the input data need to be computed.
Typically this is not needed. But this might be needed when implementing composition
of modules.
:$force_rebind : bool
Default is 0. This function does nothing if the executors are already
binded. But with this 1, the executors will be forced to rebind.
:$shared_module : Module
Default is undef. This is used in bucketing. When not undef, the shared module
essentially corresponds to a different bucket -- a module with different symbol
but with the same sets of parameters (e.g. unrolled RNNs with different lengths).
=cut
method bind(
ArrayRef[AI::MXNet::DataDesc|NameShape] :$data_shapes,
Maybe[ArrayRef[AI::MXNet::DataDesc|NameShape]] :$label_shapes=,
Bool :$for_training=1,
Bool :$inputs_need_grad=0,
Bool :$force_rebind=0,
Maybe[AI::MXNet::Module] :$shared_module=,
GradReq|HashRef[GradReq]|ArrayRef[GradReq] :$grad_req='write',
Maybe[ArrayRef[Str]] :$state_names=$self->_p->_state_names
)
{
# force rebinding is typically used when one want to switch from
# training to prediction phase.
if($force_rebind)
{
$self->_reset_bind();
}
if($self->binded)
{
$self->logger->warning('Already binded, ignoring bind()');
return;
}
$self->for_training($for_training);
$self->inputs_need_grad($inputs_need_grad);
$self->binded(1);
$self->_p->_grad_req($grad_req);
if(not $for_training)
{
assert(not $inputs_need_grad);
}
($data_shapes, $label_shapes) = $self->_parse_data_desc(
$self->data_names, $self->label_names, $data_shapes, $label_shapes
);
$self->_p->_data_shapes($data_shapes);
$self->_p->_label_shapes($label_shapes);
my $shared_group;
if($shared_module)
{
assert($shared_module->binded and $shared_module->params_initialized);
$shared_group = $shared_module->_p->_exec_group;
}
$self->_p->_exec_group(
AI::MXNet::DataParallelExecutorGroup->new(
symbol => $self->_symbol,
contexts => $self->_p->_context,
workload => $self->_p->_work_load_list,
data_shapes => $self->_p->_data_shapes,
label_shapes => $self->_p->_label_shapes,
lib/AI/MXNet/Module.pm view on Meta::CPAN
)
);
if($shared_module)
{
$self->params_initialized(1);
$self->_p->_arg_params($shared_module->_p->_arg_params);
$self->_p->_aux_params($shared_module->_p->_aux_params);
}
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 }
);
lib/AI/MXNet/Module.pm view on Meta::CPAN
Typically is $data_iter->provide_data.
:$label_shapes= : Maybe[ArrayRef[AI::MXNet::DataDesc]]
Typically is $data_iter->provide_label.
=cut
method reshape(
ArrayRef[AI::MXNet::DataDesc|NameShape] :$data_shapes,
Maybe[ArrayRef[AI::MXNet::DataDesc|NameShape]] :$label_shapes=
)
{
assert($self->binded);
($data_shapes, $label_shapes) = $self->_parse_data_desc(
$self->data_names, $self->label_names, $data_shapes, $label_shapes
);
$self->_p->_data_shapes($data_shapes);
$self->_p->_label_shapes($label_shapes);
$self->_p->_exec_group->reshape($self->_p->_data_shapes, $self->_p->_label_shapes);
}
method init_optimizer(
Str|AI::MXNet::KVStore :$kvstore='local',
Optimizer :$optimizer='sgd',
HashRef :$optimizer_params={ learning_rate => 0.01 },
Bool :$force_init=0
)
{
assert($self->binded and $self->params_initialized);
if($self->optimizer_initialized and not $force_init)
{
$self->logger->warning('optimizer already initialized, ignoring...');
return;
}
if($self->_p->_params_dirty)
{
$self->_sync_params_from_devices;
}
lib/AI/MXNet/Module.pm view on Meta::CPAN
$self->_p->_update_on_kvstore($shared_module->_p->_update_on_kvstore);
$self->_p->_updater($shared_module->_p->_updater);
$self->optimizer_initialized(1);
}
method forward(
AI::MXNet::DataBatch $data_batch,
Maybe[Bool] :$is_train=
)
{
assert($self->binded and $self->params_initialized);
my @curr_data_shapes = map { $_->shape } @{ $self->data_shapes };
my @new_data_shapes = map { $_->shape } @{ $data_batch->data };
if(Data::Dumper->Dump(\@curr_data_shapes) ne Data::Dumper->Dump(\@new_data_shapes))
{
my $new_dshape;
if($data_batch->can('provide_data') and $data_batch->provide_data)
{
$new_dshape = $data_batch->provide_data;
}
lib/AI/MXNet/Module.pm view on Meta::CPAN
);
}, $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=)
{
assert($self->binded and $self->params_initialized);
$self->_p->_exec_group->backward($out_grads);
}
method update()
{
assert($self->binded and $self->params_initialized and $self->optimizer_initialized);
$self->_p->_params_dirty(1);
if($self->_p->_update_on_kvstore)
{
_update_params_on_kvstore(
$self->_p->_exec_group->_p->param_arrays,
$self->_p->_exec_group->_p->grad_arrays,
$self->_p->_kvstore,
$self->_p->_exec_group->param_names
);
}
lib/AI/MXNet/Module.pm view on Meta::CPAN
$self->_p->_updater,
scalar(@{ $self->_p->_context}),
$self->_p->_kvstore,
$self->_p->_exec_group->param_names
);
}
}
method get_outputs(Bool $merge_multi_context=1)
{
assert($self->binded and $self->params_initialized);
return $self->_p->_exec_group->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->_p->_exec_group->get_input_grads($merge_multi_context);
}
method get_states(Bool $merge_multi_context=1)
{
assert($self->binded and $self->params_initialized);
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);
}
lib/AI/MXNet/Module.pm view on Meta::CPAN
open(F, "<:raw", "$fname") or confess("can't open $fname for reading: $!");
my $data;
{ local($/) = undef; $data = <F>; }
close(F);
$self->_p->_updater->set_states($data);
}
}
method install_monitor(AI::MXNet::Monitor $mon)
{
assert($self->binded);
$self->_p->_exec_group->install_monitor($mon);
}
method _updater()
{
$self->_p->_updater;
}
method _kvstore()
{
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
- Initial state. Memory is not allocated yet, not ready for computation yet.
- Binded. Shapes for inputs, outputs, and parameters are all known, memory allocated,
ready for computation.
- Parameter initialized. For modules with parameters, doing computation before initializing
the parameters might result in undefined outputs.
- Optimizer installed. An optimizer can be installed to a module. After this, the parameters
of the module can be updated according to the optimizer after gradients are computed
(forward-backward).
In order for a module to interact with others, a module should be able to report the
following information in its raw stage (before binded)
- data_names: array ref of string indicating the names of required data.
- output_names: array ref of string indicating the names of required outputs.
And also the following richer information after binded:
- state information
- binded: bool, indicating whether the memory buffers needed for computation
has been allocated.
- for_training: whether the module is binded for training (if binded).
- params_initialized: bool, indicating whether the parameters of this modules
has been initialized.
- optimizer_initialized: bool, indicating whether an optimizer is defined
and initialized.
- inputs_need_grad: bool, indicating whether gradients with respect to the
input data is needed. Might be useful when implementing composition of modules.
- input/output information
- data_shapes: am array ref of [name, shape]. In theory, since the memory is allocated,
we could directly provide the data arrays. But in the case of data parallelization,
the data arrays might not be of the same shape as viewed from the external world.
- label_shapes: an array ref of [name, shape]. This might be [] if the module does
not need labels (e.g. it does not contains a loss function at the top), or a module
is not binded for training.
- output_shapes: an array ref of [name, shape] for outputs of the module.
- parameters (for modules with parameters)
- get_params(): return an array ($arg_params, $aux_params). Each of those
is a hash ref of name to NDArray mapping. Those NDArrays always on
CPU. The actual parameters used for computing might be on other devices (GPUs),
this function will retrieve (a copy of) the latest parameters. Therefore, modifying
- get_params($arg_params, $aux_params): assign parameters to the devices
doing the computation.
- init_params(...): a more flexible interface to assign or initialize the parameters.
- setup
- bind(): prepare environment for computation.
- init_optimizer(): install optimizer for parameter updating.
- computation
- 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
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
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.
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
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>)
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
$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);
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
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 }];
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
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
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
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,
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
=head2 data_shapes
An array ref of AI::MXNet::DataDesc objects specifying the data inputs to this module.
=cut
method data_shapes() { confess("NotImplemented") }
=head2 label_shapes
A array ref of AI::MXNet::DataDesc objects specifying the label inputs to this module.
If this module does not accept labels -- either it is a module without a loss
function, or it is not binded for training, then this should return an empty
array ref.
=cut
method label_shapes() { confess("NotImplemented") }
=head2 output_shapes
An array ref of (name, shape) array refs specifying the outputs of this module.
=cut
method output_shapes() { confess("NotImplemented") }
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
Returns
-------
If $merge_multi_context is 1, it is like [$out1, $out2]. Otherwise, it
is like [[$out1_dev1, $out1_dev2], [$out2_dev1, $out2_dev2]]. All the output
elements are AI::MXNet::NDArray.
=cut
method get_states(Bool $merge_multi_context=1)
{
assert($self->binded and $self->params_initialized);
assert(not $merge_multi_context);
return [];
}
=head2 set_states
Set value for states. You can specify either $states or $value, not both.
Parameters
----------
$states= : Maybe[ArrayRef[ArrayRef[AI::MXNet::NDArray]]]
source states arrays formatted like [[$state1_dev1, $state1_dev2],
[$state2_dev1, $state2_dev2]].
$value= : Maybe[Num]
a single scalar value for all state arrays.
=cut
method set_states(Maybe[ArrayRef[ArrayRef[AI::MXNet::NDArray]]] $states=, Maybe[Num] $value=)
{
assert($self->binded and $self->params_initialized);
assert(not $states and not $value);
}
=head2 install_monitor
Install monitor on all executors
Parameters
----------
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
################################################################################
# Computations
################################################################################
=head2 forward
Forward computation. It supports data batches with different shapes, such as
different batch sizes or different image sizes.
If reshaping of data batch relates to modification of symbol or module, such as
changing image layout ordering or switching from training to predicting, module
rebinding is required.
Parameters
----------
$data_batch : DataBatch
Could be anything with similar API implemented.
:$is_train= : Bool
Default is undef, which means is_train takes the value of $self->for_training.
=cut
method forward(AI::MXNet::DataBatch $data_batch, Bool :$is_train=) { confess("NotImplemented") }
=head2 backward
Backward computation.
Parameters
----------
$out_grads : Maybe[AI::MXNet::NDArray|ArrayRef[AI::MXNet::NDArray]], optional
Gradient on the outputs to be propagated back.
This parameter is only needed when bind is called
on outputs that are not a loss function.
=cut
method backward(Maybe[AI::MXNet::NDArray|ArrayRef[AI::MXNet::NDArray]] $out_grads=)
{
confess("NotImplemented")
}
=head2 get_outputs
lib/AI/MXNet/Module/Base.pm view on Meta::CPAN
method update_metric(EvalMetric $eval_metric, ArrayRef[AI::MXNet::NDArray] $labels)
{
confess("NotImplemented")
}
################################################################################
# module setup
################################################################################
=head2 bind
Binds the symbols in order to construct the executors. This is necessary
before the computations can be performed.
Parameters
----------
$data_shapes : ArrayRef[AI::MXNet::DataDesc]
Typically is $data_iter->provide_data.
:$label_shapes= : Maybe[ArrayRef[AI::MXNet::DataDesc]]
Typically is $data_iter->provide_label.
:$for_training=1 : Bool
Default is 1. Whether the executors should be bind for training.
:$inputs_need_grad=0 : Bool
Default is 0. Whether the gradients to the input data need to be computed.
Typically this is not needed. But this might be needed when implementing composition
of modules.
:$force_rebind=0 : Bool
Default is 0. This function does nothing if the executors are already
binded. But with this as 1, the executors will be forced to rebind.
:$shared_module= : A subclass of AI::MXNet::Module::Base
Default is undef. This is used in bucketing. When not undef, the shared module
essentially corresponds to a different bucket -- a module with different symbol
but with the same sets of parameters (e.g. unrolled RNNs with different lengths).
:$grad_req='write' : Str|ArrayRef[Str]|HashRef[Str]
Requirement for gradient accumulation. Can be 'write', 'add', or 'null'
(defaults to 'write').
Can be specified globally (str) or for each argument (array ref, hash ref).
=cut
method bind(
ArrayRef[AI::MXNet::DataDesc] $data_shapes,
Maybe[ArrayRef[AI::MXNet::DataDesc]] :$label_shapes=,
Bool :$for_training=1,
Bool :$inputs_need_grad=0,
Bool :$force_rebind=0,
Maybe[AI::MXNet::BaseModule] :$shared_module=,
Str|ArrayRef[Str]|HashRef[Str] :$grad_req='write'
)
{
confess("NotImplemented")
}
=head2 init_optimizer
Install and initialize optimizers.
lib/AI/MXNet/Module/Bucketing.pm view on Meta::CPAN
$self->_fixed_param_names([]) unless defined $original_params->{fixed_param_names};
$self->_state_names([]) unless defined $original_params->{state_names};
$self->_params_dirty(0);
my ($symbol, $data_names, $label_names) = &{$self->_sym_gen}($self->_default_bucket_key);
$self->_check_input_names($symbol, $data_names//[], "data", 1);
$self->_check_input_names($symbol, $label_names//[], "label", 0);
$self->_check_input_names($symbol, $self->_state_names, "state", 1);
$self->_check_input_names($symbol, $self->_fixed_param_names, "fixed_param", 1);
}
method _reset_bind()
{
$self->binded(0);
$self->_buckets({});
$self->_curr_module(undef);
$self->_curr_bucket_key(undef);
}
method data_names()
{
if($self->binded)
{
return $self->_curr_module->data_names;
}
else
{
return (&{$self->_sym_gen}($self->_default_bucket_key))[1];
}
}
method output_names()
{
if($self->binded)
{
return $self->_curr_module->ouput_names;
}
else
{
my ($symbol) = &{$self->_sym_gen}($self->_default_bucket_key);
return $symbol->list_ouputs;
}
}
method data_shapes()
{
assert($self->binded);
return $self->_curr_module->data_shapes;
}
method label_shapes()
{
assert($self->binded);
return $self->_curr_module->label_shapes;
}
method output_shapes()
{
assert($self->binded);
return $self->_curr_module->output_shapes;
}
method get_params()
{
assert($self->binded and $self->params_initialized);
$self->_curr_module->_p->_params_dirty($self->_params_dirty);
my ($arg_params, $aux_params) = $self->_curr_module->get_params;
$self->_params_dirty(0);
return ($arg_params, $aux_params);
}
method set_params(
HashRef[AI::MXNet::NDArray] $arg_params,
HashRef[AI::MXNet::NDArray] $aux_params,
Bool $allow_missing=0,
lib/AI/MXNet/Module/Bucketing.pm view on Meta::CPAN
method init_params(
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_init=0,
Bool :$allow_extra=0
)
{
return if($self->params_initialized and not $force_init);
assert($self->binded, 'call bind before initializing the parameters');
$self->_curr_module->init_params(
initializer => $initializer,
arg_params => $arg_params,
aux_params => $aux_params,
allow_missing => $allow_missing,
force_init => $force_init,
allow_extra => $allow_extra
);
$self->_params_dirty(0);
$self->params_initialized(1);
}
method get_states(Bool $merge_multi_context=1)
{
assert($self->binded and $self->params_initialized);
$self->_curr_module->get_states($merge_multi_context);
}
method set_states(:$states=, :$value=)
{
assert($self->binded and $self->params_initialized);
$self->_curr_module->set_states(states => $states, value => $value);
}
=head2 bind
Binding for a AI::MXNet::Module::Bucketing means setting up the buckets and bind the
executor for the default bucket key. Executors corresponding to other keys are
binded afterwards with switch_bucket.
Parameters
----------
:$data_shapes : ArrayRef[AI::MXNet::DataDesc|NameShape]
This should correspond to the symbol for the default bucket.
:$label_shapes= : Maybe[ArrayRef[AI::MXNet::DataDesc|NameShape]]
This should correspond to the symbol for the default bucket.
:$for_training : Bool
Default is 1.
:$inputs_need_grad : Bool
Default is 0.
:$force_rebind : Bool
Default is 0.
:$shared_module : AI::MXNet::Module::Bucketing
Default is undef. This value is currently not used.
:$grad_req : str, array ref of str, hash ref of str to str
Requirement for gradient accumulation. Can be 'write', 'add', or 'null'
(defaults to 'write').
Can be specified globally (str) or for each argument (array ref, hash ref).
:$bucket_key : str
bucket key for binding. by default is to use the ->default_bucket_key
=cut
method bind(
ArrayRef[AI::MXNet::DataDesc|NameShape] :$data_shapes,
Maybe[ArrayRef[AI::MXNet::DataDesc|NameShape]] :$label_shapes=,
Bool :$for_training=1,
Bool :$inputs_need_grad=0,
Bool :$force_rebind=0,
Maybe[AI::MXNet::BaseModule] :$shared_module=,
Str|ArrayRef[Str]|HashRef[Str] :$grad_req='write',
Maybe[Str] :$bucket_key=
)
{
# in case we already initialized params, keep it
my ($arg_params, $aux_params);
if($self->params_initialized)
{
($arg_params, $aux_params) = $self->get_params;
}
# force rebinding is typically used when one want to switch from
# training to prediction phase.
$self->_reset_bind if $force_rebind;
if($self->binded)
{
$self->logger->warning('Already binded, ignoring bind()');
return;
}
assert((not defined $shared_module), 'shared_module for BucketingModule is not supported');
$self->for_training($for_training);
$self->inputs_need_grad($inputs_need_grad);
$self->binded(1);
my ($symbol, $data_names, $label_names) = &{$self->_sym_gen}($bucket_key//$self->_default_bucket_key);
my $module = AI::MXNet::Module->new(
symbol => $symbol,
data_names => $data_names,
label_names => $label_names,
logger => $self->logger,
context => $self->_context,
work_load_list => $self->_work_load_list,
state_names => $self->_state_names,
fixed_param_names => $self->_fixed_param_names
);
$module->bind(
data_shapes => $data_shapes,
label_shapes => $label_shapes,
for_training => $for_training,
inputs_need_grad => $inputs_need_grad,
force_rebind => 0,
shared_module => undef,
grad_req => $grad_req
);
$self->_curr_module($module);
$self->_curr_bucket_key($self->_default_bucket_key);
$self->_buckets->{ $self->_default_bucket_key } = $module;
# copy back saved params, if already initialized
if($self->params_initialized)
{
lib/AI/MXNet/Module/Bucketing.pm view on Meta::CPAN
:$label_shapes : Maybe[ArrayRef[AI::MXNet::DataDesc|NameShape]]
Typically $data_batch->provide_label.
=cut
method switch_bucket(
Maybe[ArrayRef[AI::MXNet::DataDesc|NameShape]] :$data_shapes=,
Maybe[ArrayRef[AI::MXNet::DataDesc|NameShape]] :$label_shapes=,
:$bucket_key
)
{
assert($self->binded, 'call bind before switching bucket');
if(not exists $self->_buckets->{ $bucket_key })
{
my ($symbol, $data_names, $label_names) = &{$self->_sym_gen}($bucket_key);
my $module = AI::MXNet::Module->new(
symbol => $symbol,
data_names => $data_names,
label_names => $label_names,
logger => $self->logger,
context => $self->_context,
work_load_list => $self->_work_load_list
);
$module->bind(
data_shapes => $data_shapes,
label_shapes => $label_shapes,
for_training => $self->_curr_module->for_training,
inputs_need_grad => $self->_curr_module->inputs_need_grad,
force_rebind => 0,
shared_module => $self->_buckets->{ $self->_default_bucket_key },
);
$self->_buckets->{ $bucket_key } = $module;
}
$self->_curr_module($self->_buckets->{ $bucket_key });
$self->_curr_bucket_key($bucket_key);
}
method init_optimizer(
Str :$kvstore='local',
Optimizer :$optimizer='sgd',
HashRef :$optimizer_params={ learning_rate => 0.01 },
Bool :$force_init=0
)
{
assert($self->binded and $self->params_initialized);
if($self->optimizer_initialized and not $force_init)
{
$self->logger->warning('optimizer already initialized, ignoring.');
return;
}
$self->_curr_module->init_optimizer(
kvstore => $kvstore,
optimizer => $optimizer,
optimizer_params => $optimizer_params,
lib/AI/MXNet/Module/Bucketing.pm view on Meta::CPAN
if($mod ne $self->_curr_module)
{
$mod->borrow_optimizer($self->_curr_module);
}
}
$self->optimizer_initialized(1);
}
method prepare(AI::MXNet::DataBatch $data_batch)
{
assert($self->binded and $self->params_initialized);
## perform bind if have not done so yet
my $original_bucket_key = $self->_curr_bucket_key;
$self->switch_bucket(
bucket_key => $data_batch->bucket_key,
data_shapes => $data_batch->provide_data,
label_shapes => $data_batch->provide_label
);
# switch back
$self->switch_bucket(bucket_key => $original_bucket_key);
}
method forward(
AI::MXNet::DataBatch $data_batch,
Bool :$is_train=
)
{
assert($self->binded and $self->params_initialized);
$self->switch_bucket(
bucket_key => $data_batch->bucket_key,
data_shapes => $data_batch->provide_data,
label_shapes => $data_batch->provide_label
);
$self->_curr_module->forward($data_batch, is_train => $is_train);
}
method backward(Maybe[ArrayRef[AI::MXNet::NDArray]|AI::MXNet::NDArray] $out_grads=)
{
assert($self->binded and $self->params_initialized);
$self->_curr_module->backward($out_grads);
}
method update()
{
assert($self->binded and $self->params_initialized and $self->optimizer_initialized);
$self->_params_dirty(1);
$self->_curr_module->update;
}
method get_outputs(Bool $merge_multi_context=1)
{
assert($self->binded and $self->params_initialized);
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()
{
assert($self->binded);
return $self->_buckets->{ $self->_default_bucket_key }->symbol;
}
method install_monitor(AI::MXNet::Monitor $mon)
{
assert($self->binded);
for my $mod (values %{ $self->_buckets })
{
$mod->install_monitor($mon);
}
}
1;
lib/AI/MXNet/Monitor.pm view on Meta::CPAN
);
=head2 install
install callback to executor.
Supports installing to multiple exes.
Parameters
----------
exe : AI::MXNet::Executor
the Executor (returned by $symbol->bind) to install to.
=cut
method install(AI::MXNet::Executor $exe)
{
$exe->set_monitor_callback($self->stat_helper);
push @{ $self->exes }, $exe;
}
=head2 tic
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
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.
This means the file saved using save can be loaded by other language binding of mxnet.
You also get the benefit being able to directly load/save from cloud storage(S3, HDFS)
Parameters
----------
fname : str
The name of the file.Can be S3 or HDFS address (remember built with S3 support).
Example of fname:
- `s3://my-bucket/path/my-s3-ndarray`
- `hdfs://my-bucket/path/my-hdfs-ndarray`
lib/AI/MXNet/NDArray.pm view on Meta::CPAN
return \%ret;
}
}
=head2 save
Save array ref of NDArray or hash of str->NDArray to 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.
This means the file saved using save can be loaded by other language binding of mxnet.
You also get the benefit being able to directly load/save from cloud storage(S3, HDFS)
Parameters
----------
fname : str
The name of the file.Can be S3 or HDFS address (remember built with S3 support).
Example of fname:
- `s3://my-bucket/path/my-s3-ndarray`
- `hdfs://my-bucket/path/my-hdfs-ndarray`
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
{
return scalar(check_call(AI::MXNetCAPI::SymbolPrint($self->handle)));
}
=head2 save
Save the symbol into a 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.
This means the file saved using save can be loaded by other language binding of mxnet.
You also get the benefit being able to directly load/save from cloud storage(S3, HDFS)
Parameters
----------
fname : str
The name of the file
- s3://my-bucket/path/my-s3-symbol
- hdfs://my-bucket/path/my-hdfs-symbol
- /path-to/my-local-symbol
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
}
for my $name (@$arg_names)
{
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.
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
The dict mapping argument names to the `NDArray` that can be reused for initializing
the current executor. This buffer will be checked for reuse if one argument name
of the current executor is not found in `shared_arg_names`.
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=
)
{
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
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;
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
scalar(@shared_arg_name_list),
\@shared_arg_name_list,
defined $shared_buffer ? \%shared_data : undef,
$shared_exec_handle
)
);
};
if($@)
{
confess(
"simple_bind failed: Error: $@; Arguments: ".
Data::Dumper->new(
[$shapes//{}]
)->Purity(1)->Deepcopy(1)->Terse(1)->Dump
);
}
if(defined $shared_buffer)
{
while(my ($k, $v) = each %{ $updated_shared_data })
{
$shared_buffer->{$k} = AI::MXNet::NDArray->new(handle => $v);
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
ctx => $ctx,
grad_req => $grad_req,
group2ctx => $group2ctx
);
$executor->arg_arrays(\@arg_arrays);
$executor->grad_arrays(\@grad_arrays);
$executor->aux_arrays(\@aux_arrays);
return $executor;
}
=head2 bind
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.
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
-----
Auxiliary states are special states of symbols that do not corresponds to an argument,
and do not have gradient. But still be useful for the specific operations.
A common example of auxiliary state is the moving_mean and moving_variance in BatchNorm.
Most operators do not have auxiliary states and this parameter can be safely ignored.
User can give up gradient by using a hash ref in args_grad and only specify
the gradient they're interested in.
=cut
method bind(
AI::MXNet::Context :$ctx,
HashRef[AI::MXNet::NDArray]|ArrayRef[AI::MXNet::NDArray] :$args,
Maybe[HashRef[AI::MXNet::NDArray]|ArrayRef[AI::MXNet::NDArray]] :$args_grad=,
Str|HashRef[Str]|ArrayRef[Str] :$grad_req='write',
Maybe[HashRef[AI::MXNet::NDArray]|ArrayRef[AI::MXNet::NDArray]] :$aux_states=,
Maybe[HashRef[AI::MXNet::Context]] :$group2ctx=,
Maybe[AI::MXNet::Executor] :$shared_exec=
)
{
$grad_req //= 'write';
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
$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
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
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
----------
$wrt : Array of String
lib/AI/MXNet/Symbol.pm view on Meta::CPAN
my $handle = check_call(AI::MXNetCAPI::SymbolCreateGroup(scalar(@handles), \@handles));
return __PACKAGE__->new(handle => $handle);
}
=head2 load
Load symbol from a JSON 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.
This means the file saved using save can be loaded by other language binding of mxnet.
You also get the benefit being able to directly load/save from cloud storage(S3, HDFS)
Parameters
----------
fname : str
The name of the file, examples:
- `s3://my-bucket/path/my-s3-symbol`
- `hdfs://my-bucket/path/my-hdfs-symbol`
- `/path-to/my-local-symbol`
lib/AI/MXNet/TestUtils.pm view on Meta::CPAN
{
Test::More::ok(@$sym == @$ctx_list);
}
my $output_names = $sym->[0]->list_outputs;
my $arg_names = $sym->[0]->list_arguments;
my @exe_list;
zip(sub {
my ($s, $ctx) = @_;
Test::More::is_deeply($s->list_arguments, $arg_names);
Test::More::is_deeply($s->list_outputs, $output_names);
push @exe_list, $s->simple_bind(grad_req=>$grad_req, %$ctx);
}, $sym, $ctx_list);
$arg_params //= {};
$aux_params //= {};
my %arg_dict = %{ $exe_list[0]->arg_dict };
while(my ($n, $arr) = each %arg_dict)
{
if(not exists $arg_params->{$n})
{
$arg_params->{$n} = random(reverse @{ $arr->shape })*$scale;
}
t/test_executor.t view on Meta::CPAN
use strict;
use warnings;
use Test::More tests => 2283;
use AI::MXNet qw(mx);
use AI::MXNet::TestUtils qw(reldiff pdl_maximum pdl_minimum);
use PDL;
sub check_bind_with_uniform
{
my ($uf, $gf, $dim, $sf, $lshape, $rshape) = @_;
my $shape = (random($dim)*int(1000**(1.0/$dim))+1)->floor->unpdl;
my $lhs = mx->symbol->Variable('lhs');
my $rhs = mx->symbol->Variable('rhs');
my $ret;
if(defined $sf)
{
$ret = &{$sf}($lhs, $rhs);
}
t/test_executor.t view on Meta::CPAN
}
is_deeply($ret->list_arguments(), ['lhs', 'rhs']);
$lshape //= $shape;
$rshape //= $shape;
my $lhs_arr = mx->nd->array(random(reverse (@$lshape)));
my $rhs_arr = mx->nd->array(random(reverse (@$rshape)));
my $lhs_grad = mx->nd->empty($lshape);
my $rhs_grad = mx->nd->empty($rshape);
my $executor = $ret->bind(
ctx => mx->Context('cpu'),
args => [$lhs_arr, $rhs_arr],
args_grad => [$lhs_grad, $rhs_grad]
);
my $exec3 = $ret->bind(
ctx => mx->Context('cpu'),
args => [$lhs_arr, $rhs_arr]
);
my $exec4 = $ret->bind(
ctx => mx->Context('cpu'),
args => {'rhs' => $rhs_arr, 'lhs' => $lhs_arr},
args_grad=>{'lhs' => $lhs_grad, 'rhs' => $rhs_grad}
);
$executor->forward(1);
$exec3->forward(1);
$exec4->forward(1);
my $out2 = $executor->outputs->[0]->aspdl;
my $out1 = &{$uf}($lhs_arr->aspdl, $rhs_arr->aspdl);
t/test_executor.t view on Meta::CPAN
$out_grad->aspdl,
$lhs_arr->aspdl,
$rhs_arr->aspdl
);
$executor->backward([$out_grad]);
ok(reldiff($lhs_grad->aspdl, $lhs_grad2) < 1e-6);
ok(reldiff($rhs_grad->aspdl, $rhs_grad2) < 1e-6);
}
sub test_bind
{
my ($disable_bulk_exec) = @_;
my ($prev_fwd_var, $prev_bwd_var);
if($disable_bulk_exec)
{
$prev_fwd_var = $ENV{MXNET_EXEC_BULK_FWD_THRESHOLD_TRAIN}//1;
$prev_bwd_var = $ENV{MXNET_EXEC_BULK_BWD_TRAIN}//1;
$ENV{MXNET_EXEC_BULK_FWD_THRESHOLD_TRAIN} = 0;
$ENV{MXNET_EXEC_BULK_BWD_TRAIN} = 0;
}
srand(0);
my $nrepeat = 9;
my $maxdim = 3;
for my $repeat (0..$nrepeat)
{
for my $dim (1..$maxdim)
{
check_bind_with_uniform(sub { my ($x, $y) = @_; $x + $y },
sub { my ($g) = @_; ($g, $g) },
$dim);
check_bind_with_uniform(sub { my ($x, $y) = @_; $x - $y },
sub { my ($g) = @_; ($g, -$g) },
$dim);
check_bind_with_uniform(sub { my ($x, $y) = @_; $x * $y },
sub { my ($g, $x, $y) = @_; ($g*$y, $g*$x) },
$dim);
check_bind_with_uniform(sub { my ($x, $y) = @_; $x / $y },
sub { my ($g, $x, $y) = @_; ($g / $y, -$x * $g/ ($y**2)) },
$dim);
check_bind_with_uniform(sub { my ($x, $y) = @_; pdl_maximum($x, $y) },
sub { my ($g, $x, $y) = @_; ($g * ($x>$y), $g * ($y>$x)) },
$dim,
sub { $_[0]->maximum($_[1]) });
check_bind_with_uniform(sub { my ($x, $y) = @_; pdl_minimum($x, $y) },
sub { my ($g, $x, $y) = @_; ($g * ($x<$y), $g * ($y<$x)) },
$dim,
sub { $_[0]->minimum($_[1]) });
}
}
if($disable_bulk_exec)
{
$ENV{MXNET_EXEC_BULK_FWD_THRESHOLD_TRAIN} = $prev_fwd_var;
$ENV{MXNET_EXEC_BULK_BWD_TRAIN} = $prev_bwd_var;
}
t/test_executor.t view on Meta::CPAN
sub test_dot
{
srand(0);
my $nrepeat = 9;
my $maxdim = 4;
for my $repeat (0..$nrepeat)
{
my $shape = (random(3)*500+1)->floor->unpdl;
check_bind_with_uniform(sub { my ($x, $y) = @_; $x x $y },
sub { my ($g, $x, $y) = @_; ($g x $y->transpose, $x->transpose x $g) },
2,
sub { mx->symbol->dot(@_) },
[@{$shape}[0, 1]],
[@{$shape}[1, 2]],
);
}
for my $repeat (0..$nrepeat)
{
my $shape = (random(1)*500+1)->floor->unpdl;
check_bind_with_uniform(sub { my ($x, $y) = @_; $x x $y->transpose },
sub { my ($g, $x, $y) = @_; ($g * $y, $g * $x) },
2,
sub { mx->symbol->dot(@_) },
[@{$shape}[0]],
[@{$shape}[0]],
);
}
}
sub test_reshape
{
my $x = mx->sym->Variable('x');
my $y = mx->sym->FullyConnected($x, num_hidden=>4);
my $exe = $y->simple_bind(ctx => mx->cpu(), shapes => { x=>[5,4] }, grad_req=>'null');
$exe->arg_arrays->[0] .= 1;
$exe->arg_arrays->[1] .= mx->nd->ones([4,4]);
$exe->arg_arrays->[2] .= 0;
my $new_exe = $exe->reshape({ x=>[3,4] });
$new_exe->forward(0);
# test sub exec forward
ok(($new_exe->outputs->[0]->aspdl == 4)->all);
# test shared memory
ok(($exe->outputs->[0]->aspdl->slice('X', [0,2]) == 4)->all);
# test base exec forward
$exe->forward(0);
ok(($new_exe->outputs->[0]->aspdl == 4)->all);
}
test_bind(0);
test_bind(1);
test_dot();
test_reshape();
t/test_init.t view on Meta::CPAN
use strict;
use warnings;
use Test::More tests => 4;
use AI::MXNet qw(mx);
sub test_default_init
{
my $data = mx->sym->Variable('data');
my $sym = mx->sym->LeakyReLU(data => $data, act_type => 'prelu');
my $mod = mx->mod->Module($sym);
$mod->bind(data_shapes=>[['data', [10,10]]]);
$mod->init_params;
ok((((values %{ ($mod->get_params)[0] }))[0]->aspdl == 0.25)->all);
}
sub test_variable_init
{
my $data = mx->sym->Variable('data');
my $gamma = mx->sym->Variable('gamma', init => mx->init->One());
my $sym = mx->sym->LeakyReLU(data => $data, gamma => $gamma, act_type => 'prelu');
my $mod = mx->mod->Module($sym);
$mod->bind(data_shapes=>[['data', [10,10]]]);
$mod->init_params();
ok((((values %{ ($mod->get_params)[0] }))[0]->aspdl == 1)->all);
}
sub test_aux_init
{
my $data = mx->sym->Variable('data');
my $sym = mx->sym->BatchNorm(data => $data, name => 'bn');
my $mod = mx->mod->Module($sym);
$mod->bind(data_shapes=>[['data', [10, 10, 3, 3]]]);
$mod->init_params();
ok((($mod->get_params)[1]->{bn_moving_var}->aspdl == 1)->all);
ok((($mod->get_params)[1]->{bn_moving_mean}->aspdl == 0)->all);
}
test_default_init();
test_variable_init();
test_aux_init();
t/test_model_parallel.t view on Meta::CPAN
push @$arr, mx->nd->empty($shape);
push @$arr_grad, mx->nd->empty($shape);
}
}
{
local($mx::Context) = $ctx2;
push @$arr, mx->nd->empty($shape);
push @$arr_grad, mx->nd->empty($shape);
}
my $exec1 = $net->bind(
ctx => $ctx1,
args => $arr,
args_grad => $arr_grad,
group2ctx => { dev1 => $ctx1, dev2 => $ctx2 }
);
$arr->[0] .= 1;
$arr->[1] .= 2;
$arr->[2] .= 3;
my $arr2 = [map { $_->copyto($ctx1) } @$arr];
my $arr_grad2 = [map { $_->copyto($ctx1) } @$arr_grad];
my $exec2 = $net->bind(
ctx => $ctx1,
args => $arr2,
args_grad => $arr_grad2
);
$exec1->forward(1);
$exec2->forward(1);
ok(reldiff($exec1->outputs->[0]->aspdl, $exec2->outputs->[0]->aspdl) < 1e-6);
my $out_grad = mx->nd->empty($shape, ctx => $ctx1);
$out_grad .= 1;
t/test_module.t view on Meta::CPAN
{
my $sym = mx->sym->Variable('data');
$sym = mx->sym->Activation(data=>$sym, act_type=>'relu', __layout__=>'TNC');
my $dshape = [3, 8, 7];
my $mod = mx->mod->Module(
$sym,
data_names=>['data'],
context=>[mx->cpu(0), mx->cpu(1)]
);
$mod->bind(
data_shapes=>[mx->io->DataDesc('data', $dshape, layout=>'TNC')]
);
$mod->init_params();
$mod->forward(
mx->io->DataBatch(
data=>[mx->nd->ones($dshape)]
),
is_train => 1
);
$mod->backward([mx->nd->ones($dshape)]);
t/test_module.t view on Meta::CPAN
for my $k (keys %$a)
{
ok(($a->{$k}->aspdl == $b->{$k}->aspdl)->all);
}
};
my $sym = mx->sym->Variable('data');
$sym = mx->sym->FullyConnected($sym, num_hidden=>100);
# single device
my $mod = mx->mod->Module($sym, data_names=>['data']);
$mod->bind(data_shapes=>[['data', [10, 10]]]);
$mod->init_params();
$mod->init_optimizer(optimizer_params=>{learning_rate => 0.1, momentum => 0.9});
$mod->update();
$mod->save_checkpoint('test', 0, 1);
my $mod2 = mx->mod->Module->load('test', 0, 1, data_names=>['data']);
$mod2->bind(data_shapes=>[['data', [10, 10]]]);
$mod2->init_optimizer(optimizer_params=>{learning_rate => 0.1, momentum => 0.9});
is($mod->_symbol->tojson(), $mod2->_symbol->tojson());
$dict_equ->(($mod->get_params())[0], ($mod2->get_params())[0]);
$dict_equ->($mod->_updater->states, $mod2->_updater->states);
# multi device
$mod = mx->mod->Module($sym, data_names=>['data'], context=>[mx->cpu(0), mx->cpu(1)]);
$mod->bind(data_shapes=>[['data', [10, 10]]]);
$mod->init_params();
$mod->init_optimizer(optimizer_params=>{learning_rate => 0.1, momentum => 0.9});
$mod->update();
$mod->save_checkpoint('test', 0, 1);
$mod2 = mx->mod->Module->load('test', 0, 1, data_names=>['data']);
$mod2->bind(data_shapes=>[['data', [10, 10]]]);
$mod2->init_optimizer(optimizer_params=>{learning_rate => 0.1, momentum => 0.9});
is($mod->_symbol->tojson(), $mod2->_symbol->tojson());
$dict_equ->(($mod->get_params())[0], ($mod2->get_params())[0]);
$dict_equ->($mod->_kvstore->_updater->states, $mod2->_updater->states);
unlink('test-0000.params');
unlink('test-0000.states');
unlink('test-symbol.json');
}
sub test_module_reshape
{
my $data = mx->sym->Variable('data');
my $sym = mx->sym->FullyConnected($data, num_hidden=>20, name=>'fc');
my $dshape = [7, 20];
my $mod = mx->mod->Module($sym, data_names=>['data'], context=>[mx->cpu(0), mx->cpu(1)]);
$mod->bind(data_shapes=>[['data', $dshape]]);
$mod->init_params();
$mod->init_optimizer(optimizer_params=>{learning_rate => 1});
$mod->forward(
mx->io->DataBatch(
data=>[mx->nd->ones($dshape)]
),
is_train => 1
);
$mod->backward([mx->nd->ones($dshape)]);
t/test_module.t view on Meta::CPAN
$stack->add(mx->rnn->LSTMCell(num_hidden=>20, prefix=>"lstm_l${i}_"));
}
my $begin_state = $stack->begin_state(func=>mx->sym->can('Variable'));
my (undef, $states) = $stack->unroll(10, begin_state=>$begin_state, inputs=>mx->sym->Variable('data'));
my $state_names = [map { $_->name } @$begin_state];
my $mod = mx->mod->Module(
mx->sym->Group($states), context=>[mx->cpu(0), mx->cpu(1)],
state_names=>$state_names
);
$mod->bind(data_shapes=>[['data', [5, 10]]], for_training=>0);
$mod->init_params();
my $batch = mx->io->DataBatch(data=>[mx->nd->zeros([5, 10])], label=>[]);
$mod->set_states(value=>1);
$mod->forward($batch);
my $out = $mod->get_outputs(0);
my $out1 = $mod->get_outputs(1);
$mod->set_states(states=>$out);
$mod->forward($batch);
t/test_module.t view on Meta::CPAN
$pred = mx->sym->SoftmaxOutput(data=>$pred, label=>$label, name=>'softmax');
return ($pred, ['data'], ['softmax_label']);
};
my $create_bucketing_module = sub { my $key = shift;
my $model = mx->mod->BucketingModule(
sym_gen => $gen_sym,
default_bucket_key => $key,
context => $contexts
);
$model->bind(data_shapes=>[['data', [$batch_size, $key]]],
label_shapes=>[['softmax_label', [$batch_size, $key]]]
);
$model->init_params(initializer=>$initializer);
return $model;
};
#initialize the bucketing module with the default bucket key
my $bucketing_model = $create_bucketing_module->($default_key);
#switch to test_key
$bucketing_model->switch_bucket(
bucket_key => $test_key,
t/test_module.t view on Meta::CPAN
$x = mx->symbol->LinearRegressionOutput(data=>$x, name=>'softmax', grad_scale=>2);
# create monitor
my $mean_abs = sub { my ($x) = @_;
return $x->abs->sum/$x->size;
};
my $mon = mx->mon->Monitor(1, stat_func=>$mean_abs, pattern=>'.*', sort=>1);
# create module
my $mod = mx->mod->Module($x, context=>[mx->cpu()]);
$mod->bind(data_shapes=>$train_data->provide_data, label_shapes=>$train_data->provide_label,
for_training=>1);
$mod->install_monitor($mon);
my $arg_params = {fc_0_weight => mx->nd->array([[.15, .20], [.25, .30]]),
fc_0_bias => mx->nd->array([.35, .35]),
fc_1_weight => mx->nd->array([[.40, .45], [.50, .55]]),
fc_1_bias => mx->nd->array([.60, .60])};
$mod->init_params(arg_params=>$arg_params);
my $data_batch = <$train_data>;
$mon->tic();
t/test_module.t view on Meta::CPAN
sub test_module_dtype
{
my $dtype = 'float16';
my $dshape = [3, 8, 7];
my $sym = mx->sym->Variable('data');
$sym = mx->sym->Activation(data=>$sym, act_type=>'relu', __layout__=>'TNC');
my $mod = mx->mod->Module($sym, data_names=>['data'], context => [mx->cpu(0), mx->cpu(1)]);
$mod->bind(data_shapes=>[
mx->io->DataDesc('data', $dshape, dtype => $dtype, layout=>'TNC')
]);
$mod->init_params();
$mod->forward(
mx->io->DataBatch(
data=>[mx->nd->ones($dshape, dtype=>$dtype)]
)
);
$mod->backward([mx->nd->ones($dshape, dtype=>$dtype)]);
t/test_module.t view on Meta::CPAN
{
my $a = mx->sym->Variable('a', __layout__=>'NC');
my $b = mx->sym->Variable('b', __layout__=>'NC');
my $c = mx->sym->Variable('c', __layout__=>'NC');
$c = $a + 2 * $b + 3 * $c;
my $net = mx->mod->Module(
$c, data_names=>['b', 'c', 'a'],
context=>[mx->cpu(0), mx->cpu(1)]
);
$net->bind(
data_shapes => [['b', [5, 5]], ['c', [5, 5]], ['a', [5, 5]]],
inputs_need_grad => 1
);
$net->init_params();
$net->forward(
mx->io->DataBatch(data => [
mx->nd->ones([5, 5]),
mx->nd->ones([5, 5]),
mx->nd->ones([5, 5])
t/test_module.t view on Meta::CPAN
# symbols
my $x = mx->symbol->Variable('data');
$x = mx->symbol->FullyConnected(name=>'fc_0', data=>$x, num_hidden=>2);
$x = mx->symbol->Activation(name=>"act_0", data=>$x, act_type=>'sigmoid');
$x = mx->symbol->FullyConnected(name=>'fc_1', data=>$x, num_hidden=>2);
$x = mx->symbol->Activation(name=>"act_1", data=>$x, act_type=>'sigmoid');
$x = mx->symbol->LinearRegressionOutput(data=>$x, name=>'softmax', grad_scale=>2);
# create module
my $mod = mx->mod->Module($x, context=>[mx->cpu()]);
$mod->bind(data_shapes => $train_data->provide_data, label_shapes=>$train_data->provide_label,
for_training=>1);
my $arg_params_correct = {fc_0_weight => mx->nd->array([[.15, .20], [.25, .30]]),
fc_0_bias => mx->nd->array([.35, .35]),
fc_1_weight => mx->nd->array([[.40, .45], [.50, .55]]),
fc_1_bias => mx->nd->array([.60, .60])};
my $arg_params_missing = {fc_0_weight => mx->nd->array([[.15, .20], [.25, .30]]),
fc_0_bias => mx->nd->array([.35, .35]),
fc_1_weight => mx->nd->array([[.40, .45], [.50, .55]])};
t/test_module.t view on Meta::CPAN
my $sum = mx->sym->sum(data=>$flatten1, axis=>1) + mx->sym->sum(data=>$flatten2, axis=>1);
my $fc = mx->sym->FullyConnected(data=>$sum, num_hidden=>$num_class);
my $sym = mx->sym->SoftmaxOutput(data=>$fc, name=>'softmax');
my $dshape1 = [10, 3, 64, 64];
my $dshape2 = [10, 3, 32, 32];
my $lshape = [10];
my $mod = mx->mod->Module(symbol=>$sym, data_names=>['data1', 'data2'],
label_names=>['softmax_label']);
$mod->bind(data_shapes=>[['data1', $dshape1], ['data2', $dshape2]],
label_shapes=>[['softmax_label', $lshape]]);
$mod->init_params();
$mod->init_optimizer(optimizer_params=>{learning_rate => 0.01});
# Train with original data shapes
my $data_batch = mx->io->DataBatch(data=>[mx->nd->random_uniform(0, 9, $dshape1),
mx->nd->random_uniform(5, 15, $dshape2)],
label=>[mx->nd->ones($lshape)]);
$mod->forward($data_batch);
is_deeply($mod->get_outputs->[0]->shape, [$lshape->[0], $num_class]);
t/test_module.t view on Meta::CPAN
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]],
for_training=>0, force_rebind=>1);
is_deeply($mod->predict($pred_dataiter)->shape, [10, $num_class]);
}
test_module_input_grads();
test_module_dtype();
test_monitor();
test_module_switch_bucket();
test_module_layout();
test_module_states();
t/test_multi_device_exec.t view on Meta::CPAN
for my $k (keys %set_stage1)
{
delete $set_stage2{$k};
}
my $group2ctx = {
stage1 => mx->cpu(1),
stage2 => mx->cpu(2)
};
my $texec = $mlp->simple_bind(
ctx => mx->cpu(0),
group2ctx => $group2ctx,
shapes => { data => [1,200] }
);
zip(sub {
my ($arr, $name) = @_;
if(exists $set_stage1{ $name })
{
ok($arr->context == $group2ctx->{stage1});
t/test_optimizers.t view on Meta::CPAN
}
func test_lr_wd_mult()
{
my $data = mx->sym->Variable('data');
my $bias = mx->sym->Variable('fc1_bias', lr_mult => 1.0);
my $fc1 = mx->sym->FullyConnected({ data => $data, bias => $bias, name => 'fc1', num_hidden => 10, lr_mult => 0 });
my $fc2 = mx->sym->FullyConnected({ data => $fc1, name => 'fc2', num_hidden => 10, wd_mult => 0.5 });
my $mod = mx->mod->new(symbol => $fc2, label_names => undef);
$mod->bind(data_shapes => [['data', [5,10]]]);
$mod->init_params(initializer => mx->init->Uniform(scale => 1.0));
$mod->init_optimizer(optimizer_params => { learning_rate => "1.0" });
my %args1 = %{ ($mod->get_params())[0] };
for my $k (keys %args1)
{
$args1{$k} = $args1{$k}->aspdl;
}
$mod->forward(AI::MXNet::DataBatch->new(data=>[mx->random->uniform({low=>-1.0, high=>1.0, shape=>[5,10]})], label=>undef), is_train=>1);
$mod->backward($mod->get_outputs());
$mod->update();
t/test_random.t view on Meta::CPAN
sub check_symbolic_random
{
my ($dev) = @_;
my ($a, $b) = (-10, 10);
my ($mu, $sigma) = (10, 2);
my $shape = [100, 100];
my $X = mx->sym->Variable("X");
my $Y = mx->sym->uniform(low=>$a, high=>$b, shape=>$shape) + $X;
my $x = mx->nd->zeros($shape, ctx=>$dev);
my $xgrad = mx->nd->zeros($shape, ctx=>$dev);
my $yexec = $Y->bind(ctx => $dev, args => {X => $x}, args_grad => {X => $xgrad});
mx->random->seed(128);
$yexec->forward(1);
$yexec->backward($yexec->outputs->[0]);
my $un1 = ($yexec->outputs->[0] - $x)->copyto($dev);
ok(same($xgrad->aspdl, $un1->aspdl));
mx->random->seed(128);
$yexec->forward;
my $un2 = ($yexec->outputs->[0] - $x)->copyto($dev);
ok(same($un1->aspdl, $un2->aspdl));
ok(abs($un1->aspdl->avg - ($a+$b)/2) < 0.1);
t/test_rnn.t view on Meta::CPAN
my $forget_bias = 2;
my $stack = mx->rnn->SequentialRNNCell();
$stack->add(mx->rnn->LSTMCell(100, forget_bias=>$forget_bias, prefix=>'l0_'));
$stack->add(mx->rnn->LSTMCell(100, forget_bias=>$forget_bias, prefix=>'l1_'));
my $dshape = [32, 1, 200];
my $data = mx->sym->Variable('data');
my ($sym) = $stack->unroll(1, inputs => $data, merge_outputs => 1);
my $mod = mx->mod->Module($sym, context => mx->cpu(0));
$mod->bind(data_shapes=>[['data', $dshape]]);
$mod->init_params();
my ($bias_argument) = grep { /i2h_bias$/ } @{ $sym->list_arguments };
my $f = zeros(100);
my $expected_bias = $f->glue(0, $forget_bias * ones(100), zeros(200));
ok(
((($mod->get_params())[0]->{$bias_argument}->aspdl - $expected_bias)->abs < 1e-07)->all
);
}