Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I set the value of an input tensor in c++?

I'm trying to run a sample through a pre trained model on ios. session->Run() takes as input a tensor to my understanding. I have initialized a tensor, but how do i set it's value? I don't have much experience using C++.

I have successfully created a test model that accepts 3 dimensional tensor of shape {1, 1, 10}.

I pulled the following line of code from Tensorflow's simple example to create the input tensor.

https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/ios_examples/simple/RunModelViewController.mm#L189

tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({1,1,10}));

From here, I cannot figure out how I would set the data of input_tensor. I would like to set the tensor to something like {{{.0, .1, .2, .3, .4, .5, .6, .7, .8, .9}}}

like image 327
agsolid Avatar asked Aug 09 '16 17:08

agsolid


2 Answers

I had a similar problem and was trying to set the tensor input values in C++ for a model trained in Python. The model is a simple NN with one hidden layer to learn to calculate the XOR operation.

I first created an output graph file with both the graph structure and the model parameters by following steps 1-4 of this nice post: https://medium.com/@hamedmp/exporting-trained-tensorflow-models-to-c-the-right-way-cf24b609d183#.j4l51ptvb.

Then in C++ (the TensorFlow iOS simple example), I used the following code:

tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({4,2}));

// input_tensor_mapped is an interface to the data of a tensor and used to copy data into the tensor
auto input_tensor_mapped = input_tensor.tensor<float, 2>();

// set the (4,2) possible input values for XOR
input_tensor_mapped(0, 0) = 0.0;
input_tensor_mapped(0, 1) = 0.0;
input_tensor_mapped(1, 0) = 0.0;
input_tensor_mapped(1, 1) = 1.0;
input_tensor_mapped(2, 0) = 1.0;
input_tensor_mapped(2, 1) = 0.0;
input_tensor_mapped(3, 0) = 1.0;
input_tensor_mapped(3, 1) = 1.0;

tensorflow::Status run_status = session->Run({{input_layer, input_tensor}},
                                             {output_layer}, {}, &outputs);

After this, GetTopN(output->flat<float>(), kNumResults, kThreshold, &top_results); returns the same 4 values (0.94433498, 0.94425952, 0.06565627, 0.05823805), as in my Python test code for XOR after the model is trained, in top_results.

So if your tensor's shape is {1,1,10}, you can set the values as follows:

auto input_tensor_mapped = input_tensor.tensor<float, 3>();
input_tensor_mapped(0, 0, 0) = 0.0;
input_tensor_mapped(0, 0, 1) = 0.1;
....
input_tensor_mapped(0, 0, 9) = 0.9;

Credit: the answer at How do I pass an OpenCV Mat into a C++ Tensorflow graph? is very helpful.

like image 152
Jeff Tang Avatar answered Sep 28 '22 11:09

Jeff Tang


If you want to directly set the value of a tensor you can use few utilities functions provided by the Tensor interface. For the most common linear access you can use flat<T>.

From tensor_test

void ExpectClose(const Tensor& x, const Tensor& y, double atol, double rtol) {
  auto Tx = x.flat<T>();
  auto Ty = y.flat<T>();
  for (int i = 0; i < Tx.size(); ++i) {
    if (!IsClose(Tx(i), Ty(i), atol, rtol)) {
      LOG(ERROR) << "x = " << x.DebugString();
      LOG(ERROR) << "y = " << y.DebugString();
      LOG(ERROR) << "atol = " << atol << " rtol = " << rtol
                 << " tol = " << atol + rtol * std::fabs(Tx(i));
      EXPECT_TRUE(false) << i << "-th element is not close " << Tx(i) << " vs. "
                         << Ty(i);
    }
  }
}

to create a tensor you can use one of the constructors

Tensor(DT_FLOAT, new TensorShape(..))

If you want to set the value of a tensor or a placeholder at run time you need to pass it through the Run() interface:

  Status run_status = session->Run({{input_layer, resized_tensor}},
                                   {output_layer}, {}, &outputs);
  if (!run_status.ok()) {
    LOG(ERROR) << "Running model failed: " << run_status;
    return -1;
  }

If you want to have a predefine value of a tensor you can use the Const constructor

tensorflow::ops::Const({input_height, input_width})
like image 40
fabrizioM Avatar answered Sep 28 '22 10:09

fabrizioM