Articles

Publié par

Il y a 5 mois -

Temps de lecture 15 minutes

What’s new in TensorFlow ? Des nouvelles du TensorFlow Dev Summit 2018 (1/3)

Le 30 mars dernier s’est tenu le 2e TensorFlow Dev Summit à Mountain View (Californie), avec encore une fois énormément d’annonces, de nouveaux modules et des exemples de cas d’application. En 1 an, beaucoup de choses ont changé dans l’écosystème TensorFlow, qui se positionne comme l’un des outils de Machine Learning open source les plus complets. Il peut être difficile de suivre tous ces avancements, tant ils sont nombreux.

Dans cette courte série d’articles, nous vous proposons de passer en revue les principales nouveautés techniques qui ont été annoncées au cours de cette conférence, et de comprendre quels sont leurs impacts sur la manière dont nous utiliserons ce framework.

@Une majeure partie des efforts qui ont été faits ces derniers mois sur le projet TensorFlow s’est concentrée sur la manière de rendre TensorFlow plus facile à utiliser pour un plus grand nombre de personnes, ainsi qu’à proposer des outils pour aller au-delà du simple entraînement de modèles : de la préparation de données à la mise en production.

Le focus de ce premier article sera sur toutes les nouvelles API plus haut niveau de TensorFlow et la manière optimale de les utiliser. Les prochains articles vous permettront de connaître les nouveaux outils qui gravitent autour, de la mise en place de répertoires de partage de modèles au nouveau mode d’exécution qui s’abstrait des graphes, en passant par le debugging et les nouveaux langages disponibles.

Au programme de cet article, le résumé de 3 présentations sur les API plus haut niveau :

  • tf.data : API pour la gestion des données d’entrée ;
  • TF High Level APIs : toutes les API pour vous simplifier la vie pour créer, entraîner et exporter vos modèles ;
  • TensorFlow Extended : les différents blocs rendus open-source pour faire de TensorFlow le framework permettant de faire du Machine Learning end-to-end.

tf.data: Fast, flexible and easy-to-use input pipelines (Derek Murray)

tf.data est l’API la plus recommandée pour gérer ses données d’entrée avec TensorFlow. Aux débuts de TensorFlow, les input pipelines (chaînes de traitement des données d’entrée), étaient gérées en allant chercher les données depuis Python directement à chaque étape (solution plutôt lente) ou en créant des queue runners (plus compliqué à mettre en place). La mission de tf.data est donc triple :

  • Rapidité, pour garder le rythme des CPU, GPU & TPU ;
  • Flexibilité, pour être capable de gérer n’importe quel format de données ;
  • Facilité d’utilisation, pour être accessible au plus grand nombre.

tf.data a été conçue en s’inspirant du fonctionnement des bases de données ainsi que des langages fonctionnels, et se décompose en des phases classiques d’ETL (Extract, Transform, Load). Un code typique avec tf.data ressemble donc à ceci :

tf.data example
# Extract
files = tf.data.Dataset.list_files(file_pattern)
dataset = tf.data.TFRecordDataset(files)

# Transform (methods chaining)
dataset = dataset.shuffle(10000)
dataset = dataset.repeat(NUM_EPOCHS) # NUM_EPOCHS correspond au nombre d'itérations complètes sur le dataset
dataset = dataset.map(lambda x: tf.parse_single_example(x, features))
dataset = dataset.batch(BATCH_SIZE)

# Load
iterator = dataset.make_one_shot_iterator()
features = iterator.get_next()

Performance

tf.data a été optimisé pour améliorer les performances dans la gestion des données d’entrée, comme le montre le guide des performances présent sur le site de TensorFlow. Pour le moment, les performances sont focalisées pour le fonctionnement sur CPU, alors que le fonctionnement sur GPU est prévu pour la version 1.8.

Flexibilité

tf.data supporte maintenant les types de données complexes ainsi que les données sparses via tf.SparseTensor. Il est aussi possible de créer du code Python custom via Dataset.from_generator(), ainsi que d’utiliser du code C++ directement.

Facilité d’utilisation

Via le nouveau mode d’exécution (Eager Mode), il est possible d’utiliser des datasets comme de simples objets sur lesquels on peut itérer. Quelques nouvelles fonctionnalités seront présentes en TensorFlow 1.8 pour encapsuler toutes les bonnes pratiques techniques en une seule fonction (gestion des namespaces, parallélisation, gestion de la Session, etc.).

tf.data – Eager mode
tf.enable_eager_execution()

dataset = tf.contrib.data.make_batched_features_dataset(file_pattern, BATCH_SIZE, features, num_epochs=NUM_EPOCHS)

