AI-MXNet
view release on metacpan or search on metacpan
lib/AI/MXNet/TestUtils.pm view on Meta::CPAN
symbol(s) to run the consistency test
ctx_list : list
running context. See example for more detail.
scale : float, optional
standard deviation of the inner normal distribution. Used in initialization
grad_req : str or list of str or dict of str to str
gradient requirement.
=cut
my %dtypes = (
float32 => 0,
float64 => 1,
float16 => 2,
uint8 => 3,
int32 => 4
);
func check_consistency(
SymbolOrArrayOfSymbols :$sym,
ArrayRef :$ctx_list,
Num :$scale=1,
Str|ArrayRef[Str]|HashRef[Str] :$grad_req='write',
Maybe[HashRef[AI::MXNet::NDArray]] :$arg_params=,
Maybe[HashRef[AI::MXNet::NDArray]] :$aux_params=,
Maybe[HashRef[Num]|Num] :$tol=,
Bool :$raise_on_err=1,
Maybe[AI::MXNer::NDArray] :$ground_truth=
)
{
$tol //= {
float16 => 1e-1,
float32 => 1e-3,
float64 => 1e-5,
uint8 => 0,
int32 => 0
};
$tol = {
float16 => $tol,
float32 => $tol,
float64 => $tol,
uint8 => $tol,
int32 => $tol
} unless ref $tol;
Test::More::ok(@$ctx_list > 1);
if(blessed $sym)
{
$sym = [($sym)x@$ctx_list];
}
else
{
Test::More::ok(@$sym == @$ctx_list);
}
my $output_names = $sym->[0]->list_outputs;
my $arg_names = $sym->[0]->list_arguments;
my @exe_list;
zip(sub {
my ($s, $ctx) = @_;
Test::More::is_deeply($s->list_arguments, $arg_names);
Test::More::is_deeply($s->list_outputs, $output_names);
push @exe_list, $s->simple_bind(grad_req=>$grad_req, %$ctx);
}, $sym, $ctx_list);
$arg_params //= {};
$aux_params //= {};
my %arg_dict = %{ $exe_list[0]->arg_dict };
while(my ($n, $arr) = each %arg_dict)
{
if(not exists $arg_params->{$n})
{
$arg_params->{$n} = random(reverse @{ $arr->shape })*$scale;
}
}
my %aux_dict = %{ $exe_list[0]->aux_dict };
while(my ($n, $arr) = each %aux_dict)
{
if(not exists $aux_params->{$n})
{
$aux_params->{$n} = 0;
}
}
for my $exe(@exe_list)
{
%arg_dict = %{ $exe->arg_dict };
while(my ($name, $arr) = each %arg_dict)
{
$arr .= $arg_params->{$name};
}
%aux_dict = %{ $exe->aux_dict };
while(my ($name, $arr) = each %aux_dict)
{
$arr .= $aux_params->{$name};
}
}
my @dtypes = map { $_->outputs->[0]->dtype } @exe_list;
my $max_idx = pdl(map { $dtypes{$_} } @dtypes)->maximum_ind;
my $gt = $ground_truth;
if(not defined $gt)
{
$gt = { %{ $exe_list[$max_idx]->output_dict } };
if($grad_req ne 'null')
{
%{$gt} = (%{$gt}, %{ $exe_list[$max_idx]->grad_dict });
}
}
# test
for my $exe (@exe_list)
{
$exe->forward(0);
}
enumerate(sub {
my ($i, $exe) = @_;
if($i == $max_idx)
{
return;
}
zip(sub {
my ($name, $arr) = @_;
my $gtarr = $gt->{$name}->astype($dtypes[$i])->aspdl;
$arr = $arr->aspdl;
Test::More::ok(
( run in 0.515 second using v1.01-cache-2.11-cpan-39bf76dae61 )