Comment utiliser TensorFlow Mobile dans les applications Android

Avec TensorFlow, l’un des frameworks d’apprentissage automatique les plus populaires sur le marché actuel, vous pouvez facilement créer et former des modèles profonds, également appelés réseaux neuronaux à feed-forward profonds, capables de résoudre divers problèmes complexes, tels que la classification des images, la détection et compréhension du langage naturel. TensorFlow Mobile est une bibliothèque conçue pour vous aider à exploiter ces modèles dans vos applications mobiles..

Dans ce tutoriel, je vais vous montrer comment utiliser TensorFlow Mobile dans des projets Android Studio..

Conditions préalables

Pour pouvoir suivre ce tutoriel, vous aurez besoin de:

  • Android Studio 3.0 ou supérieur
  • TensorFlow 1.5.0 ou supérieur
  • un appareil Android exécutant l'API de niveau 21 ou supérieur
  • et une compréhension de base du cadre TensorFlow

1. Créer un modèle

Avant de commencer à utiliser TensorFlow Mobile, nous avons besoin d’un modèle TensorFlow formé. Créons-en un maintenant.

Notre modèle va être très basique. Elle se comportera comme une porte XOR, prenant deux entrées, les deux pouvant être zéro ou une, et produisant une sortie, qui sera zéro si les deux entrées sont identiques et une sinon. De plus, comme il s'agira d'un modèle profond, il comportera deux couches cachées, une avec quatre neurones et une autre avec trois neurones. Vous êtes libre de changer le nombre de couches cachées et le nombre de neurones qu'elles contiennent.

Pour que ce didacticiel soit court, au lieu d'utiliser directement les API TensorFlow de bas niveau, nous utiliserons TFLearn, un framework d'encapsulation populaire pour TensorFlow offrant des API plus intuitives et concises. Si vous ne l'avez pas déjà, utilisez la commande suivante pour l'installer dans votre environnement virtuel TensorFlow:

pip installer tflearn

Pour commencer à créer le modèle, créez un script Python nommé create_model.py, de préférence dans un répertoire vide et ouvrez-le avec votre éditeur de texte préféré.

Dans le fichier, la première chose à faire est d'importer les API TFLearn..

importer tflearn

Ensuite, nous devons créer les données d'apprentissage. Pour notre modèle simple, il n'y aura que quatre entrées et sorties possibles, qui ressembleront au contenu de la table de vérité de la porte XOR..

