You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by jx...@apache.org on 2017/08/09 20:20:07 UTC
[incubator-mxnet] branch master updated: 1) Fixes for ImageIter
(#7357)
This is an automated email from the ASF dual-hosted git repository.
jxie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git
The following commit(s) were added to refs/heads/master by this push:
new f674bc4 1) Fixes for ImageIter (#7357)
f674bc4 is described below
commit f674bc40dbdb834919a37bd12af3003d7a427307
Author: Sergey Kolychev <se...@gmail.com>
AuthorDate: Wed Aug 9 13:20:04 2017 -0700
1) Fixes for ImageIter (#7357)
2) Convolutional RNN
3) Improved Visualization
4) PearsonCorrelation metric
5) Fixed tests.
---
perl-package/AI-MXNet/Changes | 3 +
perl-package/AI-MXNet/MANIFEST | 1 -
perl-package/AI-MXNet/META.json | 4 +-
perl-package/AI-MXNet/META.yml | 4 +-
perl-package/AI-MXNet/Makefile.PL | 4 +-
perl-package/AI-MXNet/README | 2 +-
perl-package/AI-MXNet/lib/AI/MXNet.pm | 2 +-
perl-package/AI-MXNet/lib/AI/MXNet/Base.pm | 2 +-
perl-package/AI-MXNet/lib/AI/MXNet/Image.pm | 8 +-
perl-package/AI-MXNet/lib/AI/MXNet/Metric.pm | 50 ++++
perl-package/AI-MXNet/lib/AI/MXNet/Module.pm | 8 -
perl-package/AI-MXNet/lib/AI/MXNet/RNN.pm | 3 +
perl-package/AI-MXNet/lib/AI/MXNet/RNN/Cell.pm | 307 ++++++++++++++++++++-
perl-package/AI-MXNet/lib/AI/MXNet/Symbol.pm | 2 +-
perl-package/AI-MXNet/lib/AI/MXNet/Types.pm | 4 +-
.../AI-MXNet/lib/AI/MXNet/Visualization.pm | 8 +
perl-package/AI-MXNet/t/test_model_parallel.t | 74 +++++
perl-package/AI-MXNet/t/test_rnn.t | 62 ++++-
perl-package/AI-MXNetCAPI/Changes | 3 +
perl-package/AI-MXNetCAPI/META.json | 2 +-
perl-package/AI-MXNetCAPI/META.yml | 2 +-
perl-package/AI-MXNetCAPI/README | 2 +-
perl-package/AI-MXNetCAPI/lib/AI/MXNetCAPI.pm | 2 +-
perl-package/AI-MXNetCAPI/mxnet.i | 7 +
24 files changed, 537 insertions(+), 29 deletions(-)
diff --git a/perl-package/AI-MXNet/Changes b/perl-package/AI-MXNet/Changes
index 5d5c5a2..f8ecc75 100644
--- a/perl-package/AI-MXNet/Changes
+++ b/perl-package/AI-MXNet/Changes
@@ -1,5 +1,8 @@
Revision history for Perl extension AI::MXNet
+1.0102 Sun Aug 6 16:55:08 PDT 2017
+ - bugfixes in Image.pm, updated tests, added PearsonCorrelation metric, added Convolutional RNN modules.
+
1.0101 Sun Jul 2 17:16:01 PDT 2017
- reworked CachedOp, two new optimizers, auto module reshape, using strings to index the kvstore.
diff --git a/perl-package/AI-MXNet/MANIFEST b/perl-package/AI-MXNet/MANIFEST
index 7a6d78b..48cb31d 100644
--- a/perl-package/AI-MXNet/MANIFEST
+++ b/perl-package/AI-MXNet/MANIFEST
@@ -10,7 +10,6 @@ examples/cudnn_lstm_bucketing.pl
Makefile.PL
Changes
META.json
-t/test_autograd.t
t/test_recordio.t
t/test_random.t
t/test_init.t
diff --git a/perl-package/AI-MXNet/META.json b/perl-package/AI-MXNet/META.json
index 5454592..692f1dd 100644
--- a/perl-package/AI-MXNet/META.json
+++ b/perl-package/AI-MXNet/META.json
@@ -30,7 +30,7 @@
},
"runtime" : {
"requires" : {
- "AI::MXNetCAPI" : "1.0101",
+ "AI::MXNetCAPI" : "1.0102",
"AI::NNVMCAPI" : "1.01",
"Function::Parameters" : "1.0705",
"GraphViz" : "2.14",
@@ -43,5 +43,5 @@
}
},
"release_status" : "stable",
- "version" : "1.0101"
+ "version" : "1.0102"
}
diff --git a/perl-package/AI-MXNet/META.yml b/perl-package/AI-MXNet/META.yml
index 8c09c96..5b92018 100644
--- a/perl-package/AI-MXNet/META.yml
+++ b/perl-package/AI-MXNet/META.yml
@@ -17,10 +17,10 @@ no_index:
- t
- inc
requires:
- AI::MXNetCAPI: '1.0101'
+ AI::MXNetCAPI: '1.0102'
AI::NNVMCAPI: '1.01'
Function::Parameters: '1.0705'
GraphViz: '2.14'
Mouse: v2.1.0
PDL: '2.007'
-version: '1.0101'
+version: '1.0102'
diff --git a/perl-package/AI-MXNet/Makefile.PL b/perl-package/AI-MXNet/Makefile.PL
index 990176d..2c9bda8 100644
--- a/perl-package/AI-MXNet/Makefile.PL
+++ b/perl-package/AI-MXNet/Makefile.PL
@@ -19,7 +19,7 @@ my %WriteMakefileArgs = (
"LICENSE" => "apache_2_0",
"NAME" => "AI::MXNet",
"PREREQ_PM" => {
- "AI::MXNetCAPI" => "1.0101",
+ "AI::MXNetCAPI" => "1.0102",
"AI::NNVMCAPI" => "1.01",
"Function::Parameters" => "1.0705",
"Mouse" => "v2.1.0",
@@ -35,7 +35,7 @@ my %WriteMakefileArgs = (
my %FallbackPrereqs = (
- "AI::MXNetCAPI" => "1.0101",
+ "AI::MXNetCAPI" => "1.0102",
"AI::NNVMCAPI" => "1.01",
"Function::Parameters" => "1.0705",
"Mouse" => "v2.1.0",
diff --git a/perl-package/AI-MXNet/README b/perl-package/AI-MXNet/README
index f275d08..86b6cf1 100644
--- a/perl-package/AI-MXNet/README
+++ b/perl-package/AI-MXNet/README
@@ -1,5 +1,5 @@
This archive contains the distribution AI-MXNet,
-version 1.0101:
+version 1.0102:
Perl interface to MXNet machine learning library
diff --git a/perl-package/AI-MXNet/lib/AI/MXNet.pm b/perl-package/AI-MXNet/lib/AI/MXNet.pm
index 1d21253..40e84a6 100644
--- a/perl-package/AI-MXNet/lib/AI/MXNet.pm
+++ b/perl-package/AI-MXNet/lib/AI/MXNet.pm
@@ -46,7 +46,7 @@ use AI::MXNet::Image;
use AI::MXNet::Contrib;
use AI::MXNet::Contrib::AutoGrad;
use AI::MXNet::CachedOp;
-our $VERSION = '1.0101';
+our $VERSION = '1.0102';
sub import
{
diff --git a/perl-package/AI-MXNet/lib/AI/MXNet/Base.pm b/perl-package/AI-MXNet/lib/AI/MXNet/Base.pm
index d5ff0dd..0c42fa9 100644
--- a/perl-package/AI-MXNet/lib/AI/MXNet/Base.pm
+++ b/perl-package/AI-MXNet/lib/AI/MXNet/Base.pm
@@ -20,7 +20,7 @@ use strict;
use warnings;
use PDL;
use PDL::Types qw();
-use AI::MXNetCAPI 1.0101;
+use AI::MXNetCAPI 1.0102;
use AI::NNVMCAPI 1.01;
use AI::MXNet::Types;
use Time::HiRes;
diff --git a/perl-package/AI-MXNet/lib/AI/MXNet/Image.pm b/perl-package/AI-MXNet/lib/AI/MXNet/Image.pm
index b996b02..18ef42a 100644
--- a/perl-package/AI-MXNet/lib/AI/MXNet/Image.pm
+++ b/perl-package/AI-MXNet/lib/AI/MXNet/Image.pm
@@ -764,7 +764,7 @@ sub BUILD
{
chomp($line);
my @line = split(/\t/, $line);
- my $label = AI::MXNet::NDArray->array([@line[1..@line-1]]);
+ my $label = AI::MXNet::NDArray->array([@line[1..@line-2]]);
my $key = $line[0];
$imglist{$key} = [$label, $line[-1]];
push @imgkeys, $key;
@@ -838,6 +838,10 @@ sub BUILD
{
$self->aug_list(AI::MXNet::Image->CreateAugmenter(data_shape => $self->data_shape, %{ $self->kwargs//{} }));
}
+ else
+ {
+ $self->aug_list([]);
+ }
$self->cur(0);
$self->reset();
}
@@ -877,7 +881,7 @@ method next_sample()
}
else
{
- my ($label, $fname) = $self->imglist->{$idx};
+ my ($label, $fname) = @{ $self->imglist->{$idx} };
if(not defined $self->imgrec)
{
open(F, $self->path_root . "/$fname") or confess("can't open $fname $!");
diff --git a/perl-package/AI-MXNet/lib/AI/MXNet/Metric.pm b/perl-package/AI-MXNet/lib/AI/MXNet/Metric.pm
index 6504481..c3a3183 100644
--- a/perl-package/AI-MXNet/lib/AI/MXNet/Metric.pm
+++ b/perl-package/AI-MXNet/lib/AI/MXNet/Metric.pm
@@ -510,6 +510,55 @@ method update(ArrayRef[AI::MXNet::NDArray] $labels, ArrayRef[AI::MXNet::NDArray]
}, $labels, $preds);
}
+package AI::MXNet::PearsonCorrelation;
+use Mouse;
+use AI::MXNet::Base;
+extends 'AI::MXNet::EvalMetric';
+has '+name' => (default => 'pearson-correlation');
+
+=head1 NAME
+
+ AI::MXNet::PearsonCorrelation
+=cut
+
+=head1 DESCRIPTION
+
+ Computes Pearson correlation.
+
+ Parameters
+ ----------
+ name : str
+ Name of this metric instance for display.
+
+ Examples
+ --------
+ >>> $predicts = [mx->nd->array([[0.3, 0.7], [0, 1.], [0.4, 0.6]])]
+ >>> $labels = [mx->nd->array([[1, 0], [0, 1], [0, 1]])]
+ >>> $pr = mx->metric->PearsonCorrelation()
+ >>> $pr->update($labels, $predicts)
+ >>> print pr->get()
+ ('pearson-correlation', '0.421637061887229')
+=cut
+
+method update(ArrayRef[AI::MXNet::NDArray] $labels, ArrayRef[AI::MXNet::NDArray] $preds)
+{
+ AI::MXNet::Metric::check_label_shapes($labels, $preds);
+ zip(sub {
+ my ($label, $pred) = @_;
+ AI::MXNet::Metric::check_label_shapes($label, $pred);
+ $label = $label->aspdl->flat;
+ $pred = $pred->aspdl->flat;
+ my ($label_mean, $label_stdv) = ($label->stats)[0, 6];
+ my ($pred_mean, $pred_stdv) = ($pred->stats)[0, 6];
+ $self->sum_metric(
+ $self->sum_metric
+ +
+ ((($label-$label_mean)*($pred-$pred_mean))->sum/$label->nelem)/(($label_stdv*$pred_stdv)->at(0))
+ );
+ $self->num_inst($self->num_inst + 1);
+ }, $labels, $preds);
+}
+
=head1 DESCRIPTION
Custom evaluation metric that takes a sub ref.
@@ -574,6 +623,7 @@ my %metrics = qw/
top_k_accuracy AI::MXNet::TopKAccuracy
Perplexity AI::MXNet::Perplexity
perplexity AI::MXNet::Perplexity
+ pearsonr AI::MXNet::PearsonCorrelation
/;
method create(Metric|ArrayRef[Metric] $metric, %kwargs)
diff --git a/perl-package/AI-MXNet/lib/AI/MXNet/Module.pm b/perl-package/AI-MXNet/lib/AI/MXNet/Module.pm
index 967a511..3e4d938 100644
--- a/perl-package/AI-MXNet/lib/AI/MXNet/Module.pm
+++ b/perl-package/AI-MXNet/lib/AI/MXNet/Module.pm
@@ -796,14 +796,6 @@ method forward(
)
{
assert($self->binded and $self->params_initialized);
- # If starting to do the inference, force rebind the module.
- if($self->label_shapes and not $data_batch->label)
- {
- confess(
- "If you are trying to do inference, rebind module ".
- "with 'force_rebind=True' and 'for_training=False'"
- );
- }
my @curr_data_shapes = map { $_->shape } @{ $self->data_shapes };
my @new_data_shapes = map { $_->shape } @{ $data_batch->data };
diff --git a/perl-package/AI-MXNet/lib/AI/MXNet/RNN.pm b/perl-package/AI-MXNet/lib/AI/MXNet/RNN.pm
index 1ccab31..07e72a7 100644
--- a/perl-package/AI-MXNet/lib/AI/MXNet/RNN.pm
+++ b/perl-package/AI-MXNet/lib/AI/MXNet/RNN.pm
@@ -166,6 +166,9 @@ method SequentialRNNCell(@args) { AI::MXNet::RNN::SequentialCell->new(@args) }
method BidirectionalCell(@args) { AI::MXNet::RNN::BidirectionalCell->new(@args) }
method DropoutCell(@args) { AI::MXNet::RNN::DropoutCell->new(@args) }
method ZoneoutCell(@args) { AI::MXNet::RNN::ZoneoutCell->new(@args) }
+method ConvRNNCell(@args) { AI::MXNet::RNN::ConvCell->new(@args) }
+method ConvLSTMCell(@args) { AI::MXNet::RNN::ConvLSTMCell->new(@args) }
+method ConvGRUCell(@args) { AI::MXNet::RNN::ConvGRUCell->new(@args) }
method ResidualCell(@args) { AI::MXNet::RNN::ResidualCell->new(@args) }
method encode_sentences(@args) { AI::MXNet::RNN::IO->encode_sentences(@args) }
method BucketSentenceIter(@args)
diff --git a/perl-package/AI-MXNet/lib/AI/MXNet/RNN/Cell.pm b/perl-package/AI-MXNet/lib/AI/MXNet/RNN/Cell.pm
index 0221a90..08c3094 100644
--- a/perl-package/AI-MXNet/lib/AI/MXNet/RNN/Cell.pm
+++ b/perl-package/AI-MXNet/lib/AI/MXNet/RNN/Cell.pm
@@ -766,7 +766,7 @@ has '_dropout' => (is => 'ro', isa => 'Num', init_arg => 'dropout',
has '_get_next_state' => (is => 'ro', isa => 'Bool', init_arg => 'get_next_state', default => 0);
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[AI::MXNet::Initializer]');
+has 'initializer' => (is => 'rw', isa => 'Maybe[Initializer]');
has '_mode' => (
is => 'ro',
isa => enum([qw/rnn_relu rnn_tanh lstm gru/]),
@@ -1429,6 +1429,309 @@ method unroll(
return($outputs, $states);
}
+package AI::MXNet::RNN::ConvCell::Base;
+use Mouse;
+use AI::MXNet::Base;
+extends 'AI::MXNet::RNN::Cell::Base';
+
+=head1 NAME
+
+ AI::MXNet::RNN::Conv::Base
+=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 ]})"
+ );
+ $self->_h2h_pad([
+ int($self->_h2h_dilate->[0] * ($self->_h2h_kernel->[0] - 1) / 2),
+ int($self->_h2h_dilate->[1] * ($self->_h2h_kernel->[1] - 1) / 2)
+ ]);
+ # Infer state shape
+ my $data = AI::MXNet::Symbol->Variable('data');
+ my $state_shape = AI::MXNet::Symbol->Convolution(
+ data => $data,
+ num_filter => $self->_num_hidden,
+ kernel => $self->_i2h_kernel,
+ stride => $self->_i2h_stride,
+ pad => $self->_i2h_pad,
+ dilate => $self->_i2h_dilate,
+ layout => $self->_conv_layout
+ );
+ $state_shape = ($state_shape->infer_shape(data=>$self->_input_shape))[1]->[0];
+ $state_shape->[0] = 0;
+ $self->_state_shape($state_shape);
+}
+
+method state_info()
+{
+ return [
+ { shape => $self->_state_shape, __layout__ => $self->_conv_layout },
+ { shape => $self->_state_shape, __layout__ => $self->_conv_layout }
+ ];
+}
+
+method call($inputs, $states)
+{
+ confess("AI::MXNet::RNN::ConvCell::Base is abstract class for convolutional RNN");
+}
+
+package AI::MXNet::RNN::ConvCell;
+use Mouse;
+extends 'AI::MXNet::RNN::ConvCell::Base';
+
+=head1 NAME
+
+ AI::MXNet::RNN::ConvCell
+=cut
+
+=head1 DESCRIPTION
+
+ Convolutional RNN cells
+
+ Parameters
+ ----------
+ input_shape : array ref of int
+ Shape of input in single timestep.
+ num_hidden : int
+ Number of units in output symbol.
+ h2h_kernel : array ref of int, default (3, 3)
+ Kernel of Convolution operator in state-to-state transitions.
+ h2h_dilate : array ref of int, default (1, 1)
+ Dilation of Convolution operator in state-to-state transitions.
+ i2h_kernel : array ref of int, default (3, 3)
+ Kernel of Convolution operator in input-to-state transitions.
+ i2h_stride : array ref of int, default (1, 1)
+ Stride of Convolution operator in input-to-state transitions.
+ i2h_pad : array ref of int, default (1, 1)
+ Pad of Convolution operator in input-to-state transitions.
+ i2h_dilate : array ref of int, default (1, 1)
+ Dilation of Convolution operator in input-to-state transitions.
+ activation : str or Symbol,
+ default functools.partial(symbol.LeakyReLU, act_type='leaky', slope=0.2)
+ Type of activation function.
+ prefix : str, default 'ConvRNN_'
+ Prefix for name of layers (and name of weight if params is None).
+ params : RNNParams, default None
+ Container for weight sharing between cells. Created if None.
+ conv_layout : str, , default 'NCHW'
+ Layout of ConvolutionOp
+=cut
+
+has '+_h2h_kernel' => (default => sub { [3, 3] });
+has '+_h2h_dilate' => (default => sub { [1, 1] });
+has '+_i2h_kernel' => (default => sub { [3, 3] });
+has '+_i2h_stride' => (default => sub { [1, 1] });
+has '+_i2h_dilate' => (default => sub { [1, 1] });
+has '+_i2h_pad' => (default => sub { [1, 1] });
+has '+_prefix' => (default => 'ConvRNN_');
+has '+_activation' => (default => sub { sub { AI::MXNet::Symbol->LeakyReLU(@_, act_type => 'leaky', slope => 0.2) } });
+has '+i2h_bias_initializer' => (default => 'zeros');
+has '+h2h_bias_initializer' => (default => 'zeros');
+has 'forget_bias' => (is => 'ro', isa => 'Num');
+has [qw/_iW _iB
+ _hW _hB/] => (is => 'rw', init_arg => undef);
+
+
+sub BUILD
+{
+ my $self = shift;
+ $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',
+ (defined($self->forget_bias and not defined $self->i2h_bias_initializer)
+ ? (init => AI::MXNet::LSTMBias->new(forget_bias => $self->forget_bias))
+ : (init => $self->i2h_bias_initializer)
+ )
+ )
+ );
+ $self->_hB($self->_params->get('h2h_bias', init => $self->h2h_bias_initializer));
+}
+
+method _num_gates()
+{
+ scalar(@{ $self->_gate_names() });
+}
+
+method _gate_names()
+{
+ return ['']
+}
+
+method _conv_forward($inputs, $states, $name)
+{
+ my $i2h = AI::MXNet::Symbol->Convolution(
+ name => "${name}i2h",
+ data => $inputs,
+ num_filter => $self->_num_hidden*$self->_num_gates(),
+ kernel => $self->_i2h_kernel,
+ stride => $self->_i2h_stride,
+ pad => $self->_i2h_pad,
+ dilate => $self->_i2h_dilate,
+ weight => $self->_iW,
+ bias => $self->_iB
+ );
+ my $h2h = AI::MXNet::Symbol->Convolution(
+ name => "${name}h2h",
+ data => @{ $states }[0],
+ num_filter => $self->_num_hidden*$self->_num_gates(),
+ kernel => $self->_h2h_kernel,
+ stride => [1, 1],
+ pad => $self->_h2h_pad,
+ dilate => $self->_h2h_dilate,
+ weight => $self->_hW,
+ bias => $self->_hB
+ );
+ return ($i2h, $h2h);
+}
+
+method call(AI::MXNet::Symbol $inputs, AI::MXNet::Symbol|ArrayRef[AI::MXNet::Symbol] $states)
+{
+ $self->_counter($self->_counter + 1);
+ my $name = sprintf('%st%d_', $self->_prefix, $self->_counter);
+ my ($i2h, $h2h) = $self->_conv_forward($inputs, $states, $name);
+ my $output = $self->_get_activation($i2h + $h2h, $self->_activation, name => "${name}out");
+ return ($output, [$output]);
+}
+
+package AI::MXNet::RNN::ConvLSTMCell;
+use Mouse;
+extends 'AI::MXNet::RNN::ConvCell';
+has '+forget_bias' => (default => 1);
+has '+_prefix' => (default => 'ConvLSTM_');
+
+=head1 NAME
+
+ AI::MXNet::RNN::ConvLSTMCell
+=cut
+
+=head1 DESCRIPTION
+
+ Convolutional LSTM network cell.
+
+ Reference:
+ Xingjian et al. NIPS2015
+=cut
+
+method _gate_names()
+{
+ return ['_i', '_f', '_c', '_o'];
+}
+
+method call(AI::MXNet::Symbol $inputs, AI::MXNet::Symbol|ArrayRef[AI::MXNet::Symbol] $states)
+{
+ $self->_counter($self->_counter + 1);
+ my $name = sprintf('%st%d_', $self->_prefix, $self->_counter);
+ my ($i2h, $h2h) = $self->_conv_forward($inputs, $states, $name);
+ my $gates = $i2h + $h2h;
+ my @slice_gates = @{ AI::MXNet::Symbol->SliceChannel(
+ $gates,
+ num_outputs => 4,
+ axis => index($self->_conv_layout, 'C'),
+ name => "${name}slice"
+ ) };
+ my $in_gate = AI::MXNet::Symbol->Activation(
+ $slice_gates[0],
+ act_type => "sigmoid",
+ name => "${name}i"
+ );
+ my $forget_gate = AI::MXNet::Symbol->Activation(
+ $slice_gates[1],
+ act_type => "sigmoid",
+ name => "${name}f"
+ );
+ my $in_transform = $self->_get_activation(
+ $slice_gates[2],
+ $self->_activation,
+ name => "${name}c"
+ );
+ my $out_gate = AI::MXNet::Symbol->Activation(
+ $slice_gates[3],
+ act_type => "sigmoid",
+ name => "${name}o"
+ );
+ my $next_c = AI::MXNet::Symbol->_plus(
+ $forget_gate * @{$states}[1],
+ $in_gate * $in_transform,
+ name => "${name}state"
+ );
+ my $next_h = AI::MXNet::Symbol->_mul(
+ $out_gate, $self->_get_activation($next_c, $self->_activation),
+ name => "${name}out"
+ );
+ return ($next_h, [$next_h, $next_c]);
+}
+
+package AI::MXNet::RNN::ConvGRUCell;
+use Mouse;
+extends 'AI::MXNet::RNN::ConvCell';
+has '+_prefix' => (default => 'ConvGRU_');
+
+=head1 NAME
+
+ AI::MXNet::RNN::ConvGRUCell
+=cut
+
+=head1 DESCRIPTION
+
+ Convolutional GRU network cell.
+=cut
+
+method _gate_names()
+{
+ return ['_r', '_z', '_o'];
+}
+
+method call(AI::MXNet::Symbol $inputs, AI::MXNet::Symbol|ArrayRef[AI::MXNet::Symbol] $states)
+{
+ $self->_counter($self->_counter + 1);
+ my $name = sprintf('%st%d_', $self->_prefix, $self->_counter);
+ my ($i2h, $h2h) = $self->_conv_forward($inputs, $states, $name);
+ my ($i2h_r, $i2h_z, $h2h_r, $h2h_z);
+ ($i2h_r, $i2h_z, $i2h) = @{ AI::MXNet::Symbol->SliceChannel($i2h, num_outputs => 3, name => "${name}_i2h_slice") };
+ ($h2h_r, $h2h_z, $h2h) = @{ AI::MXNet::Symbol->SliceChannel($h2h, num_outputs => 3, name => "${name}_h2h_slice") };
+ my $reset_gate = AI::MXNet::Symbol->Activation(
+ $i2h_r + $h2h_r, act_type => "sigmoid",
+ name => "${name}_r_act"
+ );
+ my $update_gate = AI::MXNet::Symbol->Activation(
+ $i2h_z + $h2h_z, act_type => "sigmoid",
+ name => "${name}_z_act"
+ );
+ my $next_h_tmp = $self->_get_activation($i2h + $reset_gate * $h2h, $self->_activation, name => "${name}_h_act");
+ my $next_h = AI::MXNet::Symbol->_plus(
+ (1 - $update_gate) * $next_h_tmp, $update_gate * @{$states}[0],
+ name => "${name}out"
+ );
+ return ($next_h, [$next_h]);
+}
+
package AI::MXNet::RNN::ModifierCell;
use Mouse;
use AI::MXNet::Base;
@@ -1593,7 +1896,7 @@ method call(AI::MXNet::Symbol $inputs, SymbolOrArrayOfSymbols $states)
p => $p
);
};
- my $prev_output = $self->prev_output || AI::MXNet::Symbol->zeros(shape => [0, 0]);
+ my $prev_output = $self->prev_output // AI::MXNet::Symbol->zeros(shape => [0, 0]);
my $output = $p_outputs != 0
? AI::MXNet::Symbol->where(
&{$mask}($p_outputs, $next_output),
diff --git a/perl-package/AI-MXNet/lib/AI/MXNet/Symbol.pm b/perl-package/AI-MXNet/lib/AI/MXNet/Symbol.pm
index a5298c7..eed6e93 100644
--- a/perl-package/AI-MXNet/lib/AI/MXNet/Symbol.pm
+++ b/perl-package/AI-MXNet/lib/AI/MXNet/Symbol.pm
@@ -1232,7 +1232,7 @@ method Variable(
Maybe[Num] :$lr_mult=,
Maybe[Num] :$wd_mult=,
Maybe[Dtype] :$dtype=,
- Maybe[AI::MXNet::Initializer] :$init=,
+ Maybe[Initializer] :$init=,
HashRef[Str] :$kwargs={},
Maybe[Str] :$__layout__=
)
diff --git a/perl-package/AI-MXNet/lib/AI/MXNet/Types.pm b/perl-package/AI-MXNet/lib/AI/MXNet/Types.pm
index e48ae3c..b4ec7e9 100644
--- a/perl-package/AI-MXNet/lib/AI/MXNet/Types.pm
+++ b/perl-package/AI-MXNet/lib/AI/MXNet/Types.pm
@@ -34,6 +34,7 @@ class_type 'AI::MXNet::Callback';
class_type 'AI::MXNet::EvalMetric';
class_type 'AI::MXNet::DataParallelExecutorGroup';
class_type 'AI::MXNet::Optimizer';
+class_type 'AI::MXNet::Initializer';
class_type 'AI::MXNet::InitDesc';
class_type 'AI::MXNet::IRHeader';
subtype "AcceptableInput" => as "Num|PDL|PDL::Matrix|AI::MXNet::NDArray|AI::MXNet::NDArray::Slice|ArrayRef";
@@ -55,6 +56,7 @@ subtype "NameShape" => as "ArrayRef" => where {
subtype "Callback" => as "CodeRef|ArrayRef[Coderef]|AI::MXNet::Callback|ArrayRef[AI::MXNet::Callback]";
subtype "EvalMetric" => as "AI::MXNet::EvalMetric|Str|CodeRef";
subtype "Optimizer" => as "AI::MXNet::Optimizer|Str";
-subtype "Activation" => as "AI::MXNet::Symbol|Str";
+subtype "Initializer" => as "AI::MXNet::Initializer|Str";
+subtype "Activation" => as "AI::MXNet::Symbol|Str|CodeRef";
subtype "SymbolOrArrayOfSymbols" => as "AI::MXNet::Symbol|ArrayRef[AI::MXNet::Symbol]";
subtype "NameShapeOrDataDesc" => as "NameShape|AI::MXNet::DataDesc";
diff --git a/perl-package/AI-MXNet/lib/AI/MXNet/Visualization.pm b/perl-package/AI-MXNet/lib/AI/MXNet/Visualization.pm
index 4cdc135..e28cd65 100644
--- a/perl-package/AI-MXNet/lib/AI/MXNet/Visualization.pm
+++ b/perl-package/AI-MXNet/lib/AI/MXNet/Visualization.pm
@@ -371,6 +371,7 @@ method plot_network(
}
$dot->graph->add_node($name, label => $label, %attr);
};
+
# add edges
for my $node (@{ $nodes })
{
@@ -395,6 +396,13 @@ method plot_network(
{
my $key = $input_name;
$key .= '_output' if $input_node->{op} ne 'null';
+ if($input_node->{op} ne 'null' and exists $input_node->{attr})
+ {
+ if(ref $input_node->{attr} eq 'HASH' and exists $input_node->{attr}{num_outputs})
+ {
+ $key .= ($input_node->{attr}{num_outputs} - 1);
+ }
+ }
my $end = @{ $shape_dict{$key} };
$attr{label} = join('x', @{ $shape_dict{$key} }[1..$end-1]);
}
diff --git a/perl-package/AI-MXNet/t/test_model_parallel.t b/perl-package/AI-MXNet/t/test_model_parallel.t
new file mode 100644
index 0000000..6a8aba7
--- /dev/null
+++ b/perl-package/AI-MXNet/t/test_model_parallel.t
@@ -0,0 +1,74 @@
+use strict;
+use warnings;
+use Test::More tests => 4;
+use AI::MXNet qw(mx);
+use AI::MXNet::TestUtils qw(reldiff);
+use AI::MXNet::Base;
+
+sub test_chain
+{
+ my $ctx1 = mx->cpu(0);
+ my $ctx2 = mx->cpu(1);
+ my $n = 2;
+ my $data1 = mx->sym->Variable('data1');
+ my $data2 = mx->sym->Variable('data2');
+ my $data3 = mx->sym->Variable('data2');
+ my $net;
+ {
+ local($mx::AttrScope) = mx->AttrScope(ctx_group=>'dev1');
+ $net = $data1 + $data2;
+ $net = $net * 3;
+ }
+ {
+ local($mx::AttrScope) = mx->AttrScope(ctx_group=>'dev2');
+ $net = $net + $data3;
+ }
+
+ my $arr = [];
+ my $arr_grad = [];
+ my $shape = [4, 5];
+ {
+ local($mx::Context) = $ctx1;
+ for (0..$n-1)
+ {
+ push @$arr, mx->nd->empty($shape);
+ push @$arr_grad, mx->nd->empty($shape);
+ }
+ }
+ {
+ local($mx::Context) = $ctx2;
+ push @$arr, mx->nd->empty($shape);
+ push @$arr_grad, mx->nd->empty($shape);
+ }
+
+ my $exec1 = $net->bind(
+ ctx => $ctx1,
+ args => $arr,
+ args_grad => $arr_grad,
+ group2ctx => { dev1 => $ctx1, dev2 => $ctx2 }
+ );
+ $arr->[0] .= 1;
+ $arr->[1] .= 2;
+ $arr->[2] .= 3;
+ my $arr2 = [map { $_->copyto($ctx1) } @$arr];
+ my $arr_grad2 = [map { $_->copyto($ctx1) } @$arr_grad];
+ my $exec2 = $net->bind(
+ ctx => $ctx1,
+ args => $arr2,
+ args_grad => $arr_grad2
+ );
+
+ $exec1->forward(1);
+ $exec2->forward(1);
+ ok(reldiff($exec1->outputs->[0]->aspdl, $exec2->outputs->[0]->aspdl) < 1e-6);
+ my $out_grad = mx->nd->empty($shape, ctx => $ctx1);
+ $out_grad .= 1;
+ $exec1->backward([$out_grad]);
+ $exec2->backward([$out_grad->copyto($ctx1)]);
+ zip(sub {
+ my ($a, $b) = @_;
+ ok(reldiff($a->aspdl, $b->aspdl) < 1e-6);
+ }, $arr_grad, $arr_grad2);
+}
+
+test_chain();
diff --git a/perl-package/AI-MXNet/t/test_rnn.t b/perl-package/AI-MXNet/t/test_rnn.t
index 77332b1..76242c0 100644
--- a/perl-package/AI-MXNet/t/test_rnn.t
+++ b/perl-package/AI-MXNet/t/test_rnn.t
@@ -3,7 +3,7 @@ use warnings;
use AI::MXNet qw(mx);
use AI::MXNet::TestUtils qw(same);
use PDL;
-use Test::More tests => 45;
+use Test::More tests => 54;
sub test_rnn
{
@@ -201,6 +201,63 @@ sub test_zoneout
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();
@@ -211,3 +268,6 @@ test_stack();
test_bidirectional();
test_unfuse();
test_zoneout();
+test_convrnn();
+test_convlstm();
+test_convgru();
diff --git a/perl-package/AI-MXNetCAPI/Changes b/perl-package/AI-MXNetCAPI/Changes
index 17595b4..1a6356c 100644
--- a/perl-package/AI-MXNetCAPI/Changes
+++ b/perl-package/AI-MXNetCAPI/Changes
@@ -1,5 +1,8 @@
Revision history for Perl extension AI::MXNetCAPI
+1.0102 Sun Aug 6 16:55:08 PDT 2017
+ - updated autograd calls.
+
1.0101 Sun Jul 2 17:16:01 PDT 2017
- refactored CachedOp, using strings to index the kvstore.
diff --git a/perl-package/AI-MXNetCAPI/META.json b/perl-package/AI-MXNetCAPI/META.json
index a79b1e0..a6d65fd 100644
--- a/perl-package/AI-MXNetCAPI/META.json
+++ b/perl-package/AI-MXNetCAPI/META.json
@@ -37,5 +37,5 @@
}
},
"release_status" : "stable",
- "version" : "1.0101"
+ "version" : "1.0102"
}
diff --git a/perl-package/AI-MXNetCAPI/META.yml b/perl-package/AI-MXNetCAPI/META.yml
index 84b7801..0e3bb53 100644
--- a/perl-package/AI-MXNetCAPI/META.yml
+++ b/perl-package/AI-MXNetCAPI/META.yml
@@ -19,4 +19,4 @@ no_index:
- inc
requires:
Test::More: '0'
-version: '1.0101'
+version: '1.0102'
diff --git a/perl-package/AI-MXNetCAPI/README b/perl-package/AI-MXNetCAPI/README
index 07df0c3..5c53146 100644
--- a/perl-package/AI-MXNetCAPI/README
+++ b/perl-package/AI-MXNetCAPI/README
@@ -1,4 +1,4 @@
-AI-MXNetCAPI version 1.0101
+AI-MXNetCAPI version 1.0102
=====================
Swig interface to MXNet c api.
diff --git a/perl-package/AI-MXNetCAPI/lib/AI/MXNetCAPI.pm b/perl-package/AI-MXNetCAPI/lib/AI/MXNetCAPI.pm
index f092057..0a93d71 100644
--- a/perl-package/AI-MXNetCAPI/lib/AI/MXNetCAPI.pm
+++ b/perl-package/AI-MXNetCAPI/lib/AI/MXNetCAPI.pm
@@ -18,7 +18,7 @@
package AI::MXNetCAPI;
use base qw(DynaLoader);
bootstrap AI::MXNetCAPI;
-our $VERSION = '1.0101';
+our $VERSION = '1.0102';
1;
__END__
diff --git a/perl-package/AI-MXNetCAPI/mxnet.i b/perl-package/AI-MXNetCAPI/mxnet.i
index bf00e68..fd1a471 100644
--- a/perl-package/AI-MXNetCAPI/mxnet.i
+++ b/perl-package/AI-MXNetCAPI/mxnet.i
@@ -459,6 +459,13 @@ int MXNDArrayGetContext(NDArrayHandle handle,
int *out,
int *out);
/*!
+ * \brief return gradient buffer attached to this NDArray
+ * \param handle NDArray handle
+ * \return 0 when success, -1 when failure happens
+ */
+int MXNDArrayGetGrad(NDArrayHandle handle, NDArrayHandle *out);
+
+/*!
* \brief detach and ndarray from computation graph by clearing entry_
* \param handle NDArray handle
* \return 0 when success, -1 when failure happens
--
To stop receiving notification emails like this one, please contact
['"commits@mxnet.apache.org" <co...@mxnet.apache.org>'].