toco_from_protos: command not found

Solution 1:

The problem

Tensorflow calls to a specific binary file to convert the .pb file (stored by protobuf) in a tflite model. The binary file is 'toco_from_protos', and the error message suggests that the shell interpreter ('/bin/sh' in this case) is not able to find the binary file ('toco_from_proto').

You need to include the path to 'toco_from_proto' file in the PATH environment variable.

How to do this

First, check if the file exists. You can use the command 'locate' for example:

$ locate toco_from_proto
/home/user/anaconda3/envs/tensorflow/bin/toco_from_protos
/home/user/anaconda3/envs/tensorflow/lib/python3.6/site-packages/tensorflow/lite/toco/python/toco_from_protos.py
/home/user/anaconda3/envs/tensorflow/lib/python3.6/site-packages/tensorflow/lite/toco/python/__pycache__/toco_from_protos.cpython-36.pyc

In my case, I am using Anaconda to manage the environments. Thus, the binary is in the binary path ('bin' folder) of the environment container ('tensorflow' in this case).

To ensure the correct execution of the binary, include the path to 'toco_from_protos' file inside PATH environment variable. If you are using a Linux based system, you can do something like:

$ export PATH=$PATH:/home/user/anaconda3/envs/tensorflow/bin

If you are using an IDE program (e.g. Pycharm), you can call the IDE run script using the same console you used to export the PATH variable. For example:

$ export PATH=$PATH:/home/user/anaconda3/envs/tensorflow/bin
$ /opt/pycharm-community-2018.1.4/bin/pycharm.sh

The new PATH value change remains only in that console window, so if you want to make the change persistent, include the export sentence inside '~/.bashrc' file.

Solution 2:

I had the same issue and solved by using an official docker image, host machine has a fresh Ubuntu 18.04.

docker run --runtime=nvidia -v /path/to/my/project:/mapped/docker/path -it tensorflow/tensorflow:latest-gpu bash

Then run the conversion script inside docker:

model = load_model() # keras model
output_names = [node.op.name for node in model.outputs]
input_names = [node.op.name for node in model.inputs]
with tf.keras.backend.get_session() as sess:
    sess.run(tf.global_variables_initializer())
    frozen_def = tf.graph_util.convert_variables_to_constants(sess, sess.graph_def, output_names)
    converter = tf.lite.TFLiteConverter.from_session(sess, model.inputs, model.outputs)
    tflite_model = converter.convert()
    open("converted_model.tflite", "wb").write(tflite_model)

At the time of writing tensorflow/tensorflow:latest-gpu is version 1.13.1