AI-TensorFlow-Libtensorflow

 view release on metacpan or  search on metacpan

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod  view on Meta::CPAN

      die "Status $_[0]: " . $_[0]->Message
          unless $_[0]->GetCode == AI::TensorFlow::Libtensorflow::Status::OK;
      return;
  }
  AssertOK($s);

In this notebook, we will use C<PDL> to store and manipulate the ndarray data before converting it to a C<TFTensor>. The following functions help with copying the data back and forth between the two object types.

An important thing to note about the dimensions used by TensorFlow's TFTensors when compared with PDL is that the dimension lists are reversed. Consider a binary raster image with width W and height H stored in L<row-major format|https://en.wikipedia...

This difference will be explained more concretely further in the tutorial.

Future work will provide an API for more convenient wrappers which will provide an option to either copy or share the same data (if possible).

  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} ),
          $t->ByteSize;
      $pdl->upd_data;
  
      $pdl;
  }

The following is just a small helper to generate an HTML C<<< <table> >>> for output in C<IPerl>.

  use HTML::Tiny;
  
  sub my_table {
      my ($data, $cb) = @_;
      my $h = HTML::Tiny->new;
      $h->table( { style => 'width: 100%' },
          [
              $h->tr(
                  map {
                      [
                          $h->td( $cb->($_, $h) )
                      ]
                  } @$data
              )
          ]
      )
  }

This is a helper to display images in Gnuplot for debugging, but those debugging lines are commented out.

  sub show_in_gnuplot {
      my ($p) = @_;
      require PDL::Graphics::Gnuplot;
      PDL::Graphics::Gnuplot::image( square => 1, $p );
  }

=head2 Fetch the model and labels

We are going to use an L<image classification model|https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/classification/5> from TensorFlow Hub based on the MobileNet V2 architecture. We download both the model and ImageNet classification labels.

  # image_size => [width, height] (but usually square images)
  my %model_name_to_params = (
      mobilenet_v2_100_224 => {
          handle     => 'https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/classification/5',
          image_size => [ 224, 224 ],
      },
      mobilenet_v2_140_224 => {
          handle => "https://tfhub.dev/google/imagenet/mobilenet_v2_140_224/classification/5",
          image_size => [ 224, 224 ],
      },
  );
  
  my $model_name = 'mobilenet_v2_100_224';
  
  say "Selected model: $model_name : $model_name_to_params{$model_name}{handle}";

B<STREAM (STDOUT)>:

  Selected model: mobilenet_v2_100_224 : https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/classification/5

B<RESULT>:

  1

We download the model and labels to the current directory then extract the model to a folder with the name given in C<$model_base>.

  my $model_uri = URI->new( $model_name_to_params{$model_name}{handle} );
  $model_uri->query_form( 'tf-hub-format' => 'compressed' );
  my $model_base = substr( $model_uri->path, 1 ) =~ s,/,_,gr;
  my $model_archive_path = "${model_base}.tar.gz";
  
  use constant IMAGENET_LABEL_COUNT_WITH_BG => 1001;
  my $labels_uri = URI->new('https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt');
  my $labels_path = ($labels_uri->path_segments)[-1];
  
  my $http = HTTP::Tiny->new;
  
  for my $download ( [ $model_uri  => $model_archive_path ],
                     [ $labels_uri => $labels_path        ]) {
      my ($uri, $path) = @$download;
      say "Downloading $uri to $path";
      next if -e $path;
      $http->mirror( $uri, $path );
  }
  
  use Archive::Extract;
  my $ae = Archive::Extract->new( archive => $model_archive_path );
  die "Could not extract archive" unless $ae->extract( to => $model_base );
  



( run in 0.904 second using v1.01-cache-2.11-cpan-0bd6704ced7 )