view release on metacpan or search on metacpan
examples/image_classification.pl view on Meta::CPAN
use warnings;
use AI::MXNet::Gluon::ModelZoo 'get_model';
use AI::MXNet::Gluon::Utils 'download';
use Getopt::Long qw(HelpMessage);
GetOptions(
## my Pembroke Welsh Corgi Kyuubi, enjoing Solar eclipse of August 21, 2017
'image=s' => \(my $image = 'http://apache-mxnet.s3-accelerate.dualstack.amazonaws.com/'.
'gluon/dataset/kyuubi.jpg'),
'model=s' => \(my $model = 'resnet152_v2'),
'help' => sub { HelpMessage(0) },
) or HelpMessage(1);
## get a pretrained model (download parameters file if necessary)
my $net = get_model($model, pretrained => 1);
## ImageNet classes
my $fname = download('http://data.mxnet.io/models/imagenet/synset.txt');
my @text_labels = map { chomp; s/^\S+\s+//; $_ } IO::File->new($fname)->getlines;
## get the image from the disk or net
lib/AI/MXNet/Gluon/ModelZoo.pm view on Meta::CPAN
The context in which to load the pretrained weights.
:$root : Str, default '~/.mxnet/models'
Location for keeping the model parameters.
Returns
-------
HybridBlock
The model.
=cut
sub get_model
{
if(exists $models{lc $_[1]})
{
shift;
}
my ($name, %kwargs) = @_;
$name = lc $name;
Carp::confess(
"Model $name is not present in the zoo\nValid models are:\n".
join(', ', sort keys %models)."\n"
) unless exists $models{$name};
my $sub = $models{$name};
AI::MXNet::Gluon::ModelZoo::Vision->$sub(%kwargs);
}
sub vision { 'AI::MXNet::Gluon::ModelZoo::Vision' }
1;
=head1 AUTHOR
Sergey Kolychev, <sergeykolychev.github@gmail.com>
=head1 COPYRIGHT & LICENSE
This library is licensed under Apache 2.0 license L<https://www.apache.org/licenses/LICENSE-2.0>
lib/AI/MXNet/Gluon/ModelZoo/ModelStore.pm view on Meta::CPAN
['ad2f660d101905472b83590b59708b71ea22b2e5', 'vgg19'],
['f360b758e856f1074a85abd5fd873ed1d98297c3', 'vgg19_bn']
);
my $apache_repo_url = 'http://apache-mxnet.s3-accelerate.dualstack.amazonaws.com/';
my $_url_format = '%sgluon/models/%s.zip';
func short_hash($name)
{
Carp::confess("model $name is not available in model zoo") unless exists $_model_sha1{$name};
return substr($_model_sha1{$name}, 0, 8);
}
=head2 get_model_file
Return location for the pretrained on local file system.
This function will download from online model zoo when model cannot be found or has mismatch.
The root directory will be created if it doesn't exist.
Parameters
lib/AI/MXNet/Gluon/ModelZoo/Vision.pm view on Meta::CPAN
use warnings;
use AI::MXNet::Gluon::ModelZoo::ModelStore;
use AI::MXNet::Gluon::ModelZoo::Vision::AlexNet;
use AI::MXNet::Gluon::ModelZoo::Vision::DenseNet;
use AI::MXNet::Gluon::ModelZoo::Vision::Inception;
use AI::MXNet::Gluon::ModelZoo::Vision::MobileNet;
use AI::MXNet::Gluon::ModelZoo::Vision::ResNet;
use AI::MXNet::Gluon::ModelZoo::Vision::SqueezeNet;
use AI::MXNet::Gluon::ModelZoo::Vision::VGG;
sub import
{
my ($class, $short_name) = @_;
if($short_name)
{
$short_name =~ s/[^\w:]//g;
if(length $short_name)
{
my $short_name_package =<<"EOP";
package $short_name;
\@${short_name}::ISA = ('AI::MXNet::Gluon::ModelZoo::Vision');
lib/AI/MXNet/Gluon/ModelZoo/Vision/AlexNet.pm view on Meta::CPAN
AlexNet model from the "One weird trick..." <https://arxiv.org/abs/1404.5997> paper.
Parameters
----------
classes : Int, default 1000
Number of classes for the output layer.
=cut
has 'classes' => (is => 'ro', isa => 'Int', default => 1000);
method python_constructor_arguments() { ['classes'] }
sub BUILD
{
my $self = shift;
$self->name_scope(sub {
$self->features(nn->HybridSequential(prefix=>''));
$self->features->name_scope(sub {
$self->features->add(nn->Conv2D(64, kernel_size=>11, strides=>4,
padding=>2, activation=>'relu'));
$self->features->add(nn->MaxPool2D(pool_size=>3, strides=>2));
$self->features->add(nn->Conv2D(192, kernel_size=>5, padding=>2,
activation=>'relu'));
$self->features->add(nn->MaxPool2D(pool_size=>3, strides=>2));
$self->features->add(nn->Conv2D(384, kernel_size=>3, padding=>1,
activation=>'relu'));
$self->features->add(nn->Conv2D(256, kernel_size=>3, padding=>1,
activation=>'relu'));
lib/AI/MXNet/Gluon/ModelZoo/Vision/DenseNet.pm view on Meta::CPAN
use strict;
use warnings;
use AI::MXNet::Base;
use AI::MXNet::Function::Parameters;
use AI::MXNet::Gluon::Mouse;
extends 'AI::MXNet::Gluon::HybridBlock';
func _make_dense_block($num_layers, $bn_size, $growth_rate, $dropout, $stage_index)
{
my $out = nn->HybridSequential(prefix=>"stage${stage_index}_");
$out->name_scope(sub {
for(1..$num_layers)
{
$out->add(_make_dense_layer($growth_rate, $bn_size, $dropout));
}
});
return $out;
}
func _make_dense_layer($growth_rate, $bn_size, $dropout)
{
lib/AI/MXNet/Gluon/ModelZoo/Vision/DenseNet.pm view on Meta::CPAN
Number of classification classes.
=cut
has [qw/num_init_features
growth_rate/] => (is => 'ro', isa => 'Int', required => 1);
has 'block_config' => (is => 'ro', isa => 'ArrayRef[Int]', required => 1);
has 'bn_size' => (is => 'ro', isa => 'Int', default => 4);
has 'dropout' => (is => 'ro', isa => 'Num', default => 0);
has 'classes' => (is => 'ro', isa => 'Int', default => 1000);
method python_constructor_arguments(){ [qw/num_init_features growth_rate block_config bn_size dropout classes/] }
sub BUILD
{
my $self = shift;
$self->name_scope(sub {
$self->features(nn->HybridSequential(prefix=>''));
$self->features->add(
nn->Conv2D(
$self->num_init_features, kernel_size=>7,
strides=>2, padding=>3, use_bias=>0
)
);
$self->features->add(nn->BatchNorm());
$self->features->add(nn->Activation('relu'));
$self->features->add(nn->MaxPool2D(pool_size=>3, strides=>2, padding=>1));
lib/AI/MXNet/Gluon/ModelZoo/Vision/Inception.pm view on Meta::CPAN
}
}
$out->add(_make_basic_conv(%kwargs));
}
return $out;
}
func _make_A($pool_features, $prefix)
{
my $out = nn->HybridConcurrent(axis=>1, prefix=>$prefix);
$out->name_scope(sub {
$out->add(_make_branch('', [64, 1, undef, undef]));
$out->add(_make_branch(
'',
[48, 1, undef, undef],
[64, 5, undef, 2]
));
$out->add(_make_branch(
'',
[64, 1, undef, undef],
[96, 3, undef, 1],
[96, 3, undef, 1]
));
$out->add(_make_branch('avg', [$pool_features, 1, undef, undef]));
});
return $out;
}
func _make_B($prefix)
{
my $out = nn->HybridConcurrent(axis=>1, prefix=>$prefix);
$out->name_scope(sub {
$out->add(_make_branch('', [384, 3, 2, undef]));
$out->add(_make_branch(
'',
[64, 1, undef, undef],
[96, 3, undef, 1],
[96, 3, 2, undef]
));
$out->add(_make_branch('max'));
});
return $out;
}
func _make_C($channels_7x7, $prefix)
{
my $out = nn->HybridConcurrent(axis=>1, prefix=>$prefix);
$out->name_scope(sub {
$out->add(_make_branch('', [192, 1, undef, undef]));
$out->add(_make_branch(
'',
[$channels_7x7, 1, undef, undef],
[$channels_7x7, [1, 7], undef, [0, 3]],
[192, [7, 1], undef, [3, 0]]
));
$out->add(_make_branch(
'',
[$channels_7x7, 1, undef, undef],
lib/AI/MXNet/Gluon/ModelZoo/Vision/Inception.pm view on Meta::CPAN
'avg',
[192, 1, undef, undef]
));
});
return $out;
}
func _make_D($prefix)
{
my $out = nn->HybridConcurrent(axis=>1, prefix=>$prefix);
$out->name_scope(sub {
$out->add(_make_branch(
'',
[192, 1, undef, undef],
[320, 3, 2, undef]
));
$out->add(_make_branch(
'',
[192, 1, undef, undef],
[192, [1, 7], undef, [0, 3]],
[192, [7, 1], undef, [3, 0]],
[192, 3, 2, undef]
));
$out->add(_make_branch('max'));
});
return $out;
}
func _make_E($prefix)
{
my $out = nn->HybridConcurrent(axis=>1, prefix=>$prefix);
$out->name_scope(sub {
$out->add(_make_branch('', [320, 1, undef, undef]));
my $branch_3x3 = nn->HybridSequential(prefix=>'');
$out->add($branch_3x3);
$branch_3x3->add(_make_branch(
'',
[384, 1, undef, undef]
));
my $branch_3x3_split = nn->HybridConcurrent(axis=>1, prefix=>'');
$branch_3x3_split->add(_make_branch('', [384, [1, 3], undef, [0, 1]]));
lib/AI/MXNet/Gluon/ModelZoo/Vision/Inception.pm view on Meta::CPAN
Parameters
----------
classes : Int, default 1000
Number of classification classes.
=cut
has 'classes' => (is => 'ro', isa => 'Int', default => 1000);
method python_constructor_arguments(){ ['classes'] }
sub BUILD
{
my $self = shift;
$self->name_scope(sub {
$self->features(nn->HybridSequential(prefix=>''));
$self->features->add(_make_basic_conv(channels=>32, kernel_size=>3, strides=>2));
$self->features->add(_make_basic_conv(channels=>32, kernel_size=>3));
$self->features->add(_make_basic_conv(channels=>64, kernel_size=>3, padding=>1));
$self->features->add(nn->MaxPool2D(pool_size=>3, strides=>2));
$self->features->add(_make_basic_conv(channels=>80, kernel_size=>1));
$self->features->add(_make_basic_conv(channels=>192, kernel_size=>3));
$self->features->add(nn->MaxPool2D(pool_size=>3, strides=>2));
$self->features->add(_make_A(32, 'A1_'));
$self->features->add(_make_A(64, 'A2_'));
lib/AI/MXNet/Gluon/ModelZoo/Vision/MobileNet.pm view on Meta::CPAN
)
{
$out->add(nn->Conv2D($channels, $kernel, $stride, $pad, groups=>$num_group, use_bias=>0));
$out->add(nn->BatchNorm(scale=>1));
if($active)
{
$out->add($relu6 ? AI::MXNet::Gluon::ModelZoo::Vision::MobileNet::RELU6->new : nn->Activation('relu'));
}
}
sub BUILD
{
my $self = shift;
$self->use_shortcut($self->stride == 1 and $self->in_channels == $self->channels);
$self->name_scope(sub {
$self->out(nn->HybridSequential());
_add_conv($self->out, $self->in_channels * $self->t, relu6=>1);
_add_conv(
$self->out, $self->in_channels * $self->t, kernel=>3, stride=>$self->stride,
pad=>1, num_group=>$self->in_channels * $self->t, relu6=>1
);
_add_conv($self->out, $self->channels, active=>0, relu6=>1);
});
}
lib/AI/MXNet/Gluon/ModelZoo/Vision/MobileNet.pm view on Meta::CPAN
}
func _add_conv_dw($out, :$dw_channels=, :$channels=, :$stride=, :$relu6=0)
{
_add_conv($out, channels=>$dw_channels, kernel=>3, stride=>$stride,
pad=>1, num_group=>$dw_channels, relu6=>$relu6);
_add_conv($out, channels=>$channels, relu6=>$relu6);
}
sub BUILD
{
my $self = shift;
$self->name_scope(sub {
$self->features(nn->HybridSequential(prefix=>''));
$self->features->name_scope(sub {
_add_conv($self->features, channels=>int(32 * $self->multiplier), kernel=>3, pad=>1, stride=>2);
my $dw_channels = [map { int($_ * $self->multiplier) } (32, 64, (128)x2, (256)x2, (512)x6, 1024)];
my $channels = [map { int($_ * $self->multiplier) } (64, (128)x2, (256)x2, (512)x6, (1024)x2)];
my $strides = [(1, 2)x3, (1)x5, 2, 1];
for(zip($dw_channels, $channels, $strides))
{
my ($dwc, $c, $s) = @$_;
_add_conv_dw($self->features, dw_channels=>$dwc, channels=>$c, stride=>$s);
}
$self->features->add(nn->GlobalAvgPool2D());
lib/AI/MXNet/Gluon/ModelZoo/Vision/MobileNet.pm view on Meta::CPAN
)
{
$out->add(nn->Conv2D($channels, $kernel, $stride, $pad, groups=>$num_group, use_bias=>0));
$out->add(nn->BatchNorm(scale=>1));
if($active)
{
$out->add($relu6 ? AI::MXNet::Gluon::ModelZoo::Vision::MobileNet::RELU6->new : nn->Activation('relu'));
}
}
sub BUILD
{
my $self = shift;
$self->name_scope(sub {
$self->features(nn->HybridSequential(prefix=>'features_'));
$self->features->name_scope(sub {
_add_conv(
$self->features, int(32 * $self->multiplier), kernel=>3,
stride=>2, pad=>1, relu6=>1
);
my $in_channels_group = [map { int($_ * $self->multiplier) } (32, 16, (24)x2, (32)x3, (64)x4, (96)x3, (160)x3)];
my $channels_group = [map { int($_ * $self->multiplier) } (16, (24)x2, (32)x3, (64)x4, (96)x3, (160)x3, 320)];
my $ts = [1, (6)x16];
my $strides = [(1, 2)x2, 1, 1, 2, (1)x6, 2, (1)x3];
lib/AI/MXNet/Gluon/ModelZoo/Vision/MobileNet.pm view on Meta::CPAN
)
);
}
my $last_channels = $self->multiplier > 1 ? int(1280 * $self->multiplier) : 1280;
_add_conv($self->features, $last_channels, relu6=>1);
$self->features->add(nn->GlobalAvgPool2D());
});
$self->output(nn->HybridSequential(prefix=>'output_'));
$self->output->name_scope(sub {
$self->output->add(
nn->Conv2D($self->classes, 1, use_bias=>0, prefix=>'pred_'),
nn->Flatten()
);
});
});
}
method hybrid_forward(GluonClass $F, GluonInput $x)
{
lib/AI/MXNet/Gluon/ModelZoo/Vision/ResNet.pm view on Meta::CPAN
has 'in_channels' => (is => 'ro', isa => 'Int', default => 0);
method python_constructor_arguments() { [qw/channels stride downsample/] }
func _conv3x3($channels, $stride, $in_channels)
{
return nn->Conv2D(
$channels, kernel_size=>3, strides=>$stride, padding=>1,
use_bias=>0, in_channels=>$in_channels
);
}
sub BUILD
{
my $self = shift;
$self->body(nn->HybridSequential(prefix=>''));
$self->body->add(_conv3x3($self->channels, $self->stride, $self->in_channels));
$self->body->add(nn->BatchNorm());
$self->body->add(nn->Activation('relu'));
$self->body->add(_conv3x3($self->channels, 1, $self->channels));
$self->body->add(nn->BatchNorm());
if($self->downsample)
{
lib/AI/MXNet/Gluon/ModelZoo/Vision/ResNet.pm view on Meta::CPAN
has 'in_channels' => (is => 'ro', isa => 'Int', default => 0);
method python_constructor_arguments() { [qw/channels stride downsample/] }
func _conv3x3($channels, $stride, $in_channels)
{
return nn->Conv2D(
$channels, kernel_size=>3, strides=>$stride, padding=>1,
use_bias=>0, in_channels=>$in_channels
);
}
sub BUILD
{
my $self = shift;
$self->body(nn->HybridSequential(prefix=>''));
$self->body->add(nn->Conv2D(int($self->channels/4), kernel_size=>1, strides=>$self->stride));
$self->body->add(nn->BatchNorm());
$self->body->add(nn->Activation('relu'));
$self->body->add(_conv3x3(int($self->channels/4), 1, int($self->channels/4)));
$self->body->add(nn->BatchNorm());
$self->body->add(nn->Activation('relu'));
$self->body->add(nn->Conv2D($self->channels, kernel_size=>1, strides=>1));
lib/AI/MXNet/Gluon/ModelZoo/Vision/ResNet.pm view on Meta::CPAN
has 'in_channels' => (is => 'ro', isa => 'Int', default => 0);
method python_constructor_arguments() { [qw/channels stride downsample/] }
func _conv3x3($channels, $stride, $in_channels)
{
return nn->Conv2D(
$channels, kernel_size=>3, strides=>$stride, padding=>1,
use_bias=>0, in_channels=>$in_channels
);
}
sub BUILD
{
my $self = shift;
$self->bn1(nn->BatchNorm());
$self->conv1(_conv3x3($self->channels, $self->stride, $self->in_channels));
$self->bn2(nn->BatchNorm());
$self->conv2(_conv3x3($self->channels, 1, $self->channels));
if($self->downsample)
{
$self->downsample(
nn->Conv2D($self->channels, kernel_size=>1, strides=>$self->stride,
lib/AI/MXNet/Gluon/ModelZoo/Vision/ResNet.pm view on Meta::CPAN
has 'in_channels' => (is => 'ro', isa => 'Int', default => 0);
method python_constructor_arguments() { [qw/channels stride downsample/] }
func _conv3x3($channels, $stride, $in_channels)
{
return nn->Conv2D(
$channels, kernel_size=>3, strides=>$stride, padding=>1,
use_bias=>0, in_channels=>$in_channels
);
}
sub BUILD
{
my $self = shift;
$self->bn1(nn->BatchNorm());
$self->conv1(nn->Conv2D(int($self->channels/4), kernel_size=>1, strides=>1, use_bias=>0));
$self->bn2(nn->BatchNorm());
$self->conv2(_conv3x3(int($self->channels/4), $self->stride, int($self->channels/4)));
$self->bn3(nn->BatchNorm());
$self->conv3(nn->Conv2D($self->channels, kernel_size=>1, strides=>1, use_bias=>0));
if($self->downsample)
{
lib/AI/MXNet/Gluon/ModelZoo/Vision/ResNet.pm view on Meta::CPAN
has 'thumbnail' => (is => 'ro', isa => 'Bool', default => 0);
method python_constructor_arguments() { [qw/block layers channels classes thumbnail/] }
func _conv3x3($channels, $stride, $in_channels)
{
return nn->Conv2D(
$channels, kernel_size=>3, strides=>$stride, padding=>1,
use_bias=>0, in_channels=>$in_channels
);
}
sub BUILD
{
my $self = shift;
assert(@{ $self->layers } == (@{ $self->channels } - 1));
$self->name_scope(sub {
$self->features(nn->HybridSequential(prefix=>''));
if($self->thumbnail)
{
$self->features->add(_conv3x3($self->channels->[0], 1, 0));
}
else
{
$self->features->add(nn->Conv2D($self->channels->[0], 7, 2, 3, use_bias=>0));
$self->features->add(nn->BatchNorm());
$self->features->add(nn->Activation('relu'));
lib/AI/MXNet/Gluon/ModelZoo/Vision/ResNet.pm view on Meta::CPAN
);
}
$self->features->add(nn->GlobalAvgPool2D());
$self->output(nn->Dense($self->classes, in_units=>$self->channels->[-1]));
});
}
method _make_layer($block, $layers, $channels, $stride, $stage_index, :$in_channels=0)
{
my $layer = nn->HybridSequential(prefix=>"stage${stage_index}_");
$layer->name_scope(sub {
$layer->add(
$block->new(
$channels, $stride, $channels != $in_channels, in_channels=>$in_channels,
prefix=>''
)
);
for(1..$layers-1)
{
$layer->add($block->new($channels, 1, 0, in_channels=>$channels, prefix=>''));
}
lib/AI/MXNet/Gluon/ModelZoo/Vision/ResNet.pm view on Meta::CPAN
has 'thumbnail' => (is => 'ro', isa => 'Bool', default => 0);
method python_constructor_arguments() { [qw/block layers channels classes thumbnail/] }
func _conv3x3($channels, $stride, $in_channels)
{
return nn->Conv2D(
$channels, kernel_size=>3, strides=>$stride, padding=>1,
use_bias=>0, in_channels=>$in_channels
);
}
sub BUILD
{
my $self = shift;
assert(@{ $self->layers } == (@{ $self->channels } - 1));
$self->name_scope(sub {
$self->features(nn->HybridSequential(prefix=>''));
$self->features->add(nn->BatchNorm(scale=>0, center=>0));
if($self->thumbnail)
{
$self->features->add(_conv3x3($self->channels->[0], 1, 0));
}
else
{
$self->features->add(nn->Conv2D($self->channels->[0], 7, 2, 3, use_bias=>0));
$self->features->add(nn->BatchNorm());
lib/AI/MXNet/Gluon/ModelZoo/Vision/ResNet.pm view on Meta::CPAN
$self->features->add(nn->Activation('relu'));
$self->features->add(nn->GlobalAvgPool2D());
$self->features->add(nn->Flatten());
$self->output(nn->Dense($self->classes, in_units=>$in_channels));
});
}
method _make_layer($block, $layers, $channels, $stride, $stage_index, :$in_channels=0)
{
my $layer = nn->HybridSequential(prefix=>"stage${stage_index}_");
$layer->name_scope(sub {
$layer->add(
$block->new(
$channels, $stride, $channels != $in_channels, in_channels=>$in_channels,
prefix=>''
)
);
for(1..$layers-1)
{
$layer->add($block->new($channels, 1, 0, in_channels=>$channels, prefix=>''));
}
lib/AI/MXNet/Gluon/ModelZoo/Vision/SqueezeNet.pm view on Meta::CPAN
version : Str
Version of squeezenet. Options are '1.0', '1.1'.
classes : Int, default 1000
Number of classification classes.
=cut
has 'version' => (is => 'ro', isa => enum([qw[1.0 1.1]]), required => 1);
has 'classes' => (is => 'ro', isa => 'Int', default => 1000);
method python_constructor_arguments() { [qw/version classes/] }
sub BUILD
{
my $self = shift;
$self->name_scope(sub {
$self->features(nn->HybridSequential(prefix=>''));
if($self->version eq '1.0')
{
$self->features->add(nn->Conv2D(96, kernel_size=>7, strides=>2));
$self->features->add(nn->Activation('relu'));
$self->features->add(nn->MaxPool2D(pool_size=>3, strides=>2, ceil_mode=>1));
$self->features->add(_make_fire(16, 64, 64));
$self->features->add(_make_fire(16, 64, 64));
$self->features->add(_make_fire(32, 128, 128));
$self->features->add(nn->MaxPool2D(pool_size=>3, strides=>2, ceil_mode=>1));
lib/AI/MXNet/Gluon/ModelZoo/Vision/VGG.pm view on Meta::CPAN
Number of classification classes.
batch_norm : Bool, default 0
Use batch normalization.
=cut
method python_constructor_arguments() { [qw/layers filters classes batch_norm/] }
has ['layers',
'filters'] => (is => 'ro', isa => 'ArrayRef[Int]', required => 1);
has 'classes' => (is => 'ro', isa => 'Int', default => 1000);
has 'batch_norm' => (is => 'ro', isa => 'Bool', default => 0);
sub BUILD
{
my $self = shift;
assert(@{ $self->layers } == @{ $self->filters });
$self->name_scope(sub {
$self->features($self->_make_features());
$self->features->add(nn->Dense(4096, activation=>'relu',
weight_initializer=>'normal',
bias_initializer=>'zeros'));
$self->features->add(nn->Dropout(rate=>0.5));
$self->features->add(nn->Dense(4096, activation=>'relu',
weight_initializer=>'normal',
bias_initializer=>'zeros'));
$self->features->add(nn->Dropout(rate=>0.5));
$self->output(nn->Dense($self->classes,
t/test_gluon_model_zoo.t view on Meta::CPAN
# "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.
use strict;
use warnings;
use AI::MXNet::Gluon::ModelZoo qw(get_model);
use Test::More tests => 34;
sub test_models
{
my @all_models = ('resnet34_v1', 'resnet18_v1', 'resnet50_v1', 'resnet101_v1', 'resnet152_v1',
'resnet18_v2', 'resnet34_v2', 'resnet50_v2', 'resnet101_v2', 'resnet152_v2',
'vgg11', 'vgg13', 'vgg16', 'vgg19',
'vgg11_bn', 'vgg13_bn', 'vgg16_bn', 'vgg19_bn',
'alexnet', 'inceptionv3',
'densenet121', 'densenet161', 'densenet169', 'densenet201',
'squeezenet1.0', 'squeezenet1.1',
'mobilenet1.0', 'mobilenet0.75', 'mobilenet0.5', 'mobilenet0.25',
'mobilenetv2_1.0', 'mobilenetv2_0.75', 'mobilenetv2_0.5', 'mobilenetv2_0.25');