This PR completes the entire prediction pipeline. If you have a graph you can now completely generate predictions. Tensor allocation functions have also been added which are used for holding output tensors which only obtain their values after a session is run successfully.
To exemplify the working of the entire prediction pipeline, I am going to use the simple toy graph created by the script in examples/ called graphdef_create.py . Upon running the script you should have a graph definition file called graphdef.pb. You can also download this file stored in my Dropbox here.
Then I would recommend going through the graphdef_create.py file to get an idea of what the operations are. The code basically works like a very simple matrix multiplication of some predefined weights with the input and then the addition of the biases. Ideally the weights should be ascertained through training but since this is a toy example they are predefined (look here in the code).
The more important thing to notice in the graphdef_create.py file are the operations where the input is fed and where the output is obtained. It is important to know the names of these operations as when we perform Inference the input will be fed to that named input operation and the output will be obtained similarly. The names of the operations are required to run sessions. In our toy example, the input operation is assigned the name "input" (look here in the code) and the output operation is assigned the name "output" (look here in the code).
Now in Tensorflex, the Inference would go something like this:
First load the graph and look to see all the operations are correct. You will see "input" and "output" somewhere as mentioned before.
iex(1)> {:ok, graph} = Tensorflex.read_graph "graphdef.pb"
2018-06-04 00:32:53.993446: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA
{:ok, #Reference<0.1321508712.421658628.225797>}
- Then create the input tensors. First create matrices to house the tensor data as well as it's dimensions. As an example, let's say we set our input to be a 3x3 tensor with the first inputs all 1.0, second row to be 2.0, and third to be 3.0. The tensor is a `float32` tensor created using the `float32_tensor` function.
```elixir
iex(3)> in_vals = Tensorflex.create_matrix(3,3,[[1.0,1.0,1.0],[2.0,2.0,2.0],[3.0,3.0,3.0]])
#Reference<0.1321508712.421658628.225826>
iex(4)> in_dims = Tensorflex.create_matrix(1,2,[[3,3]])
#Reference<0.1321508712.421658628.225834>
iex(5)> {:ok, input_tensor} = Tensorflex.float32_tensor(in_vals, in_dims)
{:ok, #Reference<0.1321508712.421658628.225842>}
Now to create the output tensor, since we know the matrix operations, the output will be a 3x2 tensor. We set the dimensions appropriately. Moreover, since we do not yet have the output values (we can only get them after the session is run), we will use the float32_tensor_alloc function instead of float32_tensor.
Finally, we need to run a session to get the output answers from sending the input tensors through the graph. We can see that the answer we get is exactly what we get when we do the matrix multiplications of the inputs with the weights and the addition of the biases. Also, the run_session function takes 5 inputs: the graph definition, the input tensor, the output tensor, the name of the input operation and the output operation. This is why knowing the names of your input and output operations is important.
This PR completes the entire prediction pipeline. If you have a graph you can now completely generate predictions. Tensor allocation functions have also been added which are used for holding output tensors which only obtain their values after a session is run successfully.
To exemplify the working of the entire prediction pipeline, I am going to use the simple toy graph created by the script in
examples/
calledgraphdef_create.py
. Upon running the script you should have a graph definition file calledgraphdef.pb
. You can also download this file stored in my Dropbox here.Then I would recommend going through the
graphdef_create.py
file to get an idea of what the operations are. The code basically works like a very simple matrix multiplication of some predefined weights with the input and then the addition of the biases. Ideally the weights should be ascertained through training but since this is a toy example they are predefined (look here in the code).The more important thing to notice in the
graphdef_create.py
file are the operations where the input is fed and where the output is obtained. It is important to know the names of these operations as when we perform Inference the input will be fed to that named input operation and the output will be obtained similarly. The names of the operations are required to run sessions. In our toy example, the input operation is assigned the name "input" (look here in the code) and the output operation is assigned the name "output" (look here in the code).Now in Tensorflex, the Inference would go something like this:
iex(2)> Tensorflex.get_graph_ops graph ["biases", "biases/read", "weights", "weights/read", "input", "MatMul", "add", "output"]
float32_tensor_alloc
function instead offloat32_tensor
.run_session
function takes 5 inputs: the graph definition, the input tensor, the output tensor, the name of the input operation and the output operation. This is why knowing the names of your input and output operations is important.