Tensorflow gerando model para dispositivo móvel

Se você não conhece Tensorflow, recomendo fortemente que antes leia esse post. Nesse post geramos um model personaizado que reconhece padrões em imagens. Mas para que esse reconhecimento de imagem funcione no dispositivo móvel, devemos fazer algumas alterações no model.

Podemos utilizar um model do Tensorflow ou um model customizado. Os models Tensorflow que já existem são: inception-v1 e inception-v3. Quando criamos nosso model personalizado como foi mostrado nesse post, o model não é treinado do zero. Ele é treinado a partir de um model do Tensorflow pré-existente. 

Por padrao o Tensorfow utiliza o inception-v3 para isso. Se quiser alterar o model base, basta passsar o parametro

--architecture

na hora de gerar o model. Mas não é mais possível utilizar o model inception-v1 para criar models personalizados.

No final das contas isso serve para fazer atalhos no processo de treinamento do nosso model. Por isso o nome do script que usamos para gerar o model é retrain.py. Isso por que estamos retreinando um model que foi treinado anteriormente. Estamos adicionado uma nova camada no modelo de treinamento. Antes de começar, temos que gerar novamente o model. Mas dessa vez precisamos utilizar outra imagem do docker. Isso por que o model que geramos com a imagem oficial não vai funcionar no dispositivo móvel.

Essa imagem foi criada por danjarvis. Na página do docker hub ele mesmo diz que esse container é baseado no container oficial que utilizamos nesse post mas com outras instalações voltadas para android

Imagem

Para subir o container com a nova imagem vamos rodar esse comando no terminal do docker:

docker run -it -v ~/projects/dump/tf_files/:/tf_files/ danjarvis/tensorflow-android:1.0.0

Estou utilizando a pasta star_wars criada nesse post

IMPORTNATE: Se tentar utilizar o model star_wars_graph.pb gerado a partir container docker tensorflow oficial, vai dá esse erro:

TF initialization failed

Depois que terminar de baixar a imagem danjarvis/tensorflow-android e entrar no container, vamos rodar esse comando dentro do container para gerar o model personalizado:

python /tensorflow/tensorflow/examples/image_retraining/retrain.py \
--bottleneck_dir=/tf_files/bottlenecks \
--how_many_training_steps 500 \
--model_dir=/tf_files_inception  \
--output_graph=/tf_files/star_wars_graph.pb \
--output_labels=/tf_files/star_wars_labels.txt \
--image_dir /tf_files/star_wars
 

Quando o processo terminar, vai ser gerado um novo arquivo star_wars_graph.pb. É esse arquivo que deve ser carregado no dispositivo móvel.

A grande questão aqui é que no dispositivo móvel só funciona modelos inception-v1.

E se tentar utilizar o model star_wars_graph.pb que acabamos de gerar no container danjarvis/tensorflow-android baseado no inception-v3 do Tensorflow vai dá esse erro:

Op BatchNormWithGlobalNormalization is not avaliable on GraphDef version 21. it has been removed in version 9. Use tf.nn.batch_normalization().

Não é mais possível gerar modelos customizados com a arquitetura inception-v1. Mesmo assim o app Android oficial de exemplo usa inception-v1. Nesse arquivo do projeto de exemplo Android diz o que temos que fazer para funcionar com inception-v3 

A partir da linha 52:

// These are the settings for the original v1 Inception model. If you want to
// use a model that's been produced from the TensorFlow for Poets codelab,
// you'll need to set IMAGE_SIZE = 299, IMAGE_MEAN = 128, IMAGE_STD = 128,
// INPUT_NAME = "Mul", and OUTPUT_NAME = "final_result".
// You'll also need to update the MODEL_FILE and LABEL_FILE paths to point to
// the ones you produced.
//
// To use v3 Inception model, strip the DecodeJpeg Op from your retrained
// model first:
//
// python strip_unused.py \
// --input_graph=<retrained-pb-file> \
// --output_graph=<your-stripped-pb-file> \
// --input_node_names="Mul" \
// --output_node_names="final_result" \
// --input_binary=true

Nesse comentário diz que temos que usar esse script strip_unused.py que está nesse mesmo repositório na pasta tensorflow/tensorflow/python/tools.

Esse script serve para revomer DecodeJpeg Op do modelo retreinado. 

Beleza! Faz todo sentido. Vi vários posts na internet dizendo a mesma coisa... Sò que não. Testei várias vezes e o erro continua:

Op BatchNormWithGlobalNormalization is not avaliable on GraphDef version 21. it has been removed in version 9. Use tf.nn.batch_normalization().

Depois de muitos testes, o que funcionou foi segir os passos 4 e 5 desse code lab:

python /tensorflow/tensorflow/python/tools/optimize_for_inference.py \
--input=/tf_files/star_wars_graph.pb \
--output=/tf_files/star_wars_graph_optimized.pb \
--frozen_graph=True \
--input_names=Mul \
--output_names=final_result

Depois esse:

python /tensorflow/tensorflow/tools/quantization/quantize_graph.py \
--input=/tf_files/star_wars_graph_optimized.pb \
--output=/tf_files/star_wars_rounded_graph.pb \
--output_node_names=final_result \
--mode=weights_rounded

IMPORTANTE: Esses dois passos devem ser feitos para otimizar o model gerado no container docker a partir da imagem danjarvis/tensorflow-androidSe o model for gerado na imagem gcr.io/tensorflow/tensorflow vai continuar dando erro quando executado no dispositivo móvel mesmo seguindo esses dois passos.

Agora sim. O arquivo que devemos utilizar no dispositivo móvel é star_wars_rounded_graph.pb.

Depois desse processo, o arquivo star_wars_rounded_graph.pb continua com o mesmo tamanho mas depois de compactado o tamanho fica bastante reduzido. Em torno de 25MB. Isso acontece por que o quantize_graph.py otimizou o model para ter tamanho reduzido quando for compactado.

Esse tamanho reduzido facilita muito quando o arquivo for baixado pelo app. 

Compactei esse arquivo junto com retrained_labels.txt em um zip e enviei para esse endereço

Nesse post mostramos como utilizar esse model em um aplicativo cordova. 

Índices de busca:

  • [Resolvido] TF initialization failed
  • [Resolvido] Op BatchNormWithGlobalNormalization is not avaliable...
  • Tensorflow gerando model para IOS
  • Tensorflow gerando model para Android
  • Tensorflow gerando model para Cordova

Comentários

 

Quem Sou

Graduado em ADS (Análise e desenvolvimento de sistemas).

Não sou "devoto" de nenhuma linguagem de programação. Procuro aproveitar o melhor de cada uma de acordo com a necessidade do projeto. Prezo por uma arquitetura bem feita, código limpo, puro e simples! 

anuncio atendente