AI-MXNet

 view release on metacpan or  search on metacpan

examples/char_lstm.pl  view on Meta::CPAN

package AI::MXNet::RNN::IO::ASCIIIterator;
use Mouse;
extends AI::MXNet::DataIter;
has 'data'          => (is => 'ro',  isa => 'PDL',   required => 1);
has 'seq_size'      => (is => 'ro',  isa => 'Int',   required => 1);
has '+batch_size'   => (is => 'ro',  isa => 'Int',   required => 1);
has 'data_name'     => (is => 'ro',  isa => 'Str',   default => 'data');
has 'label_name'    => (is => 'ro',  isa => 'Str',   default => 'softmax_label');
has 'dtype'         => (is => 'ro',  isa => 'Dtype', default => 'float32');
has [qw/nd counter seq_counter vocab_size
    data_size provide_data provide_label idx/] => (is => 'rw', init_arg => undef);

sub BUILD
{
    my $self = shift;
    $self->data_size($self->data->nelem);
    my $segments = int(($self->data_size-$self->seq_size)/($self->batch_size*$self->seq_size));
    $self->idx([0..$segments-1]);
    $self->vocab_size($self->data->uniq->shape->at(0));
    $self->counter(0);
    $self->seq_counter(0);

examples/char_lstm.pl  view on Meta::CPAN

}

method reset()
{
    $self->counter(0);
    @{ $self->idx } = List::Util::shuffle(@{ $self->idx });
}

method next()
{
    return undef if $self->counter == @{$self->idx};
    my $offset = $self->idx->[$self->counter]*$self->batch_size*$self->seq_size + $self->seq_counter;
    my $data = $self->nd->slice(
        [$offset, $offset + $self->batch_size*$self->seq_size-1]
    )->reshape([$self->batch_size, $self->seq_size]);
    my $label = $self->nd->slice(
        [$offset + 1 , $offset + $self->batch_size*$self->seq_size]
    )->reshape([$self->batch_size, $self->seq_size]);
    $self->seq_counter($self->seq_counter + 1);
    if($self->seq_counter == $seq_size - 1)
    {

examples/char_lstm.pl  view on Meta::CPAN

                dtype => $self->dtype
            )
        ],
    );
}

package main;
my $file = "data/input.txt";
open(F, $file) or die "can't open $file: $!";
my $fdata;
{ local($/) = undef; $fdata = <F>; close(F) };
my %vocabulary; my $i = 0;
$fdata = pdl(map{ exists $vocabulary{$_} ? $vocabulary{$_} : ($vocabulary{$_} = $i++) } split(//, $fdata));
my $data_iter = AI::MXNet::RNN::IO::ASCIIIterator->new(
    batch_size => $batch_size,
    data       => $fdata,
    seq_size   => $seq_size
);
my %reverse_vocab = reverse %vocabulary;
my $mode = "${cell_mode}Cell";
my $stack = mx->rnn->SequentialRNNCell();

examples/cudnn_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
    );

    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,

examples/cudnn_lstm_bucketing.pl  view on Meta::CPAN

        begin_epoch         => $load_epoch,
        initializer         => mx->init->Xavier(factor_type => "in", magnitude => 2.34),
        num_epoch           => $num_epoch,
        batch_end_callback  => mx->callback->Speedometer($batch_size, $disp_batches),
        ($model_prefix ? (epoch_end_callback  => mx->rnn->do_rnn_checkpoint($cell, $model_prefix, 1)) : ())
    );
};

