view release on metacpan or search on metacpan
lib/AI/TensorFlow/Libtensorflow/ImportGraphDefResults.pm view on Meta::CPAN
arg TF_ImportGraphDefResults => 'results',
] => 'void' );
$ffi->attach( [ 'ImportGraphDefResultsReturnOutputs' => 'ReturnOutputs' ] => [
arg TF_ImportGraphDefResults => 'results',
arg 'int*' => 'num_outputs',
arg 'opaque*' => { id => 'outputs', type => 'TF_Output_struct_array*' },
] => 'void' => sub {
my ($xs, $results) = @_;
my $num_outputs;
my $outputs_array = undef;
$xs->($results, \$num_outputs, \$outputs_array);
return [] if $num_outputs == 0;
my $sizeof_output = $ffi->sizeof('TF_Output');
window(my $outputs_packed, $outputs_array, $sizeof_output * $num_outputs );
# due to unpack, these are copies (no longer owned by $results)
my @outputs = map bless(\$_, "AI::TensorFlow::Libtensorflow::Output"),
unpack "(a${sizeof_output})*", $outputs_packed;
return \@outputs;
});
$ffi->attach( [ 'ImportGraphDefResultsReturnOperations' => 'ReturnOperations' ] => [
arg TF_ImportGraphDefResults => 'results',
arg 'int*' => 'num_opers',
arg 'opaque*' => { id => 'opers', type => 'TF_Operation_array*' },
] => 'void' => sub {
my ($xs, $results) = @_;
my $num_opers;
my $opers_array = undef;
$xs->($results, \$num_opers, \$opers_array);
return [] if $num_opers == 0;
my $opers_array_base_packed = buffer_to_scalar($opers_array,
$ffi->sizeof('opaque') * $num_opers );
my @opers = map {
$ffi->cast('opaque', 'TF_Operation', $_ )
} unpack "(@{[ AI::TensorFlow::Libtensorflow::Lib::_pointer_incantation ]})*", $opers_array_base_packed;
return \@opers;
} );
lib/AI/TensorFlow/Libtensorflow/Lib/FFIType/Variant/PackableMaybeArrayRef.pm view on Meta::CPAN
package AI::TensorFlow::Libtensorflow::Lib::FFIType::Variant::PackableMaybeArrayRef;
# ABSTRACT: Maybe[ArrayRef] to pack()'ed scalar argument with size argument (as int) (size is -1 if undef)
$AI::TensorFlow::Libtensorflow::Lib::FFIType::Variant::PackableMaybeArrayRef::VERSION = '0.0.7';
use strict;
use warnings;
use FFI::Platypus::Buffer qw(scalar_to_buffer buffer_to_scalar);
use FFI::Platypus::API qw( arguments_set_pointer arguments_set_sint32 );
use Package::Variant;
use Module::Runtime 'module_notional_filename';
sub make_variant {
lib/AI/TensorFlow/Libtensorflow/Lib/FFIType/Variant/PackableMaybeArrayRef.pm view on Meta::CPAN
if( defined $value ) {
die "Value must be an ArrayRef" unless ref $value eq 'ARRAY';
my $data = pack $arguments{pack_type} . '*', @$value;
my $n = scalar @$value;
my ($pointer, $size) = scalar_to_buffer($data);
push @stack, [ \$data, $pointer, $size ];
arguments_set_pointer( $i , $pointer);
arguments_set_sint32( $i+1, $n);
} else {
my $data = undef;
my $n = -1;
my ($pointer, $size) = (0, 0);
push @stack, [ \$data, $pointer, $size ];
arguments_set_pointer( $i , $pointer);
arguments_set_sint32( $i+1, $n);
}
};
my $perl_to_native_post = install perl_to_native_post => sub {
my ($data_ref, $pointer, $size) = @{ pop @stack };
lib/AI/TensorFlow/Libtensorflow/Lib/FFIType/Variant/PackableMaybeArrayRef.pm view on Meta::CPAN
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
AI::TensorFlow::Libtensorflow::Lib::FFIType::Variant::PackableMaybeArrayRef - Maybe[ArrayRef] to pack()'ed scalar argument with size argument (as int) (size is -1 if undef)
=head1 AUTHOR
Zakariyya Mughal <zmughal@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is Copyright (c) 2022-2023 by Auto-Parallel Technologies, Inc.
This is free software, licensed under:
lib/AI/TensorFlow/Libtensorflow/Lib/_Alloc.pm view on Meta::CPAN
use FFI::Platypus::Buffer qw(buffer_to_scalar window);
use Sub::Quote qw(quote_sub);
use Feature::Compat::Defer;
# If _aligned_alloc() implementation needs the size to be a multiple of the
# alignment.
our $_ALIGNED_ALLOC_ALIGNMENT_MULTIPLE = 0;
my $ffi = FFI::Platypus->new;
$ffi->lib(undef);
if( $ffi->find_symbol('aligned_alloc') ) {
# C11 aligned_alloc()
# NOTE: C11 aligned_alloc not available on Windows.
# void *aligned_alloc(size_t alignment, size_t size);
$ffi->attach( [ 'aligned_alloc' => '_aligned_alloc' ] =>
[ 'size_t', 'size_t' ] => 'opaque' );
*_aligned_free = *free;
$_ALIGNED_ALLOC_ALIGNMENT_MULTIPLE = 1;
} else {
# Pure Perl _aligned_alloc()
lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod view on Meta::CPAN
Fills in `funcs` with the TF_Function* registered in `g`.
`funcs` must point to an array of TF_Function* of length at least
`max_func`. In usual usage, max_func should be set to the result of
TF_GraphNumFunctions(g). In this case, all the functions registered in
`g` will be returned. Else, an unspecified subset.
If successful, returns the number of TF_Function* successfully set in
`funcs` and sets status to OK. The caller takes ownership of
all the returned TF_Functions. They must be deleted with TF_DeleteFunction.
On error, returns 0, sets status to the encountered error, and the contents
of funcs will be undefined.
=back
/* From <tensorflow/c/c_api.h> */
TF_CAPI_EXPORT extern int TF_GraphGetFunctions(TF_Graph* g, TF_Function** funcs,
int max_func, TF_Status* status);
=head2 TF_OperationToNodeDef
=over 2
lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod view on Meta::CPAN
=back
/* From <tensorflow/c/tf_shape.h> */
TF_CAPI_EXPORT extern int TF_ShapeDims(const TF_Shape* shape);
=head2 TF_ShapeDimSize
=over 2
Returns the `d`th dimension of `shape`. If `shape` has unknown rank,
invoking this function is undefined behavior. Returns -1 if dimension is
unknown.
=back
/* From <tensorflow/c/tf_shape.h> */
TF_CAPI_EXPORT extern int64_t TF_ShapeDimSize(const TF_Shape* shape, int d);
=head2 TF_DeleteShape
=over 2
lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod view on Meta::CPAN
(1) If attr_type == TF_ATTR_STRING
then total_size is the cumulative byte size
of all the strings in the list.
(3) If attr_type == TF_ATTR_SHAPE
then total_size is the number of dimensions
of the shape valued attribute, or -1
if its rank is unknown.
(4) If attr_type == TF_ATTR_SHAPE
then total_size is the cumulative number
of dimensions of all shapes in the list.
(5) Otherwise, total_size is undefined.
=back
/* From <tensorflow/c/kernels.h> */
TF_CAPI_EXPORT extern void TF_OpKernelConstruction_GetAttrSize(
TF_OpKernelConstruction* ctx, const char* attr_name, int32_t* list_size,
int32_t* total_size, TF_Status* status);
=head2 TF_OpKernelConstruction_GetAttrType
lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod view on Meta::CPAN
=back
/* From <tensorflow/c/c_api_experimental.h> */
TF_CAPI_EXPORT extern const char* TF_GetNumberAttrForOpListInput(
const char* op_name, int input_index, TF_Status* status);
=head2 TF_OpIsStateful
=over 2
Returns 1 if the op is stateful, 0 otherwise. The return value is undefined
if the status is not ok.
=back
/* From <tensorflow/c/c_api_experimental.h> */
TF_CAPI_EXPORT extern int TF_OpIsStateful(const char* op_type,
TF_Status* status);
=head2 TF_InitMain
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod view on Meta::CPAN
use PDL;
use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT UINT8);
use FFI::Platypus::Memory qw(memcpy);
use FFI::Platypus::Buffer qw(scalar_to_pointer);
sub FloatPDLTOTFTensor {
my ($p) = @_;
return AI::TensorFlow::Libtensorflow::Tensor->New(
FLOAT, [ reverse $p->dims ], $p->get_dataref, sub { undef $p }
);
}
sub FloatTFTensorToPDL {
my ($t) = @_;
my $pdl = zeros(float,reverse( map $t->Dim($_), 0..$t->NumDims-1 ) );
memcpy scalar_to_pointer( ${$pdl->get_dataref} ),
scalar_to_pointer( ${$t->Data} ),
$t->ByteSize;
$pdl->upd_data;
$pdl;
}
sub Uint8PDLTOTFTensor {
my ($p) = @_;
return AI::TensorFlow::Libtensorflow::Tensor->New(
UINT8, [ reverse $p->dims ], $p->get_dataref, sub { undef $p }
);
}
sub Uint8TFTensorToPDL {
my ($t) = @_;
my $pdl = zeros(byte,reverse( map $t->Dim($_), 0..$t->NumDims-1 ) );
memcpy scalar_to_pointer( ${$pdl->get_dataref} ),
scalar_to_pointer( ${$t->Data} ),
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod view on Meta::CPAN
qw(--signature_def) => 'serving_default'
) == 0 or die "Could not run saved_model_cli";
} else {
say "Install the tensorflow Python package to get the `saved_model_cli` command.";
}
my $opt = AI::TensorFlow::Libtensorflow::SessionOptions->New;
my $graph = AI::TensorFlow::Libtensorflow::Graph->New;
my $session = AI::TensorFlow::Libtensorflow::Session->LoadFromSavedModel(
$opt, undef, $model_base, \@tags, $graph, undef, $s
);
AssertOK($s);
my %ops = (
in => {
op => $graph->OperationByName('serving_default_input_tensor'),
dict => {
input_tensor => 0,
}
},
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod view on Meta::CPAN
p $pdl_image_batched;
p $t;
my $RunSession = sub {
my ($session, $t) = @_;
my @outputs_t;
my @keys = keys %{ $outputs{out} };
my @values = $outputs{out}->@{ @keys };
$session->Run(
undef,
[ values %{$outputs{in} } ], [$t],
\@values, \@outputs_t,
undef,
undef,
$s
);
AssertOK($s);
return { mesh \@keys, \@outputs_t };
};
undef;
my $tftensor_output_by_name = $RunSession->($session, $t);
my %pdl_output_by_name = map {
$_ => FloatTFTensorToPDL( $tftensor_output_by_name->{$_} )
} keys $tftensor_output_by_name->%*;
undef;
my $min_score_thresh = 0.30;
my $which_detect = which( $pdl_output_by_name{detection_scores} > $min_score_thresh );
my %subset;
$subset{detection_boxes} = $pdl_output_by_name{detection_boxes}->dice('X', $which_detect);
$subset{detection_classes} = $pdl_output_by_name{detection_classes}->dice($which_detect);
$subset{detection_scores} = $pdl_output_by_name{detection_scores}->dice($which_detect);
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod view on Meta::CPAN
$gp->close;
IPerl->png( bytestream => path($plot_output_path)->slurp_raw ) if IN_IPERL;
use Filesys::DiskUsage qw/du/;
my $total = du( { 'human-readable' => 1, dereference => 1 },
$model_archive_path, $model_base );
say "Disk space usage: $total"; undef;
__END__
=pod
=encoding UTF-8
=head1 NAME
AI::TensorFlow::Libtensorflow::Manual::Notebook::InferenceUsingTFHubCenterNetObjDetect - Using TensorFlow to do object detection using a pre-trained model
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod view on Meta::CPAN
use PDL;
use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT UINT8);
use FFI::Platypus::Memory qw(memcpy);
use FFI::Platypus::Buffer qw(scalar_to_pointer);
sub FloatPDLTOTFTensor {
my ($p) = @_;
return AI::TensorFlow::Libtensorflow::Tensor->New(
FLOAT, [ reverse $p->dims ], $p->get_dataref, sub { undef $p }
);
}
sub FloatTFTensorToPDL {
my ($t) = @_;
my $pdl = zeros(float,reverse( map $t->Dim($_), 0..$t->NumDims-1 ) );
memcpy scalar_to_pointer( ${$pdl->get_dataref} ),
scalar_to_pointer( ${$t->Data} ),
$t->ByteSize;
$pdl->upd_data;
$pdl;
}
sub Uint8PDLTOTFTensor {
my ($p) = @_;
return AI::TensorFlow::Libtensorflow::Tensor->New(
UINT8, [ reverse $p->dims ], $p->get_dataref, sub { undef $p }
);
}
sub Uint8TFTensorToPDL {
my ($t) = @_;
my $pdl = zeros(byte,reverse( map $t->Dim($_), 0..$t->NumDims-1 ) );
memcpy scalar_to_pointer( ${$pdl->get_dataref} ),
scalar_to_pointer( ${$t->Data} ),
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod view on Meta::CPAN
=back
Note that the above documentation has two errors: both C<num_detections> and C<detection_classes> are not of type C<tf.int>, but are actually C<tf.float32>.
Now we can load the model from that folder with the tag set C<[ 'serve' ]> by using the C<LoadFromSavedModel> constructor to create a C<::Graph> and a C<::Session> for that graph.
my $opt = AI::TensorFlow::Libtensorflow::SessionOptions->New;
my $graph = AI::TensorFlow::Libtensorflow::Graph->New;
my $session = AI::TensorFlow::Libtensorflow::Session->LoadFromSavedModel(
$opt, undef, $model_base, \@tags, $graph, undef, $s
);
AssertOK($s);
So let's use the names from the C<saved_model_cli> output to create our C<::Output> C<ArrayRef>s.
my %ops = (
in => {
op => $graph->OperationByName('serving_default_input_tensor'),
dict => {
input_tensor => 0,
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod view on Meta::CPAN
We can use the C<Run> method to run the session and get the multiple output C<TFTensor>s. The following uses the names in C<$outputs> mapping to help process the multiple outputs more easily.
my $RunSession = sub {
my ($session, $t) = @_;
my @outputs_t;
my @keys = keys %{ $outputs{out} };
my @values = $outputs{out}->@{ @keys };
$session->Run(
undef,
[ values %{$outputs{in} } ], [$t],
\@values, \@outputs_t,
undef,
undef,
$s
);
AssertOK($s);
return { mesh \@keys, \@outputs_t };
};
undef;
my $tftensor_output_by_name = $RunSession->($session, $t);
my %pdl_output_by_name = map {
$_ => FloatTFTensorToPDL( $tftensor_output_by_name->{$_} )
} keys $tftensor_output_by_name->%*;
undef;
=head2 Results summary
Then we use a score threshold to select the objects of interest.
my $min_score_thresh = 0.30;
my $which_detect = which( $pdl_output_by_name{detection_scores} > $min_score_thresh );
my %subset;
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod view on Meta::CPAN
IPerl->png( bytestream => path($plot_output_path)->slurp_raw ) if IN_IPERL;
=head1 RESOURCE USAGE
use Filesys::DiskUsage qw/du/;
my $total = du( { 'human-readable' => 1, dereference => 1 },
$model_archive_path, $model_base );
say "Disk space usage: $total"; undef;
=head1 CPANFILE
requires 'AI::TensorFlow::Libtensorflow';
requires 'AI::TensorFlow::Libtensorflow::DataType';
requires 'Archive::Extract';
requires 'Data::Printer';
requires 'Data::Printer::Filter::PDL';
requires 'FFI::Platypus::Buffer';
requires 'FFI::Platypus::Memory';
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
use PDL;
use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT);
use FFI::Platypus::Memory qw(memcpy);
use FFI::Platypus::Buffer qw(scalar_to_pointer);
sub FloatPDLTOTFTensor {
my ($p) = @_;
return AI::TensorFlow::Libtensorflow::Tensor->New(
FLOAT, [ reverse $p->dims ], $p->get_dataref, sub { undef $p }
);
}
sub FloatTFTensorToPDL {
my ($t) = @_;
my $pdl = zeros(float,reverse( map $t->Dim($_), 0..$t->NumDims-1 ) );
memcpy scalar_to_pointer( ${$pdl->get_dataref} ),
scalar_to_pointer( ${$t->Data} ),
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
say "";
say "First 5:";
say $df->head(5);
my $opt = AI::TensorFlow::Libtensorflow::SessionOptions->New;
my @tags = ( 'serve' );
my $graph = AI::TensorFlow::Libtensorflow::Graph->New;
my $session = AI::TensorFlow::Libtensorflow::Session->LoadFromSavedModel(
$opt, undef, $new_model_base, \@tags, $graph, undef, $s
);
AssertOK($s);
my %puts = (
## Inputs
inputs_args_0 =>
AI::TensorFlow::Libtensorflow::Output->New({
oper => $graph->OperationByName('serving_default_args_0'),
index => 0,
}),
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
}),
);
p %puts;
my $predict_on_batch = sub {
my ($session, $t) = @_;
my @outputs_t;
$session->Run(
undef,
[$puts{inputs_args_0}], [$t],
[$puts{outputs_human}], \@outputs_t,
undef,
undef,
$s
);
AssertOK($s);
return $outputs_t[0];
};
undef;
use PDL;
our $SHOW_ENCODER = 1;
sub one_hot_dna {
my ($seq) = @_;
my $from_alphabet = "NACGT";
my $to_alphabet = pack "C*", 0..length($from_alphabet)-1;
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
for(0..5) {
my $base = $test_interval->length;
my $to = $base + $_;
_debug_resize $test_interval, $to, "$base -> $to (+ $_)";
}
say "";
}
}
undef;
use Bio::DB::HTS::Faidx;
my $hg_db = Bio::DB::HTS::Faidx->new( $hg_bgz_path );
sub extract_sequence {
my ($db, $interval) = @_;
my $chrom_length = $db->length($interval->seq_id);
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
say "Resized interval: $resized_interval with length @{[ $resized_interval->length ]}";
die "resize() is not working properly!" unless $resized_interval->length == $model_sequence_length;
my $seq = extract_sequence( $hg_db, $resized_interval );
say "Resized sequence is ", seq_info($seq);
my $sequence_one_hot = one_hot_dna( $seq )->dummy(-1);
say $sequence_one_hot->info; undef;
use Devel::Timer;
my $t = Devel::Timer->new;
$t->mark('prediction of sequence');
my $predictions = $predict_on_batch->( $session, FloatPDLTOTFTensor( $sequence_one_hot ) );
$t->mark('End of prediction of sequence');
p $predictions;
$t->mark('END');
$t->report();
my $predictions_p = FloatTFTensorToPDL($predictions)->slice(',,(0)');
say $predictions_p->info; undef;
my @tracks = (
[ 'DNASE:CD14-positive monocyte female' => 41 => $predictions_p->slice('(41)') ],
[ 'DNASE:keratinocyte female' => 42 => $predictions_p->slice('(42)') ],
[ 'CHIP:H3K27ac:keratinocyte female' => 706 => $predictions_p->slice('(706)')],
[ 'CAGE:Keratinocyte - epidermal' => 4799 => log10(1 + $predictions_p->slice('(4799)')) ],
);
use PDL::Graphics::Gnuplot;
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
my $clinvar_tbi_path = "${clinvar_path}.tbi";
unless( -f $clinvar_tbi_path ) {
system( qw(tabix), $clinvar_path );
}
my $v = Bio::DB::HTS::VCF->new( filename => $clinvar_path );
$v->num_variants
COMMENT
undef;
use Filesys::DiskUsage qw/du/;
my $total = du( { 'human-readable' => 1, dereference => 1 },
$model_archive_path, $model_base, $new_model_base,
$targets_path,
$hg_gz_path,
$hg_bgz_path, $hg_bgz_fai_path,
$clinvar_path,
$plot_output_path,
);
say "Disk space usage: $total"; undef;
__END__
=pod
=encoding UTF-8
=head1 NAME
AI::TensorFlow::Libtensorflow::Manual::Notebook::InferenceUsingTFHubEnformerGeneExprPredModel - Using TensorFlow to do gene expression prediction using a pre-trained model
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
use PDL;
use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT);
use FFI::Platypus::Memory qw(memcpy);
use FFI::Platypus::Buffer qw(scalar_to_pointer);
sub FloatPDLTOTFTensor {
my ($p) = @_;
return AI::TensorFlow::Libtensorflow::Tensor->New(
FLOAT, [ reverse $p->dims ], $p->get_dataref, sub { undef $p }
);
}
sub FloatTFTensorToPDL {
my ($t) = @_;
my $pdl = zeros(float,reverse( map $t->Dim($_), 0..$t->NumDims-1 ) );
memcpy scalar_to_pointer( ${$pdl->get_dataref} ),
scalar_to_pointer( ${$t->Data} ),
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
=head2 Load the model
Let's now load the model in Perl and get the inputs and outputs into a data structure by name.
my $opt = AI::TensorFlow::Libtensorflow::SessionOptions->New;
my @tags = ( 'serve' );
my $graph = AI::TensorFlow::Libtensorflow::Graph->New;
my $session = AI::TensorFlow::Libtensorflow::Session->LoadFromSavedModel(
$opt, undef, $new_model_base, \@tags, $graph, undef, $s
);
AssertOK($s);
my %puts = (
## Inputs
inputs_args_0 =>
AI::TensorFlow::Libtensorflow::Output->New({
oper => $graph->OperationByName('serving_default_args_0'),
index => 0,
}),
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
</span><span style="color: #33ccff;">}</span><span style="">
</span></code></pre></span>
We need a helper to simplify running the session and getting just the predictions that we want.
my $predict_on_batch = sub {
my ($session, $t) = @_;
my @outputs_t;
$session->Run(
undef,
[$puts{inputs_args_0}], [$t],
[$puts{outputs_human}], \@outputs_t,
undef,
undef,
$s
);
AssertOK($s);
return $outputs_t[0];
};
undef;
=head2 Encoding the data
The model specifies that the way to get a sequence of DNA bases into a C<TFTensor> is to use L<one-hot encoding|https://en.wikipedia.org/wiki/One-hot#Machine_learning_and_statistics> in the order C<ACGT>.
This means that the bases are represented as vectors of length 4:
| base | vector encoding |
|------|-----------------|
| A | C<[1 0 0 0]> |
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
for(0..5) {
my $base = $test_interval->length;
my $to = $base + $_;
_debug_resize $test_interval, $to, "$base -> $to (+ $_)";
}
say "";
}
}
undef;
B<STREAM (STDOUT)>:
Testing interval resizing:
Testing interval chr11:4..8 with length 5
-----
Interval: chr11:4..8 -> chr11:4..8, length 5 : 5 -> 5 (+ 0)
Interval: chr11:4..8 -> chr11:3..8, length 6 : 5 -> 6 (+ 1)
Interval: chr11:4..8 -> chr11:3..9, length 7 : 5 -> 7 (+ 2)
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
Resized sequence is ACTAGTTCTA...GGCCCAAATC (length 393216)
B<RESULT>:
1
To prepare the input we have to one-hot encode this resized sequence and give it a dummy dimension at the end to indicate that it is is a batch with a single sequence. Then we can turn the PDL ndarray into a C<TFTensor> and pass it to our prediction ...
my $sequence_one_hot = one_hot_dna( $seq )->dummy(-1);
say $sequence_one_hot->info; undef;
B<STREAM (STDOUT)>:
PDL: Float D [4,393216,1]
use Devel::Timer;
my $t = Devel::Timer->new;
$t->mark('prediction of sequence');
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
01 -> 02 14.5634 100.00% prediction of sequence -> End of prediction of sequence
02 -> 03 0.0007 0.00% End of prediction of sequence -> END
00 -> 01 0.0000 0.00% INIT -> prediction of sequence
</span></code></pre></span>
=end html
Now we turn the C<TFTensor> output into a PDL ndarray.
my $predictions_p = FloatTFTensorToPDL($predictions)->slice(',,(0)');
say $predictions_p->info; undef;
B<STREAM (STDOUT)>:
PDL: Float D [5313,896]
=head2 Plot predicted tracks
These predictions can be plotted
my @tracks = (
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod view on Meta::CPAN
my $clinvar_tbi_path = "${clinvar_path}.tbi";
unless( -f $clinvar_tbi_path ) {
system( qw(tabix), $clinvar_path );
}
my $v = Bio::DB::HTS::VCF->new( filename => $clinvar_path );
$v->num_variants
COMMENT
undef;
=head1 RESOURCE USAGE
use Filesys::DiskUsage qw/du/;
my $total = du( { 'human-readable' => 1, dereference => 1 },
$model_archive_path, $model_base, $new_model_base,
$targets_path,
$hg_gz_path,
$hg_bgz_path, $hg_bgz_fai_path,
$clinvar_path,
$plot_output_path,
);
say "Disk space usage: $total"; undef;
B<STREAM (STDOUT)>:
Disk space usage: 4.66G
=head1 CPANFILE
requires 'AI::TensorFlow::Libtensorflow';
requires 'AI::TensorFlow::Libtensorflow::DataType';
requires 'Archive::Extract';
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod view on Meta::CPAN
use PDL;
use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT);
use FFI::Platypus::Memory qw(memcpy);
use FFI::Platypus::Buffer qw(scalar_to_pointer);
sub FloatPDLTOTFTensor {
my ($p) = @_;
return AI::TensorFlow::Libtensorflow::Tensor->New(
FLOAT, [ reverse $p->dims ], $p->get_dataref, sub { undef $p }
);
}
sub FloatTFTensorToPDL {
my ($t) = @_;
my $pdl = zeros(float,reverse( map $t->Dim($_), 0..$t->NumDims-1 ) );
memcpy scalar_to_pointer( ${$pdl->get_dataref} ),
scalar_to_pointer( ${$t->Data} ),
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod view on Meta::CPAN
qw(--signature_def) => 'serving_default'
) == 0 or die "Could not run saved_model_cli";
} else {
say "Install the tensorflow Python package to get the `saved_model_cli` command.";
}
my $opt = AI::TensorFlow::Libtensorflow::SessionOptions->New;
my $graph = AI::TensorFlow::Libtensorflow::Graph->New;
my $session = AI::TensorFlow::Libtensorflow::Session->LoadFromSavedModel(
$opt, undef, $model_base, \@tags, $graph, undef, $s
);
AssertOK($s);
my %ops = (
in => $graph->OperationByName('serving_default_inputs'),
out => $graph->OperationByName('StatefulPartitionedCall'),
);
die "Could not get all operations" unless List::Util::all(sub { defined }, values %ops);
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod view on Meta::CPAN
my $t = FloatPDLTOTFTensor($pdl_image_batched);
p $pdl_image_batched;
p $t;
my $RunSession = sub {
my ($session, $t) = @_;
my @outputs_t;
$session->Run(
undef,
$outputs{in}, [$t],
$outputs{out}, \@outputs_t,
undef,
undef,
$s
);
AssertOK($s);
return $outputs_t[0];
};
say "Warming up the model";
use PDL::GSL::RNG;
my $rng = PDL::GSL::RNG->new('default');
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod view on Meta::CPAN
my $p_approx_batched = $probabilities_batched->sumover->approx(1, 1e-5);
p $p_approx_batched;
say "All probabilities sum up to approximately 1" if $p_approx_batched->all->sclr;
use Filesys::DiskUsage qw/du/;
my $total = du( { 'human-readable' => 1, dereference => 1 },
$model_archive_path, $model_base, $labels_path );
say "Disk space usage: $total"; undef;
my @solid_channel_uris = (
'https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Solid_red.svg/480px-Solid_red.svg.png',
'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Green_00FF00_9x9.svg/480px-Green_00FF00_9x9.svg.png',
'https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Solid_blue.svg/480px-Solid_blue.svg.png',
);
undef;
__END__
=pod
=encoding UTF-8
=head1 NAME
AI::TensorFlow::Libtensorflow::Manual::Notebook::InferenceUsingTFHubMobileNetV2Model - Using TensorFlow to do image classification using a pre-trained model
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod view on Meta::CPAN
use PDL;
use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT);
use FFI::Platypus::Memory qw(memcpy);
use FFI::Platypus::Buffer qw(scalar_to_pointer);
sub FloatPDLTOTFTensor {
my ($p) = @_;
return AI::TensorFlow::Libtensorflow::Tensor->New(
FLOAT, [ reverse $p->dims ], $p->get_dataref, sub { undef $p }
);
}
sub FloatTFTensorToPDL {
my ($t) = @_;
my $pdl = zeros(float,reverse( map $t->Dim($_), 0..$t->NumDims-1 ) );
memcpy scalar_to_pointer( ${$pdl->get_dataref} ),
scalar_to_pointer( ${$t->Data} ),
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod view on Meta::CPAN
For the C<input>, we have C<(-1, 224, 224, 3)> which is a L<common input image specification for TensorFlow Hub|https://www.tensorflow.org/hub/common_signatures/images#input>. This is known as C<channels_last> (or C<NHWC>) layout where the TensorFlow...
For the C<output>, we have C<(-1, 1001)> which is C<[batch_size, num_classes]> where the elements are scores that the image received for that ImageNet class.
Now we can load the model from that folder with the tag set C<[ 'serve' ]> by using the C<LoadFromSavedModel> constructor to create a C<::Graph> and a C<::Session> for that graph.
my $opt = AI::TensorFlow::Libtensorflow::SessionOptions->New;
my $graph = AI::TensorFlow::Libtensorflow::Graph->New;
my $session = AI::TensorFlow::Libtensorflow::Session->LoadFromSavedModel(
$opt, undef, $model_base, \@tags, $graph, undef, $s
);
AssertOK($s);
So let's use the names from the C<saved_model_cli> output to create our C<::Output> C<ArrayRef>s.
my %ops = (
in => $graph->OperationByName('serving_default_inputs'),
out => $graph->OperationByName('StatefulPartitionedCall'),
);
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod view on Meta::CPAN
We can use the C<Run> method to run the session and get the output C<TFTensor>.
First, we send a single random input to warm up the model.
my $RunSession = sub {
my ($session, $t) = @_;
my @outputs_t;
$session->Run(
undef,
$outputs{in}, [$t],
$outputs{out}, \@outputs_t,
undef,
undef,
$s
);
AssertOK($s);
return $outputs_t[0];
};
say "Warming up the model";
use PDL::GSL::RNG;
my $rng = PDL::GSL::RNG->new('default');
lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod view on Meta::CPAN
1
=head1 RESOURCE USAGE
use Filesys::DiskUsage qw/du/;
my $total = du( { 'human-readable' => 1, dereference => 1 },
$model_archive_path, $model_base, $labels_path );
say "Disk space usage: $total"; undef;
B<STREAM (STDOUT)>:
Disk space usage: 27.45M
=head1 DEBUGGING
The following images can be used to test the C<load_image_to_pdl> function.
my @solid_channel_uris = (
'https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Solid_red.svg/480px-Solid_red.svg.png',
'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Green_00FF00_9x9.svg/480px-Green_00FF00_9x9.svg.png',
'https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Solid_blue.svg/480px-Solid_blue.svg.png',
);
undef;
=head1 CPANFILE
requires 'AI::TensorFlow::Libtensorflow';
requires 'AI::TensorFlow::Libtensorflow::DataType';
requires 'Archive::Extract';
requires 'Data::Printer';
requires 'Data::Printer::Filter::PDL';
requires 'FFI::Platypus::Buffer';
requires 'FFI::Platypus::Memory';
lib/AI/TensorFlow/Libtensorflow/Output.pm view on Meta::CPAN
RecordArrayRef( 'OutputArrayPtrSz',
record_module => __PACKAGE__, with_size => 1,
),
=> 'TF_Output_array_sz');
use overload
'""' => \&_op_stringify;
sub _op_stringify {
join ":", (
( defined $_[0]->_oper ? $_[0]->oper->Name : '<undefined operation>' ),
( defined $_[0]->index ? $_[0]->index : '<no index>' )
);
}
sub _data_printer {
my ($self, $ddp) = @_;
my %data = (
oper => $self->oper,
index => $self->index,
lib/AI/TensorFlow/Libtensorflow/Session.pm view on Meta::CPAN
}
);
sub _process_target_opers_args {
my ($target_opers) = @_;
my @target_opers_args = defined $target_opers
? do {
my $target_opers_a = AI::TensorFlow::Libtensorflow::Operation->_as_array( @$target_opers );
( $target_opers_a, $target_opers_a->count )
}
: ( undef, 0 );
return @target_opers_args;
}
$ffi->attach([ 'SessionPRunSetup' => 'PRunSetup' ] => [
arg TF_Session => 'session',
# Input names
arg TF_Output_struct_array => 'inputs',
arg int => 'ninputs',
# Output names
lib/AI/TensorFlow/Libtensorflow/Session.pm view on Meta::CPAN
Status.
=back
B<Returns>
=over 4
=item Maybe[TFSession]
A new execution session with the associated graph, or C<undef> on
error.
=back
B<C API>: L<< C<TF_NewSession>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_NewSession >>
=head2 LoadFromSavedModel
B<C API>: L<< C<TF_LoadSessionFromSavedModel>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_LoadSessionFromSavedModel >>
lib/AI/TensorFlow/Libtensorflow/Tensor.pm view on Meta::CPAN
=back
Creates a C<TFTensor> from a data buffer C<$data> with the given specification
of data type C<$dtype> and dimensions C<$dims>.
# Create a buffer containing 0 through 8 single-precision
# floating-point data.
my $data = pack("f*", 0..8);
$t = Tensor->New(
FLOAT, [3,3], \$data, sub { undef $data }, undef
);
ok $t, 'Created 3-by-3 float TFTensor';
Implementation note: if C<$dtype> is not a
L<STRING|AI::TensorFlow::Libtensorflow::DataType/STRING>
or
L<RESOURCE|AI::TensorFlow::Libtensorflow::DataType/RESOURCE>,
then the pointer for C<$data> is checked to see if meets the
TensorFlow's alignment preferences. If it does not, the
lib/AI/TensorFlow/Libtensorflow/Tensor.pm view on Meta::CPAN
Data buffer for the contents of the C<TFTensor>.
=item CodeRef $deallocator
A callback used to deallocate C<$data> which is passed the
parameters C<<
$deallocator->( opaque $pointer, size_t $size, opaque $deallocator_arg)
>>.
=item Ref $deallocator_arg [optional, default: C<undef>]
Argument that is passed to the C<$deallocator> callback.
=back
B<Returns>
=over 4
=item L<TFTensor|AI::TensorFlow::Libtensorflow::Lib::Types/TFTensor>
lib/AI/TensorFlow/Libtensorflow/Tensor.pm view on Meta::CPAN
=head2 MaybeMove
B<Returns>
=over 4
=item Maybe[TFTensor]
Deletes the C<TFTensor> and returns a new C<TFTensor> with the
same content if possible. Returns C<undef> and leaves the
C<TFTensor> untouched if not.
=back
B<C API>: L<< C<TF_TensorMaybeMove>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_TensorMaybeMove >>
=head2 IsAligned
B<C API>: L<< C<TF_TensorIsAligned>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_TensorIsAligned >>
maint/inc/Pod/Elemental/Transformer/TF_CAPI.pm view on Meta::CPAN
use Moose;
use Pod::Elemental::Transformer 0.101620;
with 'Pod::Elemental::Transformer';
use Pod::Elemental::Element::Pod5::Command;
use namespace::autoclean;
has command_name => (
is => 'ro',
init_arg => undef,
);
sub transform_node {
my ($self, $node) = @_;
for my $i (reverse(0 .. $#{ $node->children })) {
my $para = $node->children->[ $i ];
next unless $self->__is_xformable($para);
my @replacements = $self->_expand( $para );
splice @{ $node->children }, $i, 1, @replacements;
maint/inc/Pod/Elemental/Transformer/TF_Sig.pm view on Meta::CPAN
) {
$prefix = Pod::Elemental::Element::Pod5::Ordinary->new({
content => "B<@{[ $region_types{$para->format_name} ]}>",
});
}
my @replacements;
if( $is_list_type ) {
@replacements = $orig->($self, $para);
} else {
undef $prefix;
push @replacements, Pod::Elemental::Element::Pod5::Ordinary
->new( { content => do { my $v = <<EOF; chomp $v; $v } });
=over 2
C<<<
@{[ join("\n", map { $_->content } $para->children->@*) ]}
>>>
=back
EOF
maint/process-capi.pl view on Meta::CPAN
};
method check_types() {
my @data = $self->typedef_struct_data->@*;
my %types = map { $_ => 1 } AI::TensorFlow::Libtensorflow::Lib->ffi->types;
my %part;
@part{qw(todo done)} = part { exists $types{$_} } uniq map { $_->{name} } @data;
use DDP; p %part;
}
method check_functions($first_arg = undef) {
my $functions = AI::TensorFlow::Libtensorflow::Lib->ffi->_attached_functions;
my @dupes = map { $_->[0]{c} }
grep { @$_ != 1 } values $functions->%*;
die "Duplicated functions @dupes" if @dupes;
my @data = $self->fdecl_data->@*;
say <<~STATS;
Statistics:
==========
t/05_session_run.t view on Meta::CPAN
-0.4809832, -0.3770838, 0.1743573, 0.7720509, -0.4064746, 0.0116595, 0.0051413, 0.9135732, 0.7197526, -0.0400658, 0.1180671, -0.6829428,
-0.4810135, -0.3772099, 0.1745346, 0.7719303, -0.4066443, 0.0114614, 0.0051195, 0.9135003, 0.7196983, -0.0400035, 0.1178188, -0.6830465,
-0.4809143, -0.3773398, 0.1746384, 0.7719052, -0.4067171, 0.0111654, 0.0054433, 0.9134697, 0.7192584, -0.0399981, 0.1177435, -0.6835230,
-0.4808300, -0.3774327, 0.1748246, 0.7718700, -0.4070232, 0.0109549, 0.0059128, 0.9133330, 0.7188759, -0.0398740, 0.1181437, -0.6838635,
-0.4807833, -0.3775733, 0.1748378, 0.7718275, -0.4073670, 0.0107582, 0.0062978, 0.9131795, 0.7187147, -0.0394935, 0.1184392, -0.6840039,
);
$p_data->reshape(1,5,12);
my $input_tensor = AI::TensorFlow::Libtensorflow::Tensor->New(
FLOAT, [ $p_data->dims ], $p_data->get_dataref,
sub { undef $p_data }
);
my $output_op = Output->New({
oper => $graph->OperationByName( 'output_node0'),
index => 0 } );
die "Can not init output op" unless $output_op;
my $status = AI::TensorFlow::Libtensorflow::Status->New;
my $options = AI::TensorFlow::Libtensorflow::SessionOptions->New;
my $session = AI::TensorFlow::Libtensorflow::Session->New($graph, $options, $status);
die "Could not create session" unless $status->GetCode == AI::TensorFlow::Libtensorflow::Status::OK;
my @output_values;
my $target_op_a = undef;
$session->Run(
undef,
[$input_op ], [$input_tensor],
[$output_op], \@output_values,
undef,
undef,
$status
);
die "run failed" unless $status->GetCode == AI::TensorFlow::Libtensorflow::Status::OK;
my $output_tensor = $output_values[0];
my $output_pdl = zeros(float,( map $output_tensor->Dim($_), 0..$output_tensor->NumDims-1) );
memcpy scalar_to_pointer( ${$output_pdl->get_dataref} ),
scalar_to_pointer( ${$output_tensor->Data} ),
t/lib/TF_Utils.pm view on Meta::CPAN
$self->_targets( \@data );
}
sub Run {
my ($self, $s) = @_;
if( @{ $self->_inputs } != @{ $self->_input_values } ) {
die "Call SetInputs() before Run()";
}
$self->session->Run(
undef,
$self->_inputs, $self->_input_values,
$self->_outputs, $self->_output_values,
$self->_targets,
undef,
$s
);
}
sub output_tensor { my ($self, $i) = @_; $self->_output_values->[$i] }
}
sub BinaryOpHelper {
my ($op_name, $l, $r,
$graph, $s, $name,
t/upstream/CAPI/003_Tensor.t view on Meta::CPAN
# It should not be called in this case because aligned_alloc() is used.
ok ! $deallocator_called, 'deallocator not called yet';
is $t->Type, 'FLOAT', 'FLOAT TF_Tensor';
is $t->NumDims, 2, '2D TF_Tensor';
is $t->Dim(0), $dims[0], 'dim 0';
is $t->Dim(1), $dims[1], 'dim 1';
is $t->ByteSize, $num_bytes, 'bytes';
is scalar_to_pointer(${$t->Data}), scalar_to_pointer($values),
'data at same pointer address';
undef $t;
ok $deallocator_called, 'deallocated';
};
done_testing;
t/upstream/CAPI/004_MalformedTensor.t view on Meta::CPAN
use Test2::V0;
use lib 't/lib';
use TF_TestQuiet;
use aliased 'AI::TensorFlow::Libtensorflow';
use aliased 'AI::TensorFlow::Libtensorflow::Tensor';
use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT);
subtest "(CAPI, MalformedTensor)" => sub {
my $noop_dealloc = sub {};
my $t = Tensor->New(FLOAT, [], \undef, $noop_dealloc);
ok ! defined $t, 'No data passed in so no tensor created';
};
done_testing;
t/upstream/CAPI/006_MaybeMove.t view on Meta::CPAN
my $pointer = shift;
AI::TensorFlow::Libtensorflow::Lib::_Alloc->_tf_aligned_free($pointer);
$deallocator_called = 1;
});
ok !$deallocator_called, 'not deallocated';
my $o = $t->MaybeMove;
is $o, U(), 'it is unsafe to move memory TF might not own';
undef $t;
ok $deallocator_called, 'deallocated'
};
done_testing;
t/upstream/CAPI/014_SetShape.t view on Meta::CPAN
my $feed_out_0 = Output->New({ oper => $feed, index => 0 });
my $num_dims;
note 'Fetch the shape, it should be completely unknown';
$num_dims = $graph->GetTensorNumDims($feed_out_0, $s);
TF_Utils::AssertStatusOK($s);
is $num_dims, -1, 'Dims are unknown';
note 'Set the shape to be unknown, expect no change';
$graph->SetTensorShape($feed_out_0, undef, $s);
$num_dims = $graph->GetTensorNumDims($feed_out_0, $s);
TF_Utils::AssertStatusOK($s);
is $num_dims, -1, 'Dims are still unknown';
note 'Set the shape to be 2 x Unknown';
my $dims = [2, -1];
$graph->SetTensorShape( $feed_out_0, $dims, $s);
TF_Utils::AssertStatusOK($s);
note 'Fetch the shape and validate it is 2 by -1.';
t/upstream/CAPI/014_SetShape.t view on Meta::CPAN
note 'Fetch and see that the new value is returned.';
$returned_dims = $graph->GetTensorShape( $feed_out_0, $s );
TF_Utils::AssertStatusOK($s);
is $returned_dims, $dims, "Got shape [ @$dims ]";
note q{
Try to set 'unknown' with unknown rank on the shape and see that
it doesn't change.
};
$graph->SetTensorShape($feed_out_0, undef, $s);
TF_Utils::AssertStatusOK($s);
$num_dims = $graph->GetTensorNumDims( $feed_out_0, $s );
$returned_dims = $graph->GetTensorShape( $feed_out_0, $s );
TF_Utils::AssertStatusOK($s);
is $num_dims, 2, 'unchanged numdims';
is $returned_dims, [2,3], 'dims still [2 3]';
note q{
Try to set 'unknown' with same rank on the shape and see that
it doesn't change.
t/upstream/CAPI/018_ImportGraphDef.t view on Meta::CPAN
TF_Utils::Neg( $oper, $graph, $s );
TF_Utils::AssertStatusOK($s);
ok $graph->OperationByName( 'neg' ), 'got neg operation from graph';
note 'Export to a GraphDef.';
my $graph_def = AI::TensorFlow::Libtensorflow::Buffer->New;
$graph->ToGraphDef( $graph_def, $s );
TF_Utils::AssertStatusOK($s);
note 'Import it, with a prefix, in a fresh graph.';
undef $graph;
$graph = AI::TensorFlow::Libtensorflow::Graph->New;
my $opts = AI::TensorFlow::Libtensorflow::ImportGraphDefOptions->New;
$opts->SetPrefix('imported');
$graph->ImportGraphDef($graph_def, $opts, $s);
TF_Utils::AssertStatusOK($s);
ok my $scalar = $graph->OperationByName('imported/scalar'), 'imported/scalar';
ok my $feed = $graph->OperationByName('imported/feed'), 'imported/feed';
ok my $neg = $graph->OperationByName('imported/neg'), 'imported/neg';
t/upstream/CAPI/018_ImportGraphDef.t view on Meta::CPAN
is $scalar, $empty_control_outputs, 'scalar control outputs';
is $feed, $empty_control_inputs, 'feed control inputs';
is $feed, $empty_control_outputs, 'feed control outputs';
is $neg, $empty_control_inputs, 'neg control inputs';
is $neg, $empty_control_outputs, 'neg control outputs';
note q|Import it again, with an input mapping, return outputs, and a return
operation, into the same graph.|;
undef $opts;
$opts = AI::TensorFlow::Libtensorflow::ImportGraphDefOptions->New;
$opts->SetPrefix('imported2');
$opts->AddInputMapping( 'scalar', 0, $TFOutput->coerce([$scalar=>0]));
$opts->AddReturnOutput('feed', 0);
$opts->AddReturnOutput('scalar', 0);
is $opts->NumReturnOutputs, 2, 'num return outputs';
$opts->AddReturnOperation('scalar');
is $opts->NumReturnOperations, 1, 'num return operations';
my $results = $graph->ImportGraphDefWithResults( $graph_def, $opts, $s );
TF_Utils::AssertStatusOK($s);
t/upstream/CAPI/018_ImportGraphDef.t view on Meta::CPAN
note 'Check return operation';
my $return_opers = $results->ReturnOperations;
is $return_opers, array {
item 0 => object {
# not remapped
call Name => $scalar2->Name;
};
end;
}, 'return opers';
undef $results;
note 'Import again, with control dependencies, into the same graph.';
undef $opts;
$opts = AI::TensorFlow::Libtensorflow::ImportGraphDefOptions->New;
$opts->SetPrefix("imported3");
$opts->AddControlDependency($feed);
$opts->AddControlDependency($feed2);
$graph->ImportGraphDef($graph_def, $opts, $s);
TF_Utils::AssertStatusOK($s);
ok my $scalar3 = $graph->OperationByName("imported3/scalar"), "imported3/scalar";
ok my $feed3 = $graph->OperationByName("imported3/feed"), "imported3/feed";
ok my $neg3 = $graph->OperationByName("imported3/neg"), "imported3/neg";
t/upstream/CAPI/018_ImportGraphDef.t view on Meta::CPAN
end;
}, 'scalar3 control inputs';
is $feed3->GetControlInputs, array {
item 0 => object { call Name => $feed->Name };
item 1 => object { call Name => $feed2->Name };
end;
}, 'feed3 control inputs';
note 'Export to a graph def so we can import a graph with control dependencies';
undef $graph_def;
$graph_def = AI::TensorFlow::Libtensorflow::Buffer->New;
$graph->ToGraphDef( $graph_def, $s );
TF_Utils::AssertStatusOK($s);
note 'Import again, with remapped control dependency, into the same graph';
undef $opts;
$opts = AI::TensorFlow::Libtensorflow::ImportGraphDefOptions->New;
$opts->SetPrefix("imported4");
$opts->RemapControlDependency("imported/feed", $feed );
$graph->ImportGraphDef($graph_def, $opts, $s);
TF_Utils::AssertStatusOK($s);
ok my $scalar4 = $graph->OperationByName("imported4/imported3/scalar"),
"imported4/imported3/scalar";
ok my $feed4 = $graph->OperationByName("imported4/imported2/feed"),
"imported4/imported2/feed";
note q|Check that imported `imported3/scalar` has remapped control dep from
original graph and imported control dep|;
is $scalar4->GetControlInputs, array {
item object { call Name => $feed->Name };
item object { call Name => $feed4->Name };
end;
}, 'scalar4 control inputs';
undef $opts;
undef $graph_def;
note 'Can add nodes to the imported graph without trouble.';
TF_Utils::Add( $feed, $scalar, $graph, $s );
TF_Utils::AssertStatusOK($s);
};
done_testing;
t/upstream/CAPI/019_ImportGraphDef_WithReturnOutputs.t view on Meta::CPAN
TF_Utils::Neg( $oper, $graph, $s );
TF_Utils::AssertStatusOK($s);
ok $graph->OperationByName("neg"), "get neg";
note 'Export to a GraphDef.';
my $graph_def = AI::TensorFlow::Libtensorflow::Buffer->New;
$graph->ToGraphDef( $graph_def, $s );
TF_Utils::AssertStatusOK($s);
note 'Import it in a fresh graph with return outputs.';
undef $graph;
$graph = AI::TensorFlow::Libtensorflow::Graph->New;
my $opts = AI::TensorFlow::Libtensorflow::ImportGraphDefOptions->New;
$opts->AddReturnOutput('feed', 0);
$opts->AddReturnOutput('scalar', 0);
is $opts->NumReturnOutputs, 2, '2 return outputs';
my $return_outputs = $graph->ImportGraphDefWithReturnOutputs(
$graph_def, $opts, $s
);
TF_Utils::AssertStatusOK($s);
t/upstream/CAPI/020_ImportGraphDef_MissingUnusedInputMappings.t view on Meta::CPAN
TF_Utils::Neg( $oper, $graph, $s );
TF_Utils::AssertStatusOK($s);
ok $graph->OperationByName('neg'), 'neg';
note 'Export to a GraphDef.';
my $graph_def = AI::TensorFlow::Libtensorflow::Buffer->New;
$graph->ToGraphDef( $graph_def, $s );
TF_Utils::AssertStatusOK($s);
note 'Import it in a fresh graph.';
undef $graph;
$graph = AI::TensorFlow::Libtensorflow::Graph->New;
my $opts = AI::TensorFlow::Libtensorflow::ImportGraphDefOptions->New;
$graph->ImportGraphDef($graph_def, $opts, $s);
TF_Utils::AssertStatusOK($s);
my $scalar = $graph->OperationByName('scalar');
note 'Import it in a fresh graph with an unused input mapping.';
undef $opts;
$opts = AI::TensorFlow::Libtensorflow::ImportGraphDefOptions->New;
$opts->SetPrefix("imported");
$opts->AddInputMapping("scalar", 0, $TFOutput->coerce([$scalar, 0]));
$opts->AddInputMapping("fake", 0, $TFOutput->coerce([$scalar, 0]));
my $results = $graph->ImportGraphDefWithResults($graph_def, $opts, $s);
TF_Utils::AssertStatusOK($s);
note 'Check unused input mappings';
is my $srcs = $results->MissingUnusedInputMappings, array {
item [ 'fake', 0 ];
t/upstream/CAPI/026_SessionPRun.t view on Meta::CPAN
note q{Setup a session and a partial run handle. The partial run will allow
computation of A + 2 + B in two phases (calls to TF_SessionPRun):
1. Feed A and get (A+2)
2. Feed B and get (A+2)+B};
my $opts = AI::TensorFlow::Libtensorflow::SessionOptions->New;
my $sess = AI::TensorFlow::Libtensorflow::Session->New($graph, $opts, $s);
my @feeds = $TFOutput->map([ $op_a => 0 ], [$op_b => 0]);
my @fetches = $TFOutput->map([$plus2 => 0], [$plusB => 0]);
my $handle = $sess->PRunSetup( \@feeds, \@fetches, undef, $s);
note 'Feed A and fetch A + 2.';
my @feeds1 = $TFOutput->map( [$op_a => 0] );
my @fetches1 = $TFOutput->map( [$plus2 => 0] );
my @feedValues1 = ( TF_Utils::Int32Tensor(1) );
my @fetchValues1;
$sess->PRun( $handle,
\@feeds1, \@feedValues1,
\@fetches1, \@fetchValues1,
undef,
$s );
TF_Utils::AssertStatusOK($s);
is unpack("l", ${ $fetchValues1[0]->Data }), 3,
'(A := 1) + Const(2) = 3';
undef @feedValues1;
undef @fetchValues1;
note 'Feed B and fetch (A + 2) + B.';
my @feeds2 = $TFOutput->map( [$op_b => 0] );
my @fetches2 = $TFOutput->map( [$plusB => 0] );
my @feedValues2 = ( TF_Utils::Int32Tensor(4) );
my @fetchValues2;
$sess->PRun($handle,
\@feeds2, \@feedValues2,
\@fetches2, \@fetchValues2,
undef,
$s);
TF_Utils::AssertStatusOK($s);
is unpack("l", ${ $fetchValues2[0]->Data }), 7,
'( (A := 1) + Const(2) ) + ( B := 4 ) = 7';
undef $handle;
$sess->Close($s);
TF_Utils::AssertStatusOK($s);
undef $graph;
undef $s;
};
done_testing;
t/upstream/CAPI/030_SavedModelNullArgsAreValid.t view on Meta::CPAN
"tensorflow", "cc", "saved_model", "testdata",
"half_plus_two", "00000123"
);
my $opt = AI::TensorFlow::Libtensorflow::SessionOptions->New;
my $s = AI::TensorFlow::Libtensorflow::Status->New;
my @tags = ('serve');
my $graph = AI::TensorFlow::Libtensorflow::Graph->New;
note 'NULL run_options and meta_graph_def should work.';
is my $session = AI::TensorFlow::Libtensorflow::Session->LoadFromSavedModel(
$opt, undef, "$saved_model_dir", \@tags, $graph, undef, $s
), D();
TF_Utils::AssertStatusOK($s);
$session->Close($s);
TF_Utils::AssertStatusOK($s);
undef $session;
};
done_testing;
t/upstream/CAPI/032_TestBitcastFrom_Reshape.t view on Meta::CPAN
subtest "(CAPI, TestBitcastFrom_Reshape)" => sub {
my @dims = (2, 3);
is my $t_a = AI::TensorFlow::Libtensorflow::Tensor->Allocate(
UINT64, \@dims
), object {
call ElementCount => 6;
call ByteSize => 6 * UINT64->Size;
}, '2x3 TFTensor';
is my $t_b = AI::TensorFlow::Libtensorflow::Tensor->Allocate(
UINT64, undef
), object {
call ElementCount => 1;
call ByteSize => UINT64->Size;
}, 'scalar TFTensor';
my @new_dims = (3, 2);
my $status = AI::TensorFlow::Libtensorflow::Status->New;
$t_a->BitcastFrom( UINT64, $t_b, \@new_dims, $status );
TF_Utils::AssertStatusOK($status);
t/upstream/CAPI/037_TestTensorNonScalarBytesAllocateDelete.t view on Meta::CPAN
my $data_i = $ffi->cast('opaque', 'TF_TString', $data_i_ptr );
$data_i->Init;
$data_i->{owner} = $t; # do not want to free the pointer
# The following input string length is large enough to make sure that
# copy to tstring in large mode.
$data_i->Copy(
"This is the " . ($i + 1) . "th. data element\n"
);
}
undef $t;
pass 'Created TF_STRING tensor and deallocated';
};
done_testing;