for batch in dataset:
	train_model(batch)

Nous reviendrons sur le Eager Mode dans le prochain article.

Concernant les formats de données, bien qu’il soit recommandé d’utiliser des formats de stockage binaires pour vos données d’entrée, il reste fréquent d’être confronté à des types de données texte comme le CSV. TensorFlow 1.8 va incorporer tout un ensemble de fonctions utilitaires, comme make_csv_dataset, qui reconnaissent automatiquement le type et le nom des colonnes.

Enfin, une intégration facilitée avec les Estimators de TensorFlow permet d’éviter de passer par des itérateurs.

tf.data a donc été conçu pour rendre le code le plus « Pythonic » possible, haut niveau et performant. Il est donc maintenant recommandé d’utiliser cette API pour tous les traitements des données d’entrée en TensorFlow. Pour plus d’informations, vous pouvez consulter la rubrique dédiée dans le Programmer’s Guide.

Pour plus d’informations, consultez la vidéo associée à ce sujet.

The practitioner’s guide with TF High Level APIs (Mustafa Ispir)

TensorFlow a longtemps souffert d’une réputation de framework bas niveau pour le Machine Learning. De gros efforts ont été consenti dans ce sens pour fournir des APIs plus haut niveau et user-friendly à TensorFlow, que nous allons parcourir ici.

Estimators

Estimator est une librairie dont l’objectif est de simplifier la mise en place de modèles de Machine Learning, en encapsulant automatiquement les phases d’entraînement, évaluation, prédiction et d’export. L’utilisateur peut donc se concentrer sur ce qui constitue réellement son expérimentation, et s’abstraire des difficultés inhérentes au framework.

Un Estimator contient une fonction modèle (model function) qui définit notre réseau de neurones et la manière dont on souhaite l’entraîner, le valider, l’utiliser pour la prédiction ou l’exporter. Il gère aussi les Sessions, afin de ne pas avoir à s’en préoccuper. Un Estimator nécessite d’avoir une fonction d’entrée définissant comment charger et gérer la donnée.

Feature Columns

Les Feature Columns ont pour objectif de faciliter l’expérimentation avec les features de nos datasets. Elles définissent comment nous souhaitons traiter la donnée pour le modèle, tout en réduisant le nombre de lignes de code à implémenter pour le faire.

Tout un ensemble de transformations sont d’ores et déjà implémentées via des Feature Columns : Bucketing (partitionnage par ordre de grandeur), Crossing (création de combinaisons), Hashing (limitation en taille), Embedding (apprentissage de nouvelles représentations).

La documentation pour les Feature Columns est présente dans la section Getting Started du site de TensorFlow.

Quelques exemples de création de Feature Columns :

Feature Columns
hike_id = categorical_column_with_vocabulary_file("hike_id", vocabulary_path)
hike_embedding = embedding_column(hike_id, 1)

tags = categorical_column_with_vocabulary_list("tags", ["kids friendly", "birding", "dog friendly", ...])
tags_one_hot = indicator_column(tags)

elevation = numerical_column("elevation_gain", normalizer_fn=...)

distance = numerical_column("distance")
bucketed_distance = bucketized_column(distance, [1, 3, 6, 9])

user_id = categorical_column_with_hash_bucket("user_id", 10000)
user_embedding = embedding_column(user_id, 128)

# Putting all together
feature_columns = [user_embedding, hike_embedding, tags_one_shot, elevation, bucketed_distance]

Pre-made Estimators

Il existe de nombreux Estimators déjà implémentés pour nous, et qui sont très souvent utilisés. Quelques-unes de leurs caractéristiques sont les suivantes :

  • Ils gèrent les détails d’implémentation pour nous afin de se concentrer sur l’expérience à mener ;
  • Les valeurs par défaut sont en général raisonnables et utilisables dans de nombreux contextes, que ce soit pour l’initialisation, le partionning ou l’optimisation, ce qui permet de constuire des baselines très rapidement ;
  • Il est très simple de les expérimenter avec de nouvelles features, ce qui nous laisse nous concentrer sur nos données plutôt que sur l’implémentation en général : le même Estimator est utilisé quel que soit le nombre et le type de features à utiliser.

Voici un exemple simple d’utilisation de ces différentes notions avec l’Estimator DNNClassifier :

Pre-made Estimators
estimator = DNNClassifier(hidden_units=[1024, 256, ...], feature_columns=feature_columns)

train_spec = TrainSpec(input_fn=lambda: input_fn(TRAIN_FILES), max_steps=1000)
eval_spec = EvalSpec(input_fn=lambda: input_fn(EVAL_FILES))