my $test = sub {
    assert($model_prefix, "Must specifiy path to load from");
    my (undef, $data_val, $vocab) = get_data('NT');
    my $stack;
    if($stack_rnn)
    {
        $stack = mx->rnn->SequentialRNNCell();
        for my $i (0..$num_layers-1)
        {
            my $cell = mx->rnn->LSTMCell(num_hidden => $num_hidden, prefix => "lstm_${i}l0_");
            if($bidirectional)
            {
                $cell = mx->rnn->BidirectionalCell(

examples/cudnn_lstm_bucketing.pl  view on Meta::CPAN

        $contexts = [map { mx->gpu($_) } split(/,/, $gpus)];
    }
    else
    {
        $contexts = mx->cpu(0);
    }

    my ($arg_params, $aux_params);
    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,

examples/mnist.pl  view on Meta::CPAN

    $win->show_all();
    Gtk2->main();
}

sub show_network {
    my($viz) = @_;
    my $load = Gtk2::Gdk::PixbufLoader->new();
    $load->write($viz->graph->as_png);
    $load->close();
    my $img = Gtk2::Image->new_from_pixbuf($load->get_pixbuf());
    my $sw = Gtk2::ScrolledWindow->new(undef, undef);
    $sw->add_with_viewport($img);
    my $win = Gtk2::Window->new('toplevel');
    $win->signal_connect(delete_event => sub { Gtk2->main_quit() });
    $win->add($sw);
    $win->show_all();
    Gtk2->main();
}

#show_sample();

lib/AI/MXNet/Contrib/AutoGrad.pm  view on Meta::CPAN

    );
}

=head2 backward

     Compute the gradients of outputs w.r.t variables.

     Parameters
     ----------
     outputs: array ref of NDArray
     out_grads: array ref of NDArray or undef
     retain_graph: bool, defaults to false
=cut


method backward(
    ArrayRef[AI::MXNet::NDArray] $outputs,
    Maybe[ArrayRef[AI::MXNet::NDArray|Undef]] $out_grads=,
    Bool $retain_graph=0
)
{

lib/AI/MXNet/Contrib/AutoGrad.pm  view on Meta::CPAN

                [],
                $retain_graph
            )
        );
        return;
    }

    my @ograd_handles;
    for my $arr (@$out_grads)
    {
        push @ograd_handles, (defined $arr ? $arr->handle : undef);
    }
    assert(
        (@ograd_handles == @output_handles),
        "outputs and out_grads must have the same length"
    );

    check_call(
        AI::MXNetCAPI::AutogradBackward(
            scalar(@output_handles),
            \@output_handles,

lib/AI/MXNet/Executor.pm  view on Meta::CPAN

has '_symbol'           => (is => 'rw', init_arg => 'symbol',    isa => 'AI::MXNet::Symbol');
has '_ctx'              => (is => 'rw', init_arg => 'ctx',       isa => 'AI::MXNet::Context' );
has '_grad_req'         => (is => 'rw', init_arg => 'grad_req',  isa => 'Maybe[Str|ArrayRef[Str]|HashRef[Str]]');
has '_group2ctx'        => (is => 'rw', init_arg => 'group2ctx', isa => 'Maybe[HashRef[AI::MXNet::Context]]');
has '_monitor_callback' => (is => 'rw', isa => 'CodeRef');
has [qw/_arg_dict
        _grad_dict
        _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
    ----------

lib/AI/MXNet/Executor.pm  view on Meta::CPAN

        AI::MXNetCAPI::ExecutorBackward(
            $self->handle,
            scalar(@{ $out_grads }),
            [map { $_->handle } @{ $out_grads }]
        )
    );
    if(not $self->_output_dirty)
    {
        AI::MXNet::Logging->warning(
            "Calling backward without calling forward(is_train=True) "
            ."first. Behavior is undefined."
        );
    }
    $self->_output_dirty(0);
}

=head2 set_monitor_callback

    Install callback.

    Parameters

lib/AI/MXNet/Executor.pm  view on Meta::CPAN


    Returns
    -------
    $exec : AI::MXNet::Executor
        A new executor that shares memory with self.
=cut


method reshape(HashRef[Shape] $kwargs, Int :$partial_shaping=0, Int :$allow_up_sizing=0)
{
    my ($arg_shapes, undef, $aux_shapes) = $self->_symbol->infer_shape(%{ $kwargs });
    confess("Insufficient argument shapes provided.") 
        unless defined $arg_shapes;
    my %new_arg_dict;
    my %new_grad_dict;
    my $i = 0;
    for my $name (@{ $self->_symbol->list_arguments() })
    {
        my $new_shape = $arg_shapes->[$i];
        my $arr       = $self->arg_arrays->[$i];
        my $darr;

lib/AI/MXNet/Executor/Group.pm  view on Meta::CPAN

## this class is here because of https://github.com/gfx/p5-Mouse/pull/67
## once 2.4.7 version of Mouse in Ubuntu for affected Perl version
## these accessors should be merged into main class
package AI::MXNet::DataParallelExecutorGroup::_private;
use Mouse;
has [qw/output_layouts label_layouts arg_names aux_names
        batch_size slices execs data_arrays
        label_arrays param_arrays grad_arrays aux_arrays
        data_layouts shared_data_arrays input_grad_arrays
        _default_execs state_arrays/
    ] => (is => 'rw', init_arg => undef);

package AI::MXNet::DataParallelExecutorGroup;
use Mouse;
use AI::MXNet::Base;
use List::Util qw(sum);

=head1 DESCRIPTION

    DataParallelExecutorGroup is a group of executors that lives on a group of devices.
    This is a helper class used to implement data parallelization. Each mini-batch will
    be split and run on the devices.

    Parameters for constructor
    ----------
    symbol : AI::MXNet::Symbol
        The common symbolic computation graph for all executors.
    contexts : ArrayRef[AI::MXNet::Context]
        A array ref of contexts.
    workload : ArrayRef[Num]
        If not undef, could be an array ref of numbers that specify the workload to be assigned
        to different context. Larger number indicate heavier workload.
    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
        Default is AI::MXNet::Logging->get_logger.
    fixed_param_names: Maybe[ArrayRef[Str]]
        Indicate parameters to be fixed during training. Parameters in this array ref will not allocate
        space for gradient, nor do gradient calculation.
    grad_req : ArrayRef[GradReq]|HashRef[GradReq]|GradReq
        Requirement for gradient accumulation. Can be 'write', 'add', or 'null'

lib/AI/MXNet/Executor/Group.pm  view on Meta::CPAN

has 'data_shapes'       => (is => 'rw', isa => 'ArrayRef[NameShape|AI::MXNet::DataDesc]', required => 1);
has 'label_shapes'      => (is => 'rw', isa => 'Maybe[ArrayRef[NameShape|AI::MXNet::DataDesc]]');
has 'param_names'       => (is => 'ro', isa => 'ArrayRef[Str]', required => 1);
has 'for_training'      => (is => 'ro', isa => 'Bool', required => 1);
has 'inputs_need_grad'  => (is => 'ro', isa => 'Bool', default  => 0);
has 'shared_group'      => (is => 'ro', isa => 'Maybe[AI::MXNet::DataParallelExecutorGroup]');
has 'logger'            => (is => 'ro', default => sub { AI::MXNet::Logging->get_logger });
has 'fixed_param_names' => (is => 'rw', isa => 'Maybe[ArrayRef[Str]]');
has 'state_names'       => (is => 'rw', isa => 'Maybe[ArrayRef[Str]]');
has 'grad_req'          => (is => 'rw', isa => 'ArrayRef[GradReq]|HashRef[GradReq]|GradReq', default=>'write');
has '_p'                => (is => 'rw', init_arg => undef);
sub BUILD
{
    my $self = shift;
    my $p = AI::MXNet::DataParallelExecutorGroup::_private->new;
    $p->arg_names($self->symbol->list_arguments);
    $p->aux_names($self->symbol->list_auxiliary_states);
    $p->execs([]);
    $self->_p($p);
    $self->grad_req('null') if not $self->for_training;
    $self->fixed_param_names([]) unless defined $self->fixed_param_names;

lib/AI/MXNet/Executor/Group.pm  view on Meta::CPAN

=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)

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


    Split the data_batch according to a workload and run forward on each devices.

    Parameters
    ----------
    data_batch : AI::MXNet::DataBatch
    Or could be any object implementing similar interface.

    is_train : bool
    The hint for the backend, indicating whether we are during training phase.
    Default is undef, then the value $self->for_training will be used.
=cut


method forward(AI::MXNet::DataBatch $data_batch, Maybe[Bool] $is_train=)
{
    AI::MXNet::Executor::Group::_load_data($data_batch, $self->_p->data_arrays, $self->_p->data_layouts);
    $is_train //= $self->for_training;
    if(defined $self->_p->label_arrays)
    {
        confess("assert not is_train or data_batch.label")

lib/AI/MXNet/Executor/Group.pm  view on Meta::CPAN

    }, $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,

lib/AI/MXNet/IO.pm  view on Meta::CPAN

    {
        return AI::MXNet::DataBatch->new(
            data  => $self->getdata,
            label => $self->getlabel,
            pad   => $self->getpad,
            index => $self->getindex
        );
    }
    else
    {
        return undef;
    }
}

=head2 iter_next

    Iterate to next batch.

    Returns
    -------
    $has_next : Bool

lib/AI/MXNet/IO.pm  view on Meta::CPAN

=cut

has 'data_iter'      => (is => 'ro', isa => 'AI::MXnet::DataIter', required => 1);
has 'size'           => (is => 'ro', isa => 'Int', required => 1);
has 'reset_internal' => (is => 'rw', isa => 'Int', default => 1);
has 'cur'            => (is => 'rw', isa => 'Int', default => 0);
has 'current_batch'  => (is => 'rw', isa => 'Maybe[AI::MXNet::DataBatch]');
has [qw/provide_data
    default_bucket_key
    provide_label
    batch_size/]     => (is => 'rw', init_arg => undef);

sub BUILD
{
    my $self = shift;
    $self->provide_data($self->data_iter->provide_data);
    $self->provide_label($self->data_iter->provide_label);
    $self->batch_size($self->data_iter->batch_size);
    if($self->data_iter->can('default_bucket_key'))
    {
        $self->default_bucket_key($self->data_iter->default_bucket_key);

lib/AI/MXNet/IO.pm  view on Meta::CPAN

}

method next()
{
    if($self->iter_next)
    {
        return AI::MXNet::DataBatch->new(
            data  => $self->getdata,
            label => $self->getlabel,
            pad   => $self->getpad,
            index => undef
        );
    }
    else
    {
        return undef;
    }
}

# Load data from underlying arrays, internal use only
method _getdata($data_source)
{
    confess("DataIter needs reset.") unless $self->cursor < $self->num_data;
    if(($self->cursor + $self->batch_size) <= $self->num_data)
    {
        return [

lib/AI/MXNet/IO.pm  view on Meta::CPAN

=cut

has 'handle'           => (is => 'ro', isa => 'DataIterHandle', required => 1);
has '_debug_skip_load' => (is => 'rw', isa => 'Int', default => 0);
has '_debug_at_begin'  => (is => 'rw', isa => 'Int', default => 0);
has 'data_name'        => (is => 'ro', isa => 'Str', default => 'data');
has 'label_name'       => (is => 'ro', isa => 'Str', default => 'softmax_label');
has [qw/first_batch
        provide_data
        provide_label
        batch_size/]   => (is => 'rw', init_arg => undef);

sub BUILD
{
    my $self = shift;
    $self->first_batch($self->next);
    my $data = $self->first_batch->data->[0];
    $self->provide_data([
        AI::MXNet::DataDesc->new(
            name  => $self->data_name,
            shape => $data->shape,

lib/AI/MXNet/IO.pm  view on Meta::CPAN


method debug_skip_load()
{
    $self->_debug_skip_load(1);
    AI::MXNet::Logging->info('Set debug_skip_load to be true, will simply return first batch');
}

method reset()
{
    $self->_debug_at_begin(1);
    $self->first_batch(undef);
    check_call(AI::MXNetCAPI::DataIterBeforeFirst($self->handle));
}

method next()
{
    if($self->_debug_skip_load and not $self->_debug_at_begin)
    {
        return  AI::MXNet::DataBatch->new(
                    data  => [$self->getdata],
                    label => [$self->getlabel],
                    pad   => $self->getpad,
                    index => $self->getindex
        );
    }
    if(defined $self->first_batch)
    {
        my $batch = $self->first_batch;
        $self->first_batch(undef);
        return $batch
    }
    $self->_debug_at_begin(0);
    my $next_res =  check_call(AI::MXNetCAPI::DataIterNext($self->handle));
    if($next_res)
    {
        return  AI::MXNet::DataBatch->new(
                    data  => [$self->getdata],
                    label => [$self->getlabel],
                    pad   => $self->getpad,
                    index => $self->getindex
        );
    }
    else
    {
        return undef;
    }
}

method iter_next()
{
    if(defined $self->first_batch)
    {
        return 1;
    }
    else

lib/AI/MXNet/Image.pm  view on Meta::CPAN

has 'num_parts'   => (is => 'ro', isa => 'Int', default => 0);
has 'aug_list'    => (is => 'rw', isa => 'ArrayRef[CodeRef]');
has 'imglist'     => (is => 'rw', isa => 'ArrayRef|HashRef');
has 'kwargs'      => (is => 'ro', isa => 'HashRef');
has [qw/imgidx
        imgrec
        seq
        cur
        provide_data
        provide_label
           /]     => (is => 'rw', init_arg => undef);

sub BUILD
{
    my $self = shift;
    assert($self->path_imgrec or $self->path_imglist or ref $self->imglist eq 'ARRAY');
    if($self->path_imgrec)
    {
        print("loading recordio...\n");
        if($self->path_imgidx)
        {

lib/AI/MXNet/Image.pm  view on Meta::CPAN

    {
        $self->imgrec->reset;
    }
    $self->cur(0);
}

method next_sample()
{
    if(defined $self->seq)
    {
        return undef if($self->cur >= @{ $self->seq });
        my $idx = $self->seq->[$self->cur];
        $self->cur($self->cur + 1);
        if(defined $self->imgrec)
        {
            my $s = $self->imgrec->read_idx($idx);
            my ($header, $img) = AI::MXNet::RecordIO->unpack($s);
            if(not defined $self->imglist)
            {
                return ($header->label, $img);
            }

lib/AI/MXNet/Image.pm  view on Meta::CPAN

                return ($self->imglist->{$idx}[0], $img);
            }
        }
        else
        {
            my ($label, $fname) = @{ $self->imglist->{$idx} };
            if(not defined $self->imgrec)
            {
                open(F, $self->path_root . "/$fname") or confess("can't open $fname $!");
                my $img;
                { local $/ = undef; $img = <F> };
                close(F);
                return ($label, $img);
            }
        }
    }
    else
    {
        my $s = $self->imgrec->read;
        return undef if(not defined $s);
        my ($header, $img) = AI::MXNet::RecordIO->unpack($s);
        return ($header->label, $img)
    }
}

method next()
{
    my $batch_size = $self->batch_size;
    my ($c, $h, $w) = @{ $self->data_shape };
    my $batch_data  = AI::MXNet::NDArray->empty([$batch_size, $c, $h, $w]);

lib/AI/MXNet/Image.pm  view on Meta::CPAN

            $data = [map { @{ $aug->($_) } } @$data];
        }
        for my $d (@$data)
        {
            assert(($i < $batch_size), 'Batch size must be multiples of augmenter output length');
            $batch_data->at($i)  .= AI::MXNet::NDArray->transpose($d, { axes=>[2, 0, 1] });
            $batch_label->at($i) .= $label;
            $i++;
        }
    }
    return undef if not $i;
    return AI::MXNet::DataBatch->new(data=>[$batch_data], label=>[$batch_label], pad => $batch_size-$i);
}

1;

lib/AI/MXNet/Initializer.pm  view on Meta::CPAN

use overload "&{}" => sub { my $self = shift; sub { $self->call(@_) } },
             '""'  => sub {
                my $self = shift;
                my ($name) = ref($self) =~ /::(\w+)$/;
                encode_json(
                    [lc $name,
                        $self->kwargs//{ map { $_ => "".$self->$_ } $self->meta->get_attribute_list }
                ]);
             },
             fallback => 1;
has 'kwargs' => (is => 'rw', init_arg => undef, isa => 'HashRef');
has '_verbose'    => (is => 'rw', isa => 'Bool', lazy => 1, default => 0);
has '_print_func' => (is => 'rw', isa => 'CodeRef', lazy => 1,
    default => sub {
        return sub {
            my $x = shift;
            return ($x->norm/sqrt($x->size))->asscalar;
        };
    }
);

lib/AI/MXNet/Initializer.pm  view on Meta::CPAN

    patterns: array ref of str
        array ref of regular expression patterns to match parameter names.
    initializers: array ref of AI::MXNet::Initializer objects.
        array ref of Initializers corresponding to the patterns.
=cut

package AI::MXNet::Mixed;
use Mouse;
extends 'AI::MXNet::Initializer';

has "map"          => (is => "rw", init_arg => undef);
has "patterns"     => (is => "ro", isa => 'ArrayRef[Str]');
has "initializers" => (is => "ro", isa => 'ArrayRef[AI::MXnet::Initializer]');

sub BUILD
{
    my $self = shift;
    confess("patterns count != initializers count")
        unless (@{ $self->patterns } == @{ $self->initializers });
    my %map;
    @map{ @{ $self->patterns } } = @{ $self->initializers };

lib/AI/MXNet/KVStore.pm  view on Meta::CPAN

    fname : str
        Path to input states file.
=cut

method load_optimizer_states(Str $fname)
{
    confess("Cannot save states for distributed training")
        unless defined $self->_updater;
    open(F, "<:raw", "$fname") or confess("can't open $fname for reading: $!");
    my $data;
    { local($/) = undef; $data = <F>; }
    close(F);
    $self->_updater->set_states($data);
}

=head2 _set_updater

    Set a push updater into the store.

    This function only changes the local store. Use set_optimizer for
    multi-machines.

lib/AI/MXNet/Metric.pm  view on Meta::CPAN


    AI::MXNet::Perplexity
=cut

=head1 DESCRIPTION

    Calculate perplexity.

    Parameters
    ----------
    ignore_label : int or undef
        index of invalid label to ignore when
        counting. usually should be -1. Include
        all entries if undef.
    axis : int (default -1)
        The axis from prediction that was used to
        compute softmax. By default uses the last
        axis.
=cut

method update(ArrayRef[AI::MXNet::NDArray] $labels, ArrayRef[AI::MXNet::NDArray] $preds)
{
    AI::MXNet::Metric::check_label_shapes($labels, $preds);
    my ($loss, $num) = (0, 0);

lib/AI/MXNet/Module.pm  view on Meta::CPAN


package AI::MXNet::Module::Private;
use Mouse;
has [qw/_param_names _fixed_param_names
        _aux_names _data_names _label_names _state_names
        _output_names _arg_params _aux_params
        _params_dirty _optimizer _kvstore
         _update_on_kvstore _updater _work_load_list
        _preload_opt_states _exec_group
        _data_shapes _label_shapes _context _grad_req/
] => (is => 'rw', init_arg => undef);

package AI::MXNet::Module;
use AI::MXNet::Base;
use AI::MXNet::Function::Parameters;
use List::Util qw(max);
use Data::Dumper ();
use Mouse;

func _create_kvstore(
    Maybe[Str|AI::MXNet::KVStore] $kvstore,

lib/AI/MXNet/Module.pm  view on Meta::CPAN


extends 'AI::MXNet::Module::Base';

has '_symbol'           => (is => 'ro', init_arg => 'symbol', isa => 'AI::MXNet::Symbol', required => 1);
has '_data_names'       => (is => 'ro', init_arg => 'data_names', isa => 'ArrayRef[Str]');
has '_label_names'      => (is => 'ro', init_arg => 'label_names', isa => 'Maybe[ArrayRef[Str]]');
has 'work_load_list'    => (is => 'rw', isa => 'Maybe[ArrayRef[Int]]');
has 'fixed_param_names' => (is => 'rw', isa => 'Maybe[ArrayRef[Str]]');
has 'state_names'       => (is => 'rw', isa => 'Maybe[ArrayRef[Str]]');
has 'logger'            => (is => 'ro', default => sub { AI::MXNet::Logging->get_logger });
has '_p'                => (is => 'rw', init_arg => undef);
has 'context'           => (
    is => 'ro', 
    isa => 'AI::MXNet::Context|ArrayRef[AI::MXNet::Context]',
    default => sub { AI::MXNet::Context->cpu }
);

around BUILDARGS => sub {
    my $orig  = shift;
    my $class = shift;
    if(@_%2)

lib/AI/MXNet/Module.pm  view on Meta::CPAN

        data_names : array ref of str
            Default is ['data'] for a typical model used in image classification.
        label_names : array ref of str
            Default is ['softmax_label'] for a typical model used in image
            classification.
        logger : Logger
            Default is AI::MXNet::Logging.
        context : Context or list of Context
            Default is cpu(0).
        work_load_list : array ref of number
            Default is undef, indicating an uniform workload.
        fixed_param_names: array ref of str
            Default is undef, indicating no network parameters are fixed.
=cut

method load(
    Str $prefix,
    Int $epoch,
    Bool $load_optimizer_states=0,
    %kwargs
)
{
    my ($sym, $args, $auxs) = __PACKAGE__->load_checkpoint($prefix, $epoch);

lib/AI/MXNet/Module.pm  view on Meta::CPAN

    }
    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;
}

method label_names()
{
    return $self->_p->_label_names;

lib/AI/MXNet/Module.pm  view on Meta::CPAN

    :$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,

lib/AI/MXNet/Module.pm  view on Meta::CPAN

                ."is not normalized to 1.0/batch_size/num_workers (%s vs. %s). "
                ."Is this intended?",
                $optimizer->rescale_grad, $rescale_grad
            );
        }
    }

    $self->_p->_optimizer($optimizer);
    $self->_p->_kvstore($kvstore);
    $self->_p->_update_on_kvstore($update_on_kvstore);
    $self->_p->_updater(undef);

    if($kvstore)
    {
        # copy initialized local parameters to kvstore
        _initialize_kvstore(
            kvstore           => $kvstore,
            param_arrays      => $self->_p->_exec_group->_p->param_arrays,
            arg_params        => $self->_p->_arg_params,
            param_names       => $self->_p->_param_names,
            update_on_kvstore => $update_on_kvstore

lib/AI/MXNet/Module.pm  view on Meta::CPAN

    }
    else
    {
        $self->_p->_updater(AI::MXNet::Optimizer->get_updater($optimizer));
    }
    $self->optimizer_initialized(1);

    if($self->_p->_preload_opt_states)
    {
        $self->load_optimizer_states($self->_p->_preload_opt_states);
        $self->_p->_preload_opt_states(undef);
    }
}

=head2 borrow_optimizer

    Borrow optimizer from a shared module. Used in bucketing, where exactly the same
    optimizer (esp. kvstore) is used.

    Parameters
    ----------

lib/AI/MXNet/Module.pm  view on Meta::CPAN

{
    assert($self->optimizer_initialized);
    if($self->_p->_update_on_kvstore)
    {
        $self->_p->_kvstore->load_optimizer_states($fname);
    }
    else
    {
        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);
}

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN

    backward, update parameters, etc. We aim to make the APIs easy to use, especially in the
    case when we need to use imperative API to work with multiple modules (e.g. stochastic
    depth network).

    A module has several states:

        - 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.

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN

        - 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

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN

=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

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN

}

=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)
    {

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN

}

=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
    -------

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN

}

=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.

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN

        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.

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN


=head2 init_params

    Initialize the parameters and auxiliary states.

    Parameters
    ----------
    :$initializer : Maybe[AI::MXNet::Initializer]
        Called to initialize parameters if needed.
    :$arg_params= : Maybe[HashRef[AI::MXNet::NDArray]]
        If not undef, should be a hash ref of existing arg_params.
    :$aux_params : Maybe[HashRef[AI::MXNet::NDArray]]
        If not undef, should be a hash ref of existing aux_params.
    :$allow_missing=0 : Bool
        If true, params could contain missing values, and the initializer will be
        called to fill those missing params.
    :$force_init=0 : Bool
        If true, will force re-initialize even if already initialized.
    :$allow_extra=0 : Boolean, optional
        Whether allow extra parameters that are not needed by symbol.
        If this is True, no error will be thrown when arg_params or aux_params
        contain extra parameters that is not needed by the executor.
=cut

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN


method set_params(
    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
)
{
    $self->init_params(
        initializer   => undef,
        arg_params    => $arg_params,
        aux_params    => $aux_params,
        allow_missing => $allow_missing,
        force_init    => $force_init,
        allow_extra   => $allow_extra
    );
}

=head2 save_params

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN

    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
    ----------

lib/AI/MXNet/Module/Base.pm  view on Meta::CPAN

    :$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,

lib/AI/MXNet/Module/Bucketing.pm  view on Meta::CPAN

    ----------
    $sym_gen : subref or any perl object that overloads &{} op
        A sub when called with a bucket key, returns a list with triple
        of ($symbol, $data_names, $label_names).
    $default_bucket_key : str or anything else
        The key for the default bucket.
    $logger : Logger
    $context : AI::MXNet::Context or array ref of AI::MXNet::Context objects
        Default is cpu(0)
    $work_load_list : array ref of Num
        Default is undef, indicating uniform workload.
    $fixed_param_names: arrayref of str
        Default is undef, indicating no network parameters are fixed.
    $state_names : arrayref of str
        states are similar to data and label, but not provided by data iterator.
        Instead they are initialized to 0 and can be set by set_states()
=cut

extends 'AI::MXNet::Module::Base';
has '_sym_gen'            => (is => 'ro', init_arg => 'sym_gen', required => 1);
has '_default_bucket_key' => (is => 'rw', init_arg => 'default_bucket_key', required => 1);
has '_context'            => (
    is => 'ro', isa => 'AI::MXNet::Context|ArrayRef[AI::MXNet::Context]',
    lazy => 1, default => sub { AI::MXNet::Context->cpu },
    init_arg => 'context'
);
has '_work_load_list'     => (is => 'rw', init_arg => 'work_load_list', isa => 'ArrayRef[Num]');
has '_curr_module'        => (is => 'rw', init_arg => undef);
has '_curr_bucket_key'    => (is => 'rw', init_arg => undef);
has '_buckets'            => (is => 'rw', init_arg => undef, default => sub { +{} });
has '_fixed_param_names'  => (is => 'rw', isa => 'ArrayRef[Str]', init_arg => 'fixed_param_names');
has '_state_names'        => (is => 'rw', isa => 'ArrayRef[Str]', init_arg => 'state_names');
has '_params_dirty'       => (is => 'rw', init_arg => undef);

sub BUILD
{
    my ($self, $original_params) = @_;
    $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
    {

lib/AI/MXNet/Module/Bucketing.pm  view on Meta::CPAN

        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,

lib/AI/MXNet/Module/Bucketing.pm  view on Meta::CPAN

            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)
    {
        $self->set_params($arg_params, $aux_params);

lib/AI/MXNet/Monitor.pm  view on Meta::CPAN

        return sub {
            # returns |x|/size(x), async execution.
            my ($x) = @_;
            return $x->norm/sqrt($x->size);
        }
    },
    lazy => 1
);
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 {
        my $self = shift;
        return sub {
            my ($name, $handle) = @_;
            return if(not $self->activated or not $name =~ $self->re_pattern);
            my $array = AI::MXNet::NDArray->new(handle => $handle, writable => 0);
            push @{ $self->queue }, [$self->step, $name, $self->stat_func->($array)];
        }
    },
    lazy => 1

lib/AI/MXNet/NDArray.pm  view on Meta::CPAN

    my $handle = check_call(AI::MXNetCAPI::NDArrayDetach($self->handle));
    return __PACKAGE__->new(handle => $handle);
}

method backward(Maybe[AI::MXNet::NDArray] $out_grad=, Bool $retain_graph=0)
{
    check_call(
        AI::MXNetCAPI::AutogradBackward(
            1,
            [$self->handle],
            [defined $out_grad ? $out_grad->handle : undef],
            $retain_graph
        )
    )
}

method CachedOp(@args) { AI::MXNet::CachedOp->new(@args) }

my $lvalue_methods = join "\n", map {"use attributes 'AI::MXNet::NDArray', \\&AI::MXNet::NDArray::$_, 'lvalue';"}
qw/at slice aspdl asmpdl reshape copy sever T astype as_in_context copyto empty zero ones full
                       array/;

lib/AI/MXNet/Optimizer.pm  view on Meta::CPAN

        rescaling factor of gradient. Normally should be 1/batch_size.

    clip_gradient : float, optional
        clip gradient in range [-clip_gradient, clip_gradient]

    param_idx2name : hash ref of string/int to float, optional
        special treat weight decay in parameter ends with bias, gamma, and beta
=cut
has 'momentum'        => (is => 'ro', isa => 'Num', default => 0);
has 'lamda'           => (is => 'ro', isa => 'Num', default => 0.04);
has 'weight_previous' => (is => 'rw', init_arg => undef);

sub BUILD
{
    my $self = shift;
    $self->weight_previous({});
}

method create_state(Index $index, AI::MXNet::NDArray $weight)
{
        return [
            $self->momentum ? AI::MXNet::NDArray->zeros(
                $weight->shape, ctx => $weight->context, dtype => $weight->dtype
            ) : undef,
            $weight->copy
        ];
}

method update(
    Index                     $index,
    AI::MXNet::NDArray        $weight,
    AI::MXNet::NDArray        $grad,
    Maybe[AI::MXNet::NDArray] $state
)

lib/AI/MXNet/Optimizer.pm  view on Meta::CPAN

        special treat weight decay in parameter ends with bias, gamma, and beta
=cut

package AI::MXNet::SLGD;
use Mouse;

extends 'AI::MXNet::Optimizer';

method create_state(Index $index, AI::MXNet::NDArray $weight)
{
    return undef;
}

method update(
    Index $index, 
    AI::MXNet::NDArray $weight,
    AI::MXNet::NDArray $grad,
    AI::MXNet::NDArray|Undef $state
)
{
    my $lr = $self->_get_lr($index);

lib/AI/MXNet/Optimizer.pm  view on Meta::CPAN

use Mouse;

extends 'AI::MXNet::Optimizer';

has '+learning_rate' => (default => 0.001);
has 'gamma1'         => (is => "ro", isa => "Num",  default => 0.9);
has 'gamma2'         => (is => "ro", isa => "Num",  default => 0.9);
has 'epsilon'        => (is => "ro", isa => "Num",  default => 1e-8);
has 'centered'       => (is => "ro", isa => "Bool", default => 0);
has 'clip_weights'   => (is => "ro", isa => "Num");
has 'kwargs'         => (is => "rw", init_arg => undef);

sub BUILD
{
    my $self = shift;
    $self->kwargs({
        rescale_grad => $self->rescale_grad,
        gamma1       => $self->gamma1,
        epsilon      => $self->epsilon
    });
    if($self->centered)

lib/AI/MXNet/Optimizer.pm  view on Meta::CPAN

        Exponential decay rate for the momentum schedule
=cut

use Mouse;
extends 'AI::MXNet::Optimizer';
has '+learning_rate' => (default => 0.001);
has 'beta1'          => (is => "ro", isa => "Num",  default => 0.9);
has 'beta2'          => (is => "ro", isa => "Num",  default => 0.999);
has 'epsilon'        => (is => "ro", isa => "Num",  default => 1e-8);
has 'schedule_decay' => (is => "ro", isa => "Num",  default => 0.004);
has 'm_schedule'     => (is => "rw", default => 1, init_arg => undef);

method create_state(Index $index, AI::MXNet::NDArray $weight)
{
    return [
            AI::MXNet::NDArray->zeros(
                $weight->shape,
                ctx => $weight->context,
                dtype => $weight->dtype
            ),  # mean
            AI::MXNet::NDArray->zeros(

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

    A container for holding variables.
    Used by RNN cells for parameter sharing between cells.

    Parameters
    ----------
    prefix : str
        All variables name created by this container will
        be prepended with the prefix
=cut
has '_prefix' => (is => 'ro', init_arg => 'prefix', isa => 'Str', default => '');
has '_params' => (is => 'rw', init_arg => undef);
around BUILDARGS => sub {
    my $orig  = shift;
    my $class = shift;
    return $class->$orig(prefix => $_[0]) if @_ == 1;
    return $class->$orig(@_);
};

sub BUILD
{
    my $self = shift;

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

=cut

=head1 DESCRIPTION

    Abstract base class for RNN cells

    Parameters
    ----------
    prefix : str
        prefix for name of layers
        (and name of weight if params is undef)
    params : AI::MXNet::RNN::Params or undef
        container for weight sharing between cells.
        created if undef.
=cut

use AI::MXNet::Base;
use Mouse;
use overload "&{}"  => sub { my $self = shift; sub { $self->call(@_) } };
has '_prefix'       => (is => 'rw', init_arg => 'prefix', isa => 'Str', default => '');
has '_params'       => (is => 'rw', init_arg => 'params', isa => 'Maybe[AI::MXNet::RNN::Params]');
has [qw/_own_params
        _modified
        _init_counter
        _counter
                 /] => (is => 'rw', init_arg => undef);

around BUILDARGS => sub {
    my $orig  = shift;
    my $class = shift;
    return $class->$orig(prefix => $_[0]) if @_ == 1;
    return $class->$orig(@_);
};

sub BUILD
{

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

}

=head2 unroll

    Unroll an RNN cell across time steps.

    Parameters
    ----------
    :$length : Int
        number of steps to unroll
    :$inputs : AI::MXNet::Symbol, array ref of Symbols, or undef
        if inputs is a single Symbol (usually the output
        of Embedding symbol), it should have shape
        of [$batch_size, $length, ...] if layout == 'NTC' (batch, time series)
        or ($length, $batch_size, ...) if layout == 'TNC' (time series, batch).

        If inputs is a array ref of symbols (usually output of
        previous unroll), they should all have shape
        ($batch_size, ...).

        If inputs is undef, a placeholder variables are
        automatically created.
    :$begin_state : array ref of Symbol
        input states. Created by begin_state()
        or output state of another cell. Created
        from begin_state() if undef.
    :$input_prefix : str
        prefix for automatically created input
        placehodlers.
    :$layout : str
        layout of input symbol. Only used if the input
        is a single Symbol.
    :$merge_outputs : Bool
        If 0, returns outputs as an array ref of Symbols.
        If 1, concatenates the output across the time steps
        and returns a single symbol with the shape
        [$batch_size, $length, ...) if the layout equal to 'NTC',
        or [$length, $batch_size, ...) if the layout equal tp 'TNC'.
        If undef, output whatever is faster

    Returns
    -------
    $outputs : array ref of Symbol or Symbol
        output symbols.
    $states : Symbol or nested list of Symbol
        has the same structure as begin_state()
=cut


lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

    Simple recurrent neural network cell

    Parameters
    ----------
    num_hidden : int
        number of units in output symbol
    activation : str or Symbol, default 'tanh'
        type of activation function
    prefix : str, default 'rnn_'
        prefix for name of layers
        (and name of weight if params is undef)
    params : AI::MXNet::RNNParams or undef
        container for weight sharing between cells.
        created if undef.
=cut

has '_num_hidden'  => (is => 'ro', init_arg => 'num_hidden', isa => 'Int', required => 1);
has 'forget_bias'  => (is => 'ro', isa => 'Num');
has '_activation'  => (
    is       => 'ro',
    init_arg => 'activation',
    isa      => 'Activation',
    default  => 'tanh'
);
has '+_prefix'    => (default => 'rnn_');
has [qw/_iW _iB
        _hW _hB/] => (is => 'rw', init_arg => undef);

around BUILDARGS => sub {
    my $orig  = shift;
    my $class = shift;
    return $class->$orig(num_hidden => $_[0]) if @_ == 1;
    return $class->$orig(@_);
};

sub BUILD
{

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

=head1 DESCRIPTION

    Long-Short Term Memory (LSTM) network cell.

    Parameters
    ----------
    num_hidden : int
        number of units in output symbol
    prefix : str, default 'lstm_'
        prefix for name of layers
        (and name of weight if params is undef)
    params : AI::MXNet::RNN::Params or None
        container for weight sharing between cells.
        created if undef.
    forget_bias : bias added to forget gate, default 1.0.
        Jozefowicz et al. 2015 recommends setting this to 1.0
=cut

has '+_prefix'     => (default => 'lstm_');
has '+_activation' => (init_arg => undef);
has '+forget_bias' => (is => 'ro', isa => 'Num', default => 1);

method state_info()
{
    return [{ shape => [0, $self->_num_hidden], __layout__ => 'NC' } , { shape => [0, $self->_num_hidden], __layout__ => 'NC' }];
}

method _gate_names()
{
    [qw/_i _f _c _o/];

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

    Gated Rectified Unit (GRU) network cell.
    Note: this is an implementation of the cuDNN version of GRUs
    (slight modification compared to Cho et al. 2014).

    Parameters
    ----------
    num_hidden : int
        number of units in output symbol
    prefix : str, default 'gru_'
        prefix for name of layers
        (and name of weight if params is undef)
    params : AI::MXNet::RNN::Params or undef
        container for weight sharing between cells.
        created if undef.
=cut

has '+_prefix'     => (default => 'gru_');

method _gate_names()
{
    [qw/_r _z _o/];
}

method call(AI::MXNet::Symbol $inputs, SymbolOrArrayOfSymbols $states)

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

has '_bidirectional'   => (is => 'ro', isa => 'Bool', init_arg => 'bidirectional',  default => 0);
has 'forget_bias'      => (is => 'ro', isa => 'Num',  default => 1);
has 'initializer'      => (is => 'rw', isa => 'Maybe[Initializer]');
has '_mode'            => (
    is => 'ro',
    isa => enum([qw/rnn_relu rnn_tanh lstm gru/]),
    init_arg => 'mode',
    default => 'lstm'
);
has [qw/_parameter
        _directions/] => (is => 'rw', init_arg => undef);

around BUILDARGS => sub {
    my $orig  = shift;
    my $class = shift;
    return $class->$orig(num_hidden => $_[0]) if @_ == 1;
    return $class->$orig(@_);
};

sub BUILD
{

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN


    AI:MXNet::RNN::SequentialCell
=cut

=head1 DESCRIPTION

    Sequentially stacking multiple RNN cells

    Parameters
    ----------
    params : AI::MXNet::RNN::Params or undef
        container for weight sharing between cells.
        created if undef.
=cut

has [qw/_override_cell_params _cells/] => (is => 'rw', init_arg => undef);

sub BUILD
{
    my ($self, $original_arguments) = @_;
    $self->_override_cell_params(defined $original_arguments->{params});
    $self->_cells([]);
}

=head2 add

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

        my ($i, $cell) = @_;
        my $n   = @{ $cell->state_info };
        $states = [@{$begin_state}[$p..$p+$n-1]];
        $p += $n;
        ($inputs, $states) = $cell->unroll(
            $length,
            inputs          => $inputs,
            input_prefix    => $input_prefix,
            begin_state     => $states,
            layout          => $layout,
            merge_outputs   => ($i < $num_cells-1) ? undef : $merge_outputs
        );
        push @next_states, $states;
    }, $self->_cells);
    return ($inputs, [map { @{ $_ } } @next_states]);
}

package AI::MXNet::RNN::BidirectionalCell;
use Mouse;
use AI::MXNet::Base;
extends 'AI::MXNet::RNN::Cell::Base';

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

        cell for forward unrolling
    r_cell : AI::MXNet::RNN::Cell::Base
        cell for backward unrolling
    output_prefix : str, default 'bi_'
        prefix for name of output
=cut

has 'l_cell'         => (is => 'ro', isa => 'AI::MXNet::RNN::Cell::Base', required => 1);
has 'r_cell'         => (is => 'ro', isa => 'AI::MXNet::RNN::Cell::Base', required => 1);
has '_output_prefix' => (is => 'ro', init_arg => 'output_prefix', isa => 'Str', default => 'bi_');
has [qw/_override_cell_params _cells/] => (is => 'rw', init_arg => undef);

around BUILDARGS => sub {
    my $orig  = shift;
    my $class = shift;
    if(@_ >= 2 and blessed $_[0] and blessed $_[1])
    {
        my $l_cell = shift(@_);
        my $r_cell = shift(@_);
        return $class->$orig(
            l_cell => $l_cell,

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

=cut

=head1 DESCRIPTION

    Abstract base class for Convolutional RNN cells

=cut

has '_h2h_kernel'  => (is => 'ro', isa => 'Shape', init_arg => 'h2h_kernel');
has '_h2h_dilate'  => (is => 'ro', isa => 'Shape', init_arg => 'h2h_dilate');
has '_h2h_pad'     => (is => 'rw', isa => 'Shape', init_arg => undef);
has '_i2h_kernel'  => (is => 'ro', isa => 'Shape', init_arg => 'i2h_kernel');
has '_i2h_stride'  => (is => 'ro', isa => 'Shape', init_arg => 'i2h_stride');
has '_i2h_dilate'  => (is => 'ro', isa => 'Shape', init_arg => 'i2h_dilate');
has '_i2h_pad'     => (is => 'ro', isa => 'Shape', init_arg => 'i2h_pad');
has '_num_hidden'  => (is => 'ro', isa => 'DimSize', init_arg => 'num_hidden');
has '_input_shape' => (is => 'ro', isa => 'Shape', init_arg => 'input_shape');
has '_conv_layout' => (is => 'ro', isa => 'Str', init_arg => 'conv_layout', default => 'NCHW');
has '_activation'  => (is => 'ro', init_arg => 'activation');
has '_state_shape' => (is => 'rw', init_arg => undef);
has [qw/i2h_weight_initializer h2h_weight_initializer
    i2h_bias_initializer h2h_bias_initializer/] => (is => 'rw', isa => 'Maybe[Initializer]');

sub BUILD
{
    my $self = shift;
    assert (
        ($self->_h2h_kernel->[0] % 2 == 1 and $self->_h2h_kernel->[1] % 2 == 1),
        "Only support odd numbers, got h2h_kernel= (@{[ $self->_h2h_kernel ]})"
    );

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

has '+_i2h_kernel' => (default => sub { [3, 3] });
has '+_i2h_stride' => (default => sub { [1, 1] });
has '+_i2h_dilate' => (default => sub { [1, 1] });
has '+_i2h_pad'    => (default => sub { [1, 1] });
has '+_prefix'     => (default => 'ConvRNN_');
has '+_activation' => (default => sub { sub { AI::MXNet::Symbol->LeakyReLU(@_, act_type => 'leaky', slope => 0.2) } });
has '+i2h_bias_initializer' => (default => 'zeros');
has '+h2h_bias_initializer' => (default => 'zeros');
has 'forget_bias'  => (is => 'ro', isa => 'Num');
has [qw/_iW _iB
        _hW _hB/] => (is => 'rw', init_arg => undef);


sub BUILD
{
    my $self = shift;
    $self->_iW($self->_params->get('i2h_weight', init => $self->i2h_weight_initializer));
    $self->_hW($self->_params->get('h2h_weight', init => $self->h2h_weight_initializer));
    $self->_iB(
        $self->params->get(
            'i2h_bias',

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

        $states = [map { AI::MXNet::Symbol->Dropout(data => $_, p => $self->dropout_states) } @{ $states }];
    }
    return ($output, $states);
}

package AI::MXNet::RNN::ZoneoutCell;
use Mouse;
use AI::MXNet::Base;
extends 'AI::MXNet::RNN::ModifierCell';
has [qw/zoneout_outputs zoneout_states/] => (is => 'ro', isa => 'Num', default => 0);
has 'prev_output' => (is => 'rw', init_arg => undef);

=head1 NAME

    AI::MXNet::RNN::ZoneoutCell
=cut

=head1 DESCRIPTION

    Apply Zoneout on base cell.
=cut

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

    assert(
        (not $self->base_cell->isa('AI::MXNet::RNN::SequentialCell') or not $self->_bidirectional),
        "Bidirectional SequentialCell doesn't support zoneout. ".
        "Please add ZoneoutCell to the cells underneath instead."
    );
}

method reset()
{
    $self->SUPER::reset;
    $self->prev_output(undef);
}

method call(AI::MXNet::Symbol $inputs, SymbolOrArrayOfSymbols $states)
{
    my ($cell, $p_outputs, $p_states) = ($self->base_cell, $self->zoneout_outputs, $self->zoneout_states);
    my ($next_output, $next_states) = &{$cell}($inputs, $states);
    my $mask = sub {
        my ($p, $like) = @_;
        AI::MXNet::Symbol->Dropout(
            AI::MXNet::Symbol->ones_like(

lib/AI/MXNet/RNN/Cell.pm  view on Meta::CPAN

                            name=>$output_sym->name."_plus_residual");
        }, [@{ $outputs }], [@{ $inputs }]);
        $outputs = \@temp;
    }
    return ($outputs, $states);
}

func _normalize_sequence($length, $inputs, $layout, $merge, $in_layout=)
{
    assert((defined $inputs),
        "unroll(inputs=>undef) has been deprecated. ".
        "Please create input variables outside unroll."
    );

    my $axis = index($layout, 'T');
    my $in_axis = defined $in_layout ? index($in_layout, 'T') : $axis;
    if(blessed($inputs))
    {
        if(not $merge)
        {
            assert(

lib/AI/MXNet/RNN/IO.pm  view on Meta::CPAN


    Encode sentences and (optionally) build a mapping
    from string tokens to integer indices. Unknown keys
    will be added to vocabulary.

    Parameters
    ----------
    $sentences : array ref of array refs of str
        A array ref of sentences to encode. Each sentence
        should be a array ref of string tokens.
    :$vocab : undef or hash ref of str -> int
        Optional input Vocabulary
    :$invalid_label : int, default -1
        Index for invalid token, like <end-of-sentence>
    :$invalid_key : str, default '\n'
        Key for invalid token. Uses '\n' for end
        of sentence by default.
    :$start_label=0 : int
        lowest index.

    Returns

lib/AI/MXNet/RNN/IO.pm  view on Meta::CPAN

    ----------
    sentences : array ref of array refs of int
        encoded sentences
    batch_size : int
        batch_size of data
    invalid_label : int, default -1
        key for invalid label, e.g. <end-of-sentence>
    dtype : str, default 'float32'
        data type
    buckets : array ref of int
        size of data buckets. Automatically generated if undef.
    data_name : str, default 'data'
        name of data
    label_name : str, default 'softmax_label'
        name of label
    layout : str
        format of data and label. 'NT' means (batch_size, length)
        and 'TN' means (length, batch_size).
=cut

use Mouse;

lib/AI/MXNet/RNN/IO.pm  view on Meta::CPAN

has 'invalid_label' => (is => 'ro', isa => 'Int',   default => -1);
has 'data_name'     => (is => 'ro', isa => 'Str',   default => 'data');
has 'label_name'    => (is => 'ro', isa => 'Str',   default => 'softmax_label');
has 'dtype'         => (is => 'ro', isa => 'Dtype', default => 'float32');
has 'layout'        => (is => 'ro', isa => 'Str',   default => 'NT');
has 'buckets'       => (is => 'rw', isa => 'Maybe[ArrayRef[Int]]');
has [qw/data nddata ndlabel
        major_axis default_bucket_key
        provide_data provide_label
        idx curr_idx
    /]              => (is => 'rw', init_arg => undef);

sub BUILD
{
    my $self = shift;
    if(not defined $self->buckets)
    {
        my @buckets;
        my $p = pdl([map { scalar(@$_) } @{ $self->sentences }]);
        enumerate(sub {
            my ($i, $j) = @_;

lib/AI/MXNet/RNN/IO.pm  view on Meta::CPAN

        my $label = $buck->zeros;
        $label->slice([0, -2], 'X')  .= $buck->slice([1, -1], 'X');
        $label->slice([-1, -1], 'X') .= $self->invalid_label;
        push @{ $self->nddata }, AI::MXNet::NDArray->array($buck, dtype => $self->dtype);
        push @{ $self->ndlabel }, AI::MXNet::NDArray->array($label, dtype => $self->dtype);
    }
}

method next()
{
    return undef if($self->curr_idx == @{ $self->idx });
    my ($i, $j) = @{ $self->idx->[$self->curr_idx] };
    $self->curr_idx($self->curr_idx + 1);
    my ($data, $label);
    if($self->major_axis == 1)
    {
        $data  = $self->nddata->[$i]->slice([$j, $j+$self->batch_size-1])->T;
        $label = $self->ndlabel->[$i]->slice([$j, $j+$self->batch_size-1])->T;
    }
    else
    {

lib/AI/MXNet/RecordIO.pm  view on Meta::CPAN

    idx_path : str
        Path to index file
    uri : str
        Path to record file. Only support file types that are seekable.
    flag : str
        'w' for write or 'r' for read
=cut

has 'idx_path'  => (is => 'ro', isa => 'Str', required => 1);
has [qw/idx
    keys fidx/] => (is => 'rw', init_arg => undef);

method open()
{
    $self->SUPER::open();
    $self->idx({});
    $self->keys([]);
    open(my $f, $self->flag eq 'r' ? '<' : '>', $self->idx_path);
    $self->fidx($f);
    if(not $self->writable)
    {

lib/AI/MXNet/RecordIO.pm  view on Meta::CPAN

            push @{ $self->keys }, $key;
            $self->idx->{$key} = $val;
        }
    }
}

method close()
{
    return if not $self->is_open;
    $self->SUPER::close();
    $self->fidx(undef);
}

=head2 seek

    Query current read head position.
=cut

method seek(Int $idx)
{
    assert(not $self->writable);

lib/AI/MXNet/Rtc.pm  view on Meta::CPAN

        extern "C" __global__ mykernel(float *x, float *y) {
            const int x_ndim = 1;
            const int x_dims = { 10 };
            const int y_ndim = 1;
            const int y_dims = { 10 };

            y[threadIdx.x] = x[threadIdx.x];
        }
=cut

has 'handle'              => (is => 'rw', isa => 'RtcHandle', init_arg => undef);
has [qw/name kernel/]     => (is => 'ro', isa => 'Str', required => 1);
has [qw/inputs outputs/]  => (is => 'ro', isa => 'HashRef[AI::MXNet::NDArray]', required => 1);

sub BUILD
{
    my $self = shift;
    my (@input_names, @output_names, @input_nds, @output_nds);
    while(my ($name, $arr) = each %{ $self->inputs })
    {
        push @input_names, $name;

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN


    Returns
    -------
    value : str
        The name of this symbol, returns None for grouped symbol.
=cut

method name()
{
    my ($name, $success) = check_call(AI::MXNetCAPI::SymbolGetName($self->handle));
    return $success ? $name : undef;
}

=head2 attr

    Get an attribute string from the symbol, this function only works for non-grouped symbol.

    Parameters
    ----------
    key : str
        The key to get attribute from.

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN

    value : str
        The attribute value of the key, returns None if attribute do not exist.
=cut


method attr(Str $key)
{
    my ($attr, $success) = check_call(
        AI::MXNetCAPI::SymbolGetAttr($self->handle, $key)
    );
    return $success ? $attr : undef;
}

=head2 list_attr

    Get all attributes from the symbol.

    Returns
    -------
    ret : hash ref of str to str
        a dicitonary mapping attribute keys to values

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN

    return __PACKAGE__->new(handle => $handle);
}

=head2 get_children

    Get a new grouped symbol whose output contains
    inputs to output nodes of the original symbol

    Returns
    -------
    sgroup : Symbol or undef
        The children of the head node. If the symbol has no
        inputs undef will be returned.
=cut


method get_children()
{
    my $handle = check_call(AI::MXNetCAPI::SymbolGetChildren($self->handle));
    my $ret = __PACKAGE__->new(handle => $handle);
    return undef unless @{ $ret->list_outputs };
    return $ret;
}

=head2 list_arguments

    List all the arguments in the symbol.

    Returns
    -------
    args : array ref of strings

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN

        ----------
        args : Array
            Provide type of arguments in a positional way.
            Unknown type can be marked as None

        kwargs : Hash ref, must ne ssupplied as as sole argument to the method.
            Provide keyword arguments of known types.

        Returns
        -------
        arg_types : array ref of Dtype or undef
            List of types of arguments.
            The order is in the same order as list_arguments()
        out_types : array ref of Dtype or undef
            List of types of outputs.
            The order is in the same order as list_outputs()
        aux_types : array ref of Dtype or undef
            List of types of outputs.
            The order is in the same order as list_auxiliary()
=cut


method infer_type(Str|Undef @args)
{
    my ($positional_arguments, $kwargs, $kwargs_order) = _parse_arguments("Dtype", @args); 
    my $sdata = [];
    my $keys  = [];

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN

    if($complete)
    {
        return (
            [ map { DTYPE_MX_TO_STR->{ $_ } } @{ $arg_type }],
            [ map { DTYPE_MX_TO_STR->{ $_ } } @{ $out_type }],
            [ map { DTYPE_MX_TO_STR->{ $_ } } @{ $aux_type }]
        );
    }
    else
    {
        return (undef, undef, undef);
    }
}

=head2 infer_shape

        Infer the shape of outputs and arguments of given known shapes of arguments.

        User can either pass in the known shapes in positional way or keyword argument way.
        Tuple of Nones is returned if there is not enough information passed in.
        An error will be raised if there is inconsistency found in the known shapes passed in.

        Parameters
        ----------
        *args :
            Provide shape of arguments in a positional way.
            Unknown shape can be marked as undef

        **kwargs :
            Provide keyword arguments of known shapes.

        Returns
        -------
        arg_shapes : array ref of Shape or undef
            List of shapes of arguments.
            The order is in the same order as list_arguments()
        out_shapes : array ref of Shape or undef
            List of shapes of outputs.
            The order is in the same order as list_outputs()
        aux_shapes : array ref of Shape or undef
            List of shapes of outputs.
            The order is in the same order as list_auxiliary()
=cut

method infer_shape(Maybe[Str|Shape] @args)
{
    my @res = $self->_infer_shape_impl(0, @args);
    if(not defined $res[1])
    {
        my ($arg_shapes) = $self->_infer_shape_impl(1, @args);

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN

            $indptr,
            $sdata,
        )
    );
    if($complete)
    {
        return $arg_shapes, $out_shapes, $aux_shapes;
    }
    else
    {
        return (undef, undef, undef);
    }
}

=head2 debug_str

    The debug string.

    Returns
    -------
    debug_str : string

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN

    my ($arg_handles, $arg_arrays) = ([], []);
    if(ref $args eq 'ARRAY')
    {
        confess("Length of $arg_key do not match number of arguments") 
            unless @$args == @$arg_names;
        @{ $arg_handles } = map { $_->handle } @{ $args };
        $arg_arrays = $args;
    }
    else
    {
        my %tmp = ((map { $_ => undef } @$arg_names), %$args);
        if(not $allow_missing and grep { not defined } values %tmp)
        {
            my ($missing) = grep { not defined $tmp{ $_ } } (keys %tmp);
            confess("key $missing is missing in $arg_key");
        }
        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.

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN

        @shared_arg_name_list = @{ $shared_arg_names };
    }
    my %shared_data;
    if(defined $shared_buffer)
    {
        while(my ($k, $v) = each %{ $shared_buffer })
        {
            $shared_data{$k} = $v->handle;
        }
    }
    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)
            =

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN

                \@provided_grad_req_types,
                scalar(@provided_arg_shape_names),
                \@provided_arg_shape_names,
                \@provided_arg_shape_data,
                \@provided_arg_shape_idx,
                $num_provided_arg_types,
                \@provided_arg_type_names,
                \@provided_arg_type_data,
                scalar(@shared_arg_name_list),
                \@shared_arg_name_list,
                defined $shared_buffer ? \%shared_data : undef,
                $shared_exec_handle
            )
        );
    };
    if($@)
    {
        confess(
            "simple_bind failed: Error: $@; Arguments: ".
            Data::Dumper->new(
                [$shapes//{}]

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN

        );
    }
    if(defined $shared_buffer)
    {
        while(my ($k, $v) = each %{ $updated_shared_data })
        {
            $shared_buffer->{$k} = AI::MXNet::NDArray->new(handle => $v);
        }
    }
    my @arg_arrays  = map { AI::MXNet::NDArray->new(handle => $_) } @{ $in_arg_handles };
    my @grad_arrays = map { defined $_ ? AI::MXNet::NDArray->new(handle => $_) : undef  } @{ $arg_grad_handles };
    my @aux_arrays  = map { AI::MXNet::NDArray->new(handle => $_) } @{ $aux_state_handles };
    my $executor = AI::MXNet::Executor->new(
        handle    => $exe_handle,
        symbol    => $self,
        ctx       => $ctx,
        grad_req  => $grad_req,
        group2ctx => $group2ctx
    );
    $executor->arg_arrays(\@arg_arrays);
    $executor->grad_arrays(\@grad_arrays);

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN

        Maybe[HashRef[AI::MXNet::Context]]                              :$group2ctx=,
        Maybe[AI::MXNet::Executor]                                      :$shared_exec=
)
{
    $grad_req //= 'write';
    my $listed_arguments = $self->list_arguments();
    my ($args_handle, $args_grad_handle, $aux_args_handle) = ([], [], []);
    ($args_handle, $args) = $self->_get_ndarray_inputs('args', $args, $listed_arguments);
    if(not defined $args_grad)
    {
        @$args_grad_handle = ((undef) x (@$args));
    }
    else
    {
        ($args_grad_handle, $args_grad) = $self->_get_ndarray_inputs(
                'args_grad', $args_grad, $listed_arguments, 1
        );
    }

    if(not defined $aux_states)
    {

lib/AI/MXNet/Symbol.pm  view on Meta::CPAN


sub _parse_arguments
{
    my $type = shift;
    my @args = @_;
    my $type_c = find_type_constraint($type);
    my $str_c  = find_type_constraint("Str");
    my @positional_arguments;
    my %kwargs;
    my @kwargs_order;
    my $only_dtypes_and_undefs = (@args == grep { not defined($_) or $type_c->check($_) } @args);
    my $only_dtypes_and_strs   = (@args == grep { $type_c->check($_) or $str_c->check($_) } @args);
    if(@args % 2 and $only_dtypes_and_undefs)
    {
        @positional_arguments = @args;
    }
    else
    {
        if($only_dtypes_and_undefs)
        {
            @positional_arguments = @args;
        }
        elsif($only_dtypes_and_strs)
        {
            my %tmp = @args;
            if(values(%tmp) == grep { $type_c->check($_) } values(%tmp))
            {
                %kwargs = %tmp;
                my $i = 0;

lib/AI/MXNet/Symbol/NameManager.pm  view on Meta::CPAN


    This is default implementation.
    When user specified a name,
    the user specified name will be used.

    When user did not, we will automatically generate a
    name based on hint string.

    Parameters
    ----------
    name : str or undef
        The name the user has specified.

    hint : str
        A hint string, which can be used to generate name.

    Returns
    -------
    full_name : str
        A canonical name for the symbol.
=cut

lib/AI/MXNet/Visualization.pm  view on Meta::CPAN

    Int                      $line_length=120,
    ArrayRef[Num]            $positions=[.44, .64, .74, 1]
)
{
    my $show_shape;
    my %shape_dict;
    if(defined $shape)
    {
        $show_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;
        @shape_dict{ @{ $interals->list_outputs } } = @{ $out_shapes };
    }
    my $conf = decode_json($symbol->tojson);
    my $nodes = $conf->{nodes};
    my %heads = map { $_ => 1 } @{ $conf->{heads}[0] };
    if($positions->[-1] <= 1)
    {
        $positions = [map { int($line_length * $_) } @{ $positions }];

lib/AI/MXNet/Visualization.pm  view on Meta::CPAN

)
{
    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;
        @shape_dict{ @{ $interals->list_outputs } } = @{ $out_shapes };
    }
    my $conf = decode_json($symbol->tojson);
    my $nodes = $conf->{nodes};
    my %node_attr = (
        qw/ shape box fixedsize true
            width 1.3 height 0.8034 style filled/,
        %{ $node_attrs }

t/test_module.t  view on Meta::CPAN



sub test_module_states
{
    my $stack = mx->rnn->SequentialRNNCell();
    for my $i (0..1)
    {
        $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=>[]);

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();
    my %args2 = %{ ($mod->get_params())[0] };
    for my $k (keys %args2)
    {
        $args2{$k} = $args2{$k}->aspdl;
    }
    is_deeply($mod->_p->_optimizer->lr_mult, { fc1_bias => 1, fc1_weight => 0 }, "lr_mult");
    is_deeply($mod->_p->_optimizer->wd_mult, { fc2_bias => 0.5, fc2_weight => 0.5, fc1_bias => 0, }, "wd_mult");
    ok(almost_equal($args1{fc1_weight}, $args2{fc1_weight}, 1e-10), "fc1_weight");

t/test_recordio.t  view on Meta::CPAN

sub test_recordio
{
    my ($fd, $frec) = tempfile();
    my $N = 255;

    my $writer = mx->recordio->MXRecordIO($frec, 'w');
    for my $i (0..$N-1)
    {
        $writer->write(chr($i));
    }
    undef $writer;

    my $reader = mx->recordio->MXRecordIO($frec, 'r');
    for my $i (0..$N-1)
    {
        my $res = $reader->read;
        is($res, chr($i));
    }
}

sub test_indexed_recordio
{
    my ($fi, $fidx) = tempfile();
    my ($fr, $frec) = tempfile();
    my $N = 255;

    my $writer = mx->recordio->MXIndexedRecordIO($fidx, $frec, 'w');
    for my $i (0..$N-1)
    {
        $writer->write_idx($i, chr($i));
    }
    undef $writer;

    my $reader = mx->recordio->MXIndexedRecordIO($fidx, $frec, 'r');
    my @keys = @{ $reader->keys };
    is_deeply([sort {$a <=> $b} @keys], [0..$N-1]);
    @keys = List::Util::shuffle(@keys);
    for my $i (@keys)
    {
        my $res = $reader->read_idx($i);
        is($res, chr($i));
    }

t/test_rnn.t  view on Meta::CPAN

use PDL;
use Test::More tests => 54;

sub test_rnn
{
    my $cell = mx->rnn->RNNCell(100, prefix=>'rnn_');
    my ($outputs) = $cell->unroll(3, input_prefix=>'rnn_');
    $outputs = mx->sym->Group($outputs);
    is_deeply([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_output', 'rnn_t1_out_output', 'rnn_t2_out_output']);
    my (undef, $outs, undef) = $outputs->infer_shape(rnn_t0_data=>[10,50], rnn_t1_data=>[10,50], rnn_t2_data=>[10,50]);
    is_deeply($outs, [[10, 100], [10, 100], [10, 100]]);
}

sub test_lstm
{
    my $cell = mx->rnn->LSTMCell(100, prefix=>'rnn_', forget_bias => 1);
    my($outputs) = $cell->unroll(3, input_prefix=>'rnn_');
    $outputs = mx->sym->Group($outputs);
    is_deeply([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_output', 'rnn_t1_out_output', 'rnn_t2_out_output']);
    my (undef, $outs, undef) = $outputs->infer_shape(rnn_t0_data=>[10,50], rnn_t1_data=>[10,50], rnn_t2_data=>[10,50]);
    is_deeply($outs, [[10, 100], [10, 100], [10, 100]]);
}

sub test_lstm_forget_bias
{
    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_'));

t/test_rnn.t  view on Meta::CPAN

    );
}

sub test_gru
{
    my $cell = mx->rnn->GRUCell(100, prefix=>'rnn_');
    my($outputs) = $cell->unroll(3, input_prefix=>'rnn_');
    $outputs = mx->sym->Group($outputs);
    is_deeply([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_output', 'rnn_t1_out_output', 'rnn_t2_out_output']);
    my (undef, $outs, undef) = $outputs->infer_shape(rnn_t0_data=>[10,50], rnn_t1_data=>[10,50], rnn_t2_data=>[10,50]);
    is_deeply($outs, [[10, 100], [10, 100], [10, 100]]);
}

sub test_residual
{
    my $cell = mx->rnn->ResidualCell(mx->rnn->GRUCell(50, prefix=>'rnn_'));
    my $inputs = [map { mx->sym->Variable("rnn_t${_}_data") } 0..1];
    my ($outputs)= $cell->unroll(2, inputs => $inputs);
    $outputs = mx->sym->Group($outputs);
    is_deeply(
        [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;

t/test_rnn.t  view on Meta::CPAN

    is_deeply(
        [sort keys %{ $cell->params->_params }],
        ['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]),

t/test_rnn.t  view on Meta::CPAN

    $outputs = mx->sym->Group($outputs);
    my %params = %{ $cell->params->_params };
    for my $i (0..4)
    {
        ok(exists $params{"rnn_stack${i}_h2h_weight"});
        ok(exists $params{"rnn_stack${i}_h2h_bias"});
        ok(exists $params{"rnn_stack${i}_i2h_weight"});
        ok(exists $params{"rnn_stack${i}_i2h_bias"});
    }
    is_deeply($outputs->list_outputs(), ['rnn_stack4_t0_out_output', 'rnn_stack4_t1_out_output', 'rnn_stack4_t2_out_output']);
    my (undef, $outs, undef) = $outputs->infer_shape(rnn_t0_data=>[10,50], rnn_t1_data=>[10,50], rnn_t2_data=>[10,50]);
    is_deeply($outs, [[10, 100], [10, 100], [10, 100]]);
}

sub test_bidirectional
{
    my $cell = mx->rnn->BidirectionalCell(
        mx->rnn->LSTMCell(100, prefix=>'rnn_l0_'),
        mx->rnn->LSTMCell(100, prefix=>'rnn_r0_'),
        output_prefix=>'rnn_bi_'
    );
    my ($outputs) = $cell->unroll(3, input_prefix=>'rnn_');
    $outputs = mx->sym->Group($outputs);
    is_deeply($outputs->list_outputs(), ['rnn_bi_t0_output', 'rnn_bi_t1_output', 'rnn_bi_t2_output']);
    my (undef, $outs, undef) = $outputs->infer_shape(rnn_t0_data=>[10,50], rnn_t1_data=>[10,50], rnn_t2_data=>[10,50]);
    is_deeply($outs, [[10, 200], [10, 200], [10, 200]]);
}

sub test_unfuse
{
    my $cell = mx->rnn->FusedRNNCell(
        100, num_layers => 1, mode => 'lstm',
        prefix => 'test_', bidirectional => 1
    )->unfuse;
    my ($outputs) = $cell->unroll(3, input_prefix=>'rnn_');
    $outputs = mx->sym->Group($outputs);
    is_deeply($outputs->list_outputs(), ['test_bi_lstm_0t0_output', 'test_bi_lstm_0t1_output', 'test_bi_lstm_0t2_output']);
    my (undef, $outs, undef) = $outputs->infer_shape(rnn_t0_data=>[10,50], rnn_t1_data=>[10,50], rnn_t2_data=>[10,50]);
    is_deeply($outs, [[10, 200], [10, 200], [10, 200]]);
}

sub test_zoneout
{
    my $cell = mx->rnn->ZoneoutCell(
        mx->rnn->RNNCell(100, prefix=>'rnn_'),
        zoneout_outputs => 0.5,
        zoneout_states  => 0.5
    );
    my $inputs = [map { mx->sym->Variable("rnn_t${_}_data") } 0..2];
    my ($outputs) = $cell->unroll(3, inputs => $inputs);
    $outputs = mx->sym->Group($outputs);
    my (undef, $outs) = $outputs->infer_shape(rnn_t0_data=>[10, 50], rnn_t1_data=>[10, 50], rnn_t2_data=>[10, 50]);
    is_deeply($outs, [[10, 100], [10, 100], [10, 100]]);
}

sub test_convrnn
{
    my $cell = mx->rnn->ConvRNNCell(input_shape => [1, 3, 16, 10], num_hidden=>10,
                              h2h_kernel=>[3, 3], h2h_dilate=>[1, 1],
                              i2h_kernel=>[3, 3], i2h_stride=>[1, 1],
                              i2h_pad=>[1, 1], i2h_dilate=>[1, 1],
                              prefix=>'rnn_');
    my $inputs = [map { mx->sym->Variable("rnn_t${_}_data") } 0..2];
    my ($outputs) = $cell->unroll(3, inputs => $inputs);
    $outputs = mx->sym->Group($outputs);
    is_deeply(
        [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_output', 'rnn_t1_out_output', 'rnn_t2_out_output']);
    my (undef, $outs) = $outputs->infer_shape(rnn_t0_data=>[1, 3, 16, 10], rnn_t1_data=>[1, 3, 16, 10], rnn_t2_data=>[1, 3, 16, 10]);
    is_deeply($outs, [[1, 10, 16, 10], [1, 10, 16, 10], [1, 10, 16, 10]]);
}

sub test_convlstm
{
    my $cell = mx->rnn->ConvLSTMCell(input_shape => [1, 3, 16, 10], num_hidden=>10,
                              h2h_kernel=>[3, 3], h2h_dilate=>[1, 1],
                              i2h_kernel=>[3, 3], i2h_stride=>[1, 1],
                              i2h_pad=>[1, 1], i2h_dilate=>[1, 1],
                              prefix=>'rnn_', forget_bias => 1);
    my $inputs = [map { mx->sym->Variable("rnn_t${_}_data") } 0..2];
    my ($outputs) = $cell->unroll(3, inputs => $inputs);
    $outputs = mx->sym->Group($outputs);
    is_deeply(
        [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_output', 'rnn_t1_out_output', 'rnn_t2_out_output']);
    my (undef, $outs) = $outputs->infer_shape(rnn_t0_data=>[1, 3, 16, 10], rnn_t1_data=>[1, 3, 16, 10], rnn_t2_data=>[1, 3, 16, 10]);
    is_deeply($outs, [[1, 10, 16, 10], [1, 10, 16, 10], [1, 10, 16, 10]]);
}

sub test_convgru
{
    my $cell = mx->rnn->ConvGRUCell(input_shape => [1, 3, 16, 10], num_hidden=>10,
                              h2h_kernel=>[3, 3], h2h_dilate=>[1, 1],
                              i2h_kernel=>[3, 3], i2h_stride=>[1, 1],
                              i2h_pad=>[1, 1], i2h_dilate=>[1, 1],
                              prefix=>'rnn_', forget_bias => 1);
    my $inputs = [map { mx->sym->Variable("rnn_t${_}_data") } 0..2];
    my ($outputs) = $cell->unroll(3, inputs => $inputs);
    $outputs = mx->sym->Group($outputs);
    is_deeply(
        [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_output', 'rnn_t1_out_output', 'rnn_t2_out_output']);
    my (undef, $outs) = $outputs->infer_shape(rnn_t0_data=>[1, 3, 16, 10], rnn_t1_data=>[1, 3, 16, 10], rnn_t2_data=>[1, 3, 16, 10]);
    is_deeply($outs, [[1, 10, 16, 10], [1, 10, 16, 10], [1, 10, 16, 10]]);
}

test_rnn();
test_lstm();
test_lstm_forget_bias();
test_gru();
test_residual();
test_residual_bidirectional();
test_stack();

t/test_symbol.t  view on Meta::CPAN


    my $data = mx->symbol->Variable('data');
    my $prev = mx->symbol->Variable('prevstate');
    my $x2h  = mx->symbol->FullyConnected(data=>$data, name=>'x2h', num_hidden=>$num_hidden);
    my $h2h  = mx->symbol->FullyConnected(data=>$prev, name=>'h2h', num_hidden=>$num_hidden);

    my $out  = mx->symbol->Activation(data=>mx->sym->elemwise_add($x2h, $h2h), name=>'out', act_type=>'relu');

    # shape inference will fail because information is not available for h2h
    my @ret  = $out->infer_shape(data=>[$num_sample, $num_dim]);
    is_deeply(\@ret, [undef, undef, undef]);

    my ($arg_shapes, $out_shapes, $aux_shapes) = $out->infer_shape_partial(data=>[$num_sample, $num_dim]);
    my %arg_shapes;
    @arg_shapes{ @{ $out->list_arguments } } = @{ $arg_shapes };
    is_deeply($arg_shapes{data}, [$num_sample, $num_dim]);
    is_deeply($arg_shapes{x2h_weight}, [$num_hidden, $num_dim]);
    is_deeply($arg_shapes{h2h_weight}, []);

    # now we can do full shape inference
    my $state_shape = $out_shapes->[0];

t/test_symbol.t  view on Meta::CPAN

    }
    my ($fc2, $act2, $fc3, $sym1);
    {
        local($mx::AttrScope) = mx->AttrScope(ctx_group=>'stage2');
        $fc2  = mx->symbol->FullyConnected(data => $act1, name => 'fc2', num_hidden => 64, lr_mult=>0.01);
        $act2 = mx->symbol->Activation(data => $fc2, name=>'relu2', act_type=>"relu");
        $fc3  = mx->symbol->FullyConnected(data => $act2, name=>'fc3', num_hidden=>10);
        $fc3  = mx->symbol->BatchNorm($fc3, name=>'batchnorm0');
        $sym1 = mx->symbol->SoftmaxOutput(data => $fc3, name => 'softmax')
    }
    { local $/ = undef; my $json = <DATA>; open(F, ">save_000800.json"); print F $json; close(F); };
    my $sym2 = mx->sym->load('save_000800.json');
    unlink 'save_000800.json';

    my %attr1 = %{ $sym1->attr_dict };
    my %attr2 = %{ $sym2->attr_dict };
    while(my ($k, $v1) = each %attr1)
    {
        ok(exists $attr2{ $k });
        my $v2 = $attr2{$k};
        while(my ($kk, $vv1) = each %{ $v1 })



( run in 4.523 seconds using v1.01-cache-2.11-cpan-d80b1682f3f )