Sunday, March 18, 2018

Use keras' Classifier model on android app

At first, we need to train a model (classifier) and save the model with learned weights. We will transform it to tensorflow's .pb file to use it on android app.

Install Keras.
Install Keras on Linux mint
Install Keras on windows

You should test keras if it works in your environment.
Install Keras and test deep learning

Now you can use Keras. We will train and create a Keras' model of classifier. (You can make other models except classifier also. But maybe classifier is the easiest.) Create a Keras' model with learned weights like this. This would generate a .hdf5 file. I have made animal_model.hdf5 by training a model of classification of cats and dogs.

We will transform the model to .pb file of tensorflow. To do so, we will use this open source: keras_to_tensorflow
Clone the project in your current directory:
$ git clone https://github.com/amir-abdi/keras_to_tensorflow
$ cd ./keras_to_tensorflow

Then copy and paste the Keras' model file (.hdf5) to the folder of "keras_to_tensorflow".

Run this command:
$ python3.5 keras_to_tensorflow.py -input_model_file ./animal_model.hdf5

The .pb file will be generated like this:

We will use the model in android with tensorflow. At first, try demo apps and see if they work in your environment: How to use tensorflow demo apps on android

In "assets" folder of tensorflow android example, add the .pb file you have generated beforehand and label.txt. What's label.txt? It is just a text file in which categories of the model are written:
cat
dog

assets folder

.pb file and label.txt

Change the file path of ClassifierActivity.java.

And change the values of "input", "output", "IMAGE_SIZE", "IMAGE_MEAN", "IMAGE_STD".

You can get the name of "input" and "output" like this:
>>> import tensorflow as tf
>>> gf = tf.GraphDef()
>>> gf.ParseFromString(open('/your/path/to/the/.pb/file','rb').read())
>>> [n.name + '=>' +  n.op for n in gf.node if n.op in ( 'Softmax','Placeholder')]

The result:
['Mul=>Placeholder', 'final_result=>Softmax']
Mul is input, final_result is output.
Or use summarize_graph tool. (See "Optimization" section about how to use it)

You can get the "image_size" in the python file of Keras which you used for training:
these numbers "200" mean the image size.


Start the application.

Your model will be used by tensorflow on android like this :)  


Optimization


Use optimization_for_inference.py to optimize the .pb file. You can find it in tensorflow project:
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/tools/optimize_for_inference.py

You need bazel for the command:
https://docs.bazel.build/versions/master/install.html

According to the tensorflow page, if we suppose you cloned tensorflow in Documents directory, an example of command-line usage is:
$ cd $HOME/Documents
$ bazel build tensorflow/python/tools:optimize_for_inference && \
$ bazel-bin/tensorflow/python/tools/optimize_for_inference \
--input=frozen_inception_graph.pb \
--output=optimized_inception_graph.pb \
--frozen_graph=True \
--input_names=Mul \
--output_names=softmax
Note: you need to check what the output/input node names are by summarize_graph tool and provide them as input_names/output_names of the arguments of optimize_for_inference tool.

Suppose you cloned tensorflow in Documents directory, summarize_graph tool can be used like this:
$ cd $HOME/Documents
$ bazel build tensorflow/tools/graph_transforms:summarize_graph
$ bazel-bin/tensorflow/tools/graph_transforms/summarize_graph --in_graph=tensorflow_inception_graph.pb