train_and_evaluate(estimator, train_spec, eval_spec)

Avec ces quelques lignes de code, nous pouvons directement visualiser l’évolution de nos métriques dans TensorBoard, sans ligne de code additionnelle.

Quelques autres Estimators sont à disposition dans TensorFlow : Wide & Deep (DNNLinearCombinedClassifier) et Gradient Boosted Trees (BoostedTreesClassifier). Il est possible de les utiliser sans avoir besoin de modifier le reste du code.

Il est donc maintenant possible d’expérimenter à la fois des réseaux de neurones et d’autres types de modèles de Machine Learning sans changer de framework.

Modélisation personnalisée

Si les Estimators déjà présents dans TensorFlow ne sont pas suffisants, il est parfaitement possible d’en créer par soi-même. En fonction de sa problématique, il est parfois préférable de spécifier sa propre métrique à optimiser et ce que l’on veut utiliser lors du Serving. Ceci peut-être fait grâce à la nouvelle Head API. Il devient ainsi assez simple de combiner plusieurs types d’Estimators avec différents Heads (binary_classification_head, multi_class_head, regression_head, etc.) en fonction de sa problématique.

Si l’on souhaite personnaliser encore plus ses implémentations (le réseau de neurones ainsi que ses métriques et prédictions), il est possible de se créer une model function (model_fn). Pour les utilisateurs de Keras, il est aussi très simple de passer de son code à un Estimator, via la méthode model_to_estimator :