X = [[0, 0], [0, 1], [1, 0], [1, 1]] Y = [[0], # Sortie souhaitée pour les entrées 0, 0 [1], # Sortie souhaitée pour entrées 0, 1 [1], # Sortie souhaitée pour les entrées 1, 0 [0] # Sortie souhaitée pour les entrées 1, 1]

Il est généralement judicieux d'utiliser des valeurs aléatoires choisies dans une distribution uniforme tout en attribuant des poids initiaux à tous les neurones des couches cachées. Pour générer les valeurs, utilisez le uniforme() méthode.

poids = tflearn.initializations.uniform (minval = -1, maxval = 1)

À ce stade, nous pouvons commencer à créer les couches de notre réseau de neurones. Pour créer la couche d'entrée, nous devons utiliser le des données d'entrée() Cette méthode nous permet de spécifier le nombre d’entrées que le réseau peut accepter. Une fois que la couche d’entrée est prête, nous pouvons appeler le entièrement_connecté () méthode plusieurs fois pour ajouter plus de couches au réseau.

# Couche d'entrée net = tflearn.input_data (forme = [Aucun, 2], nom = 'mon_input') # Calques masqués net = tflearn.fully_connected (net, 4, activation = 'sigmoïde', weights_init = poids) net = tflearn. Fully_connected (net, 3, activation = 'sigmoïde', weights_init = poids) # Couche de sortie net = tflearn.fully_connected (net, 1, activation = 'sigmoïde', weights_init = poids, name = 'mon_soutput')

Notez que dans le code ci-dessus, nous avons donné des noms significatifs aux calques d’entrée et de sortie. Cela est important car nous en aurons besoin lorsque nous utiliserons le réseau depuis notre application Android. Notez également que les couches masquées et de sortie utilisent le sigmoïde fonction d'activation. Vous êtes libre d'essayer d'autres fonctions d'activation, telles que softmaxtanh, et relu.

En tant que dernière couche de notre réseau, nous devons créer une couche de régression à l'aide du régression() function, qui attend quelques hyper-paramètres comme arguments, tels que le taux d’apprentissage du réseau et les fonctions d’optimiseur et de perte qu’il devrait utiliser. Le code suivant vous montre comment utiliser la descente de gradient stochastique, SGD en abrégé, en tant que fonction d'optimisation et carré moyen en tant que fonction de perte:

net = tflearn.regression (net, learning_rate = 2, optimizer = 'sgd', loss = 'mean_square')

Ensuite, pour que le framework TFLearn sache que notre modèle de réseau est en réalité un modèle de réseau neuronal profond, nous devons appeler le DNN () une fonction.

modèle = tflearn.DNN (net)

Le modèle est maintenant prêt. Tout ce que nous devons faire maintenant, c’est de le former en utilisant les données de formation que nous avons créées précédemment. Alors appelez le en forme() méthode du modèle et, avec les données de formation, spécifiez le nombre d’époques de formation à exécuter. Comme les données d’entraînement sont très petites, notre modèle aura besoin de milliers d’époques pour atteindre une précision raisonnable..

model.fit (X, Y, 5000)

Une fois la formation terminée, nous pouvons appeler le prédire() méthode du modèle pour vérifier s’il génère les sorties souhaitées. Le code suivant vous montre comment vérifier les sorties pour toutes les entrées valides:

print ("1 XOR 0 =% f"% model.predict ([[1,0]]). item (0)) print ("1 XOR 1 =% f"% model.predict ([[1,1] ]). item (0)) print ("0 XOR 1 =% f"% model.predict ([[0,1]]). item (0)) print ("0 XOR 0 =% f"% model. prédire ([[0,0]]). item (0))

Si vous exécutez le script Python maintenant, vous devriez voir une sortie qui ressemble à ceci:

Notez que les sorties ne sont jamais exactement égales à 0 ou 1. Il s'agit plutôt de nombres à virgule flottante proches de zéro ou proches de un. Par conséquent, lorsque vous utilisez les sorties, vous pouvez utiliser le code de Python. rond() une fonction.

Si nous ne sauvegardons pas explicitement le modèle après l'avoir formé, nous le perdrons dès la fin du script. Heureusement, avec TFLearn, un simple appel à la enregistrer() méthode enregistre le modèle. Cependant, pour pouvoir utiliser le modèle enregistré avec TensorFlow Mobile avant de l’enregistrer, nous devons nous assurer de supprimer toutes les opérations liées à la formation, présentes dans la liste. tf.GraphKeys.TRAIN_OPS collection, associée à elle. Le code suivant vous montre comment procéder:

# Supprime les opérations de train avec net.graph.as_default (): del tf.get_collection_ref (tf.GraphKeys.TRAIN_OPS) [:] # Enregistrez le modèle model.save ('xor.tflearn')

Si vous exécutez à nouveau le script, vous constaterez qu'il génère un fichier de point de contrôle, un fichier de métadonnées, un fichier d'index et un fichier de données, qui, lorsqu'ils sont utilisés ensemble, peuvent rapidement recréer notre modèle formé..

2. Geler le modèle

En plus de sauvegarder le modèle, nous devons le geler avant de pouvoir l'utiliser avec TensorFlow Mobile. Comme vous l'avez peut-être deviné, le processus de gel d'un modèle implique la conversion de toutes ses variables en constantes. En outre, un modèle figé doit être un fichier binaire unique conforme au format de sérialisation des tampons de protocole de Google..

Créez un nouveau script Python nommé freeze_model.py et ouvrez-le à l'aide d'un éditeur de texte. Nous écrirons tout le code pour geler notre modèle dans ce fichier.

Comme TFLearn n’a aucune fonction pour geler des modèles, nous devrons utiliser les API TensorFlow directement maintenant. Importez-les en ajoutant la ligne suivante au fichier:

importer tensorflow en tant que tf

Tout au long du script, nous utiliserons une seule session TensorFlow. Pour créer la session, utilisez le constructeur de la Session classe.

avec tf.Session () en tant que session: # Le reste du code va ici

À ce stade, nous devons créer un Épargnant objet en appelant le import_meta_graph () fonction et en lui passant le nom du fichier de métadonnées du modèle. En plus de retourner un Épargnant objet, le import_meta_graph () La fonction ajoute également automatiquement la définition du graphique du modèle à la définition du graphique de la session..

Une fois l’épargnant créé, vous pouvez initialiser toutes les variables présentes dans la définition du graphe en appelant le restaurer() méthode, qui attend le chemin du répertoire contenant le dernier fichier de point de contrôle du modèle.

my_saver = tf.train.import_meta_graph ('xor.tflearn.meta') my_saver.restore (session, tf.train.latest_checkpoint ('.'))

À ce stade, nous pouvons appeler le convert_variables_to_constants () fonction pour créer une définition de graphe figé dans laquelle toutes les variables du modèle sont remplacées par des constantes. En entrée, la fonction attend la session en cours, la définition du graphique de la session en cours et une liste contenant les noms des couches en sortie du modèle..

frozen_graph = tf.graph_util.convert_variables_to_constants (session, session.graph_def, ['my_output / Sigmoid'])

Appeler le SerializeToString () La méthode de définition des graphes figés nous donne une représentation binaire protobuf du modèle. En utilisant les fonctionnalités d'E / S de fichiers de base de Python, je vous suggère de l'enregistrer sous un fichier nommé frozen_model.pb.

avec open ('frozen_model.pb', 'wb') en tant que f: f.write (frozen_graph.SerializeToString ())

Vous pouvez exécuter le script maintenant pour générer le modèle gelé.

Nous avons maintenant tout ce dont nous avons besoin pour commencer à utiliser TensorFlow Mobile.

3. Configuration du projet Android Studio

La bibliothèque TensorFlow Mobile est disponible sur JCenter, nous pouvons donc l'ajouter directement en tant que la mise en oeuvre dépendance dans le app modules build.gradle fichier.

implémentation 'org.tensorflow: tensorflow-android: 1.7.0'

Pour ajouter le modèle figé au projet, placez le frozen_model.pb fichier dans le projet les atouts dossier.

4. Initialisation de l'interface TensorFlow

TensorFlow Mobile offre une interface simple que nous pouvons utiliser pour interagir avec notre modèle figé. Pour créer l'interface, utilisez le constructeur de la TensorFlowInferenceInterface classe, qui attend un Gestionnaire d'actifs instance et le nom du fichier du modèle figé.

thread val tfInterface = TensorFlowInferenceInterface (assets, "frozen_model.pb") // Plus de code ici

Dans le code ci-dessus, vous pouvez voir que nous créons un nouveau thread. Bien que cela ne soit pas toujours nécessaire, il est recommandé de s'assurer que l'interface utilisateur de l'application reste sensible..

Pour être sûr que TensorFlow Mobile a réussi à lire le fichier de notre modèle correctement, essayons maintenant d’imprimer les noms de toutes les opérations présentes dans le graphique du modèle. Pour obtenir une référence au graphique, nous pouvons utiliser le graphique() méthode de l'interface, et pour obtenir toutes les opérations, la opérations () méthode du graphique. Le code suivant vous montre comment:

val graph = tfInterface.graph () graph.operations (). forEach println (it.name ())

Si vous exécutez l'application maintenant, vous devriez pouvoir voir plus d'une douzaine de noms d'opérations imprimés dans Android Studio. Logcat la fenêtre. Parmi tous ces noms, s'il n'y a pas d'erreur lors du gel du modèle, vous pourrez trouver les noms des couches d'entrée et de sortie: mon_input / X et my_output / Sigmoid.

5. Utiliser le modèle

Pour faire des prédictions avec le modèle, nous devons placer des données dans sa couche d'entrée et extraire des données de sa couche de sortie. Pour placer des données dans la couche d’entrée, utilisez la commande alimentation() méthode de l'interface, qui attend le nom de la couche, un tableau contenant les entrées et les dimensions du tableau. Le code suivant vous montre comment envoyer les numéros 0 et 1 à la couche d'entrée:

tfInterface.feed ("my_input / X", floatArrayOf (0f, 1f), 1, 2)

Après avoir chargé des données dans la couche d’entrée, nous devons exécuter une opération d’inférence à l’aide du courir() méthode, qui attend le nom de la couche en sortie. Une fois l'opération terminée, la couche de sortie contiendra la prédiction du modèle. Pour charger la prédiction dans un tableau Kotlin, nous pouvons utiliser le chercher () méthode. Le code suivant vous montre comment procéder:

tfInterface.run (arrayOf ("my_output / Sigmoid")) val output = floatArrayOf (-1f) tfInterface.fetch ("my_output / Sigmoid", sortie)

Comment vous utilisez la prédiction est bien sûr à vous. Pour l'instant, je vous suggère simplement de l'imprimer.

println ("La sortie est $ output [0]")

Vous pouvez exécuter l'application maintenant pour voir que la prédiction du modèle est correcte.

Sentez-vous libre de changer les nombres que vous donnez au calque d'entrée pour confirmer que les prédictions du modèle sont toujours correctes.

Conclusion

Vous savez maintenant comment créer un modèle simple TensorFlow et l'utiliser avec TensorFlow Mobile dans les applications Android. Cependant, vous n'êtes pas obligé de vous limiter à vos propres modèles. Avec les compétences que vous avez acquises aujourd'hui, vous ne devriez plus rencontrer de problèmes pour utiliser des modèles plus grands, tels que MobileNet et Inception, disponibles dans le zoo modèle TensorFlow. Notez toutefois que ces modèles génèrent des fichiers APK plus volumineux, ce qui peut créer des problèmes pour les utilisateurs disposant d'appareils bas de gamme..

Pour en savoir plus sur TensorFlow Mobile, consultez la documentation officielle..