sergeykolychev commented on a change in pull request #8015: [Perl] Adding Gluon interface to Perl, miscellaneous changes in order to sync with Python URL: https://github.com/apache/incubator-mxnet/pull/8015#discussion_r141497578
########## File path: perl-package/AI-MXNet/lib/AI/MXNet/Gluon/NN/ConvLayers.pm ########## @@ -0,0 +1,1363 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +package AI::MXNet::Gluon::NN::Conv; +use AI::MXNet::Function::Parameters; +use AI::MXNet::Symbol; +use AI::MXNet::Gluon::Mouse; +extends 'AI::MXNet::Gluon::HybridBlock'; + +func _infer_weight_shape($op_name, $data_shape, $kwargs) +{ + my $sym = AI::MXNet::Symbol->$op_name( + AI::MXNet::Symbol->var('data', shape => $data_shape), %{ $kwargs } + ); + return ($sym->infer_shape_partial)[0]; +} + +=head1 NAME + + AI::MXNet::Gluon::NN::Conv +=cut + +=head1 DESCRIPTION + + Abstract nD convolution layer (private, used as implementation base). + + This layer creates a convolution kernel that is convolved + with the layer input to produce a tensor of outputs. + If `use_bias` is `True`, a bias vector is created and added to the outputs. + Finally, if `activation` is not `None`, + it is applied to the outputs as well. + + Parameters + ---------- + channels : int + The dimensionality of the output space + i.e. the number of output channels in the convolution. + kernel_size : int or tuple/list of n ints + Specifies the dimensions of the convolution window. + strides: int or tuple/list of n ints, + Specifies the strides of the convolution. + padding : int or tuple/list of n ints, + If padding is non-zero, then the input is implicitly zero-padded + on both sides for padding number of points + dilation: int or tuple/list of n ints, + Specifies the dilation rate to use for dilated convolution. + groups : int + Controls the connections between inputs and outputs. + At groups=1, all inputs are convolved to all outputs. + At groups=2, the operation becomes equivalent to having two convolution + layers side by side, each seeing half the input channels, and producing + half the output channels, and both subsequently concatenated. + layout : str, + Dimension ordering of data and weight. Can be 'NCW', 'NWC', 'NCHW', + 'NHWC', 'NCDHW', 'NDHWC', etc. 'N', 'C', 'H', 'W', 'D' stands for + batch, channel, height, width and depth dimensions respectively. + Convolution is performed over 'D', 'H', and 'W' dimensions. + in_channels : int, default 0 + The number of input channels to this layer. If not specified, + initialization will be deferred to the first time `forward` is called + and `in_channels` will be inferred from the shape of input data. + activation : str + Activation function to use. See :func:`~mxnet.ndarray.Activation`. + If you don't specify anything, no activation is applied + (ie. "linear" activation: `a(x) = x`). + use_bias: bool + Whether the layer uses a bias vector. + weight_initializer : str or `Initializer` + Initializer for the `weight` weights matrix. + bias_initializer: str or `Initializer` + Initializer for the bias vector. +=cut + +has 'channels' => (is => 'rw', isa => 'Int', required => 1); +has 'in_channels' => (is => 'rw', isa => 'Int', default => 0); +has 'kernel_size' => (is => 'rw', isa => 'DimSize|Shape', required => 1); +has [qw/strides + padding + dilation/] => (is => 'rw', isa => 'DimSize|Shape'); +has 'groups' => (is => 'rw', isa => 'Int'); +has [qw/layout + activation/] => (is => 'rw', isa => 'Str'); +has 'op_name' => (is => 'rw', isa => 'Str', default => 'Convolution'); +has 'use_bias' => (is => 'rw', isa => 'Bool', default => 1); +has 'weight_initializer' => (is => 'rw', isa => 'Maybe[Initializer]'); +has 'bias_initializer' => (is => 'rw', isa => 'Maybe[Initializer]', default => 'zeros'); +has 'adj' => (is => 'rw'); +has [qw/weight bias + kwargs act/] => (is => 'rw', init_arg => undef); +method python_constructor_arguments() { [qw/channels kernel_size strides padding dilation/] } + +sub BUILD +{ + my $self = shift; + $self->_update_kernel_size; + $self->name_scope(sub { + if(not ref $self->strides) + { + $self->strides([($self->strides) x @{ $self->kernel_size }]); + } + if(not ref $self->padding) + { + $self->padding([($self->padding) x @{ $self->kernel_size }]); + } + if(not ref $self->dilation) + { + $self->dilation([($self->dilation) x @{ $self->kernel_size }]); + } + $self->kwargs({ + kernel => $self->kernel_size, stride => $self->strides, dilate => $self->dilation, + pad => $self->padding, num_filter => $self->channels, num_group => $self->groups, + no_bias => $self->use_bias ? 0 : 1, layout => $self->layout + }); + if(defined $self->adj) + { + $self->kwargs->{adj} = $self->adj; + } + + my @dshape = (0)x(@{ $self->kernel_size } + 2); + $dshape[index($self->layout, 'N')] = 1; + $dshape[index($self->layout, 'C')] = $self->in_channels; + my $wshapes = _infer_weight_shape($self->op_name, \@dshape, $self->kwargs); + $self->weight( + $self->params->get( + 'weight', shape => $wshapes->[1], + init => $self->weight_initializer, + allow_deferred_init => 1 + ) + ); + if($self->use_bias) + { + $self->bias( + $self->params->get( + 'bias', shape => $wshapes->[2], + init => $self->bias_initializer, + allow_deferred_init => 1 + ) + ); + } + if(defined $self->activation) + { + $self->act( + AI::MXNet::Gluon::NN::Activation->new( + activation => $self->activation, + prefix => $self->activation.'_' + ) + ); + } + }); +} + +method hybrid_forward(GluonClass $F, GluonInput $x, GluonInput :$weight, Maybe[GluonInput] :$bias=) +{ + my $op_name = $self->op_name; + my $act = $F->$op_name($x, $weight, defined $bias ? $bias : (), name => 'fwd', %{ $self->kwargs }); + if(defined $self->act) + { + $act = $self->act->($act); + } + return $act; +} + +method _alias() { 'conv' } + +use Data::Dumper; +use overload '""' => sub { Review comment: yes, let's worry about this later. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected] With regards, Apache Git Services