model_fn
model = Sequential()
model.add(Dense(units=64, activation="relu", input_dim=100)
model.add(Dense(units=10, activation="softmax")
model.compile(loss="categorical_crossentropy", optimizer="sgd", metrics=["accuracy"])

estimator = model_to_estimator(model)

Enfin, via TensorFlow Hub (que nous verrons après), il est possible d’extraire tout ou une partie des poids d’un réseau de neurones déjà entraîné, et de les utiliser comme un Feature Extractor pour rajouter des features ou faire du Transfer Learning.

Passage à l’échelle

Une fois que vous avez créé votre Estimator, il est très simple, sans modification de code, de l’utiliser à plus grande échelle :

  • En répliquant l’Estimator sur une plateforme multi-GPU, en modifiant simplement une ligne de configuration ;
  • En parallélisant l’entraînement en modifiant uniquement l’environnement de configuration TF_CONFIG.

Le fait de ne pas avoir à modifier le code de son Estimator en changeant de plateforme est un avantage non négligeable.

Serving

L’export de l’Estimator pour son utilisation en production est rendue simple par TensorFlow Serving. Il faut alors implémenter une receiver function (receiver_fn) qui spécifie comment utiliser le modèle.

Conclusion

Les API haut niveau de TensorFlow sont faites pour simplifier la vie du développeur. Un grand nombre d’opérations et de modèles sont pré-implémentés, ce qui permet à l’utilisateur de se concentrer sur sa donnée et son expérience. Il est de plus possible de customiser simplement l’utilisation de ces abstractions afin de satisfaire tous ses besoins.

Pour plus d’informations, consultez la vidéo associée à ce sujet.

TensorFlow Extended (Clemens Mewald & Raz Mathias)

Faire du Machine Learning en production est quelque chose de compliqué, qui va bien au-delà du simple entraînement d’un modèle : de la collecte de données au serving, en passant par du monitoring et bien d’autres.

TFX (TensorFlow eXtended) est la plateforme de Machine Learning développée et proposée par Google pour faire du Machine Learning end-to-end avec TensorFlow avec le moins de complexité possible. Cette plateforme est composée de nombreux modules, qui sont peu à peu rendus open source :

  • TensorFlow Transform
  • TensorFlow Estimators
  • TensorFlow Model Analysis
  • TensorFlow Serving

TensorFlow Transform : Consistant in-graph transformations in training and serving

Il est parfois difficile de s’assurer que toutes les étapes de transformation de la donnée et d’inférence se comportent exactement de la même manière à l’entraînement qu’en production, surtout lorsque l’on cherche à déployer sur plusieurs systèmes. Lorsque l’on déploie un modèle sur un appareil mobile par exemple, les pré-traitements de la donnée sont souvent faits dans un autre langage que lors de l’entraînement, ce qui peut provoquer des divergences dans les prédictions.

f.transform permet d’avoir accès à un ensemble de fonctions de transformation de la donnée pour aider l’utilisateur à construire ses pipelines. De plus, et ce de manière transparente, un graphe TensorFlow pourra être utilisé par le modèle durant la phase d’entraînement mais aussi de serving, sans que l’on ait à l’instancier. Toutes les transformations se font au sein du graphe TensorFlow, afin de permettre les mêmes conditions à toutes les phases. Il n’y a donc plus besoin de code spécifique sur les environnements de déploiement du modèle.

Il est donc possible grâce à tf.transform d’utiliser un ensemble de fonctions (déjà implémentées ou créées par nous-mêmes) qui seront exécutées au sein du graphe TensorFlow. Si un pipeline de pre-processing contient par exemple des calculs pour de la normalisation de données, les moyennes et variances seront calculées durant la phase d’entraînement, et les résultats seront stockés sous forme de constantes au sein du graphe qui sera utilisé pour la prédiction.

Quelques exemples de transformations pré-implémentées sont des fonctions de scaling, de bucketization, de Bag of Words ou encore de croisement d’informations. Tout est disponible sur le projet Github associé.

TensorFlow Model Analysis : Scaleable, sliced and full-pass metrics

Aujourd’hui, TensorBoard permet de contrôler via le suivi de nombreuses métriques les conditions d’entraînement des modèles : vérifier la bonne convergence, le précision, la distribution des poids, etc. Cependant, il manque un élément essentiel du puzzle : comment vérifier les performances du modèle en conditions réelles ?

C’est ce que propose TensorFlow Model Analysis : mettre à disposition des moyens simples de mesurer les performances après déploiement, avec un ensemble de métriques classiques, ainsi que des facilitations pour faire des analyses avancées (par type de population par exemple). Il permet donc de rentrer plus dans le détail de nos prédictions, pour détecter par exemple des cas où le modèle est biaisé : à cause d’un mauvais équilibre des données d’entrée, le modèle peut être meilleur pour certains groupes plutôt que d’autres.

Concrètement, TensorFlow Model Analysis peut être utilisé au sein d’un notebook Jupyter et ressemble à ceci :

De la même manière que l’on exporte un modèle entraîné pour une phase de serving, il est maintenant possible d’exporter un modèle entraîné pour évaluation. Cet export contient des annotations additionnelles qui permettent de trouver les features et les prédictions pour les analyser. Typiquement, ces informations n’ont pas besoin d’être présentes dans le modèle serialisé pour la phase de serving, mais sont nécessaires à son analyse.

Toutes les informations sont disponibles sur le projet Github associé qui a été rendu open source il y a peu.

TensorFlow Serving

TensorFlow Serving est utilisé en fin de chaîne de traitement pour déployer ses modèles et les utiliser dans des environnements de production en quelques lignes. Le plus gros du travail réalisé aujourd’hui concerne la mise à disposition d’une API REST pour l’utilisation de TensorFlow Serving, qui va pouvoir notamment fournir une API Predict qui permettra de faire des prédictions en packageant ses tenseurs d’entrée dans des fichiers JSON. Cette API devrait être mise à disposition bientôt.

End-to-end workflow

TensorFlow eXtended (TFX) est aujourd’hui composé de 4 éléments : TensorFlow Transform, Estimator, Model Analysis et Serving. Mais il y a bien plus à faire pour avoir un système complètement end-to-end, comme celui décrit dans le papier de recherche de Google expliquant le fonctionnement de TFX en interne.

Dans les prochaines versions de TFX, des modules de data ingestion et de data analysis & validation seront intégrés, permettant de contrôler le début de la chaîne de traitement. Viendront par la suite les interfaces graphiques et les configurations pour gérer ces plateformes end-to-end.

Pour plus d’informations, consultez la vidéo associée à ce sujet.

Conclusion

Grâce à toutes ces nouvelles fonctionnalités plus haut niveau, TensorFlow cherche à atteindre un panel plus large d’utilisateurs, mais aussi de devenir un framework allant au-delà du simple entraînement de modèle : un framework de Machine Learning end-to-end.

Vous pouvez suivre les prochaines évolutions de TensorFlow sur leur nouveau blog qui a été ouvert, et qui contiendra toutes les prochaines annonces ainsi que des exemples d’utilisation de tous les éléments que nous avons vu dans cet article et bien d’autres.

Mais ces API haut niveau ne sont pas les seules nouveautés ! Nous vous encourageons à lire le 2e article, qui vous montrera tous les nouveaux outils et optimisations qui gravitent autour de TensorFlow pour vous simplifier la vie. Bonne lecture !

Publié par

Publié par Yoann Benoit

Yoann est Data Scientist chez Xebia. Il est également formateur au sein de Xebia Training .

Commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Xebian, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.