Estimateurs prédéfinis

Voir sur TensorFlow.org Exécuter dans Google Colab Voir la source sur GitHub Télécharger le cahier

Ce didacticiel vous montre comment résoudre le problème de classification Iris dans TensorFlow à l'aide d'estimators. Un estimateur est une représentation de haut niveau héritée de TensorFlow d'un modèle complet. Pour plus de détails, voir Estimateurs .

Tout d'abord

Pour commencer, vous allez d'abord importer TensorFlow et un certain nombre de bibliothèques dont vous aurez besoin.

import tensorflow as tf

import pandas as pd

L'ensemble de données

L'exemple de programme de ce document construit et teste un modèle qui classe les fleurs d'iris en trois espèces différentes en fonction de la taille de leurs sépales et pétales .

Vous entraînerez un modèle à l'aide de l'ensemble de données Iris. L'ensemble de données Iris contient quatre entités et une étiquette . Les quatre caractéristiques identifient les caractéristiques botaniques suivantes des fleurs d'iris individuelles :

  • longueur des sépales
  • largeur des sépales
  • longueur des pétales
  • largeur des pétales

Sur la base de ces informations, vous pouvez définir quelques constantes utiles pour analyser les données :

CSV_COLUMN_NAMES = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species']
SPECIES = ['Setosa', 'Versicolor', 'Virginica']

Ensuite, téléchargez et analysez l'ensemble de données Iris à l'aide de Keras et de Pandas. Notez que vous conservez des ensembles de données distincts pour la formation et les tests.

train_path = tf.keras.utils.get_file(
    "iris_training.csv", "https://storage.googleapis.com/download.tensorflow.org/data/iris_training.csv")
test_path = tf.keras.utils.get_file(
    "iris_test.csv", "https://storage.googleapis.com/download.tensorflow.org/data/iris_test.csv")

train = pd.read_csv(train_path, names=CSV_COLUMN_NAMES, header=0)
test = pd.read_csv(test_path, names=CSV_COLUMN_NAMES, header=0)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/iris_training.csv
16384/2194 [================================================================================================================================================================================================================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/iris_test.csv
16384/573 [=========================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================] - 0s 0us/step

Vous pouvez inspecter vos données pour voir que vous avez quatre colonnes de caractéristiques flottantes et une étiquette int32.

train.head()

Pour chacun des ensembles de données, divisez les étiquettes que le modèle sera entraîné à prédire.

train_y = train.pop('Species')
test_y = test.pop('Species')

# The label column has now been removed from the features.
train.head()

Aperçu de la programmation avec les estimateurs

Maintenant que vous avez configuré les données, vous pouvez définir un modèle à l'aide d'un estimateur TensorFlow. Un estimateur est une classe dérivée de tf.estimator.Estimator . TensorFlow fournit une collection de tf.estimator (par exemple, LinearRegressor ) pour implémenter des algorithmes ML courants. Au-delà de ceux-ci, vous pouvez écrire vos propres estimateurs personnalisés . Il est recommandé d'utiliser des estimateurs prédéfinis lorsque vous commencez tout juste.

Pour écrire un programme TensorFlow basé sur des estimateurs prédéfinis, vous devez effectuer les tâches suivantes :

  • Créez une ou plusieurs fonctions d'entrée.
  • Définissez les colonnes de caractéristiques du modèle.
  • Instanciez un estimateur en spécifiant les colonnes de caractéristiques et divers hyperparamètres.
  • Appelez une ou plusieurs méthodes sur l'objet Estimator, en transmettant la fonction d'entrée appropriée comme source des données.

Voyons comment ces tâches sont implémentées pour la classification Iris.

Créer des fonctions d'entrée

Vous devez créer des fonctions d'entrée pour fournir des données pour la formation, l'évaluation et la prédiction.

Une fonction d'entrée est une fonction qui renvoie un objet tf.data.Dataset qui génère le tuple à deux éléments suivant :

  • features - Un dictionnaire Python dans lequel :
    • Chaque clé est le nom d'une fonction.
    • Chaque valeur est un tableau contenant toutes les valeurs de cette fonctionnalité.
  • label - Un tableau contenant les valeurs du label pour chaque exemple.

Juste pour démontrer le format de la fonction d'entrée, voici une implémentation simple :

def input_evaluation_set():
    features = {'SepalLength': np.array([6.4, 5.0]),
                'SepalWidth':  np.array([2.8, 2.3]),
                'PetalLength': np.array([5.6, 3.3]),
                'PetalWidth':  np.array([2.2, 1.0])}
    labels = np.array([2, 1])
    return features, labels

Votre fonction d'entrée peut générer le dictionnaire des features et la liste des label comme vous le souhaitez. Cependant, il est recommandé d'utiliser l' API Dataset de TensorFlow, qui peut analyser toutes sortes de données.

L'API Dataset peut gérer de nombreux cas courants pour vous. Par exemple, à l'aide de l'API Dataset, vous pouvez facilement lire les enregistrements d'une grande collection de fichiers en parallèle et les joindre en un seul flux.

Pour simplifier les choses dans cet exemple, vous allez charger les données avec pandas et créer un pipeline d'entrée à partir de ces données en mémoire :

def input_fn(features, labels, training=True, batch_size=256):
    """An input function for training or evaluating"""
    # Convert the inputs to a Dataset.
    dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))

    # Shuffle and repeat if you are in training mode.
    if training:
        dataset = dataset.shuffle(1000).repeat()

    return dataset.batch(batch_size)

Définir les colonnes de fonctionnalités

Une colonne de caractéristiques est un objet décrivant comment le modèle doit utiliser les données d'entrée brutes du dictionnaire de caractéristiques. Lorsque vous créez un modèle Estimator, vous lui transmettez une liste de colonnes de fonctionnalités décrivant chacune des fonctionnalités que vous souhaitez que le modèle utilise. Le module tf.feature_column fournit de nombreuses options pour représenter les données dans le modèle.

Pour Iris, les 4 caractéristiques brutes sont des valeurs numériques, vous allez donc créer une liste de colonnes de caractéristiques pour indiquer au modèle Estimator de représenter chacune des quatre caractéristiques sous forme de valeurs à virgule flottante 32 bits. Par conséquent, le code pour créer la colonne de fonctionnalité est :

# Feature columns describe how to use the input.
my_feature_columns = []
for key in train.keys():
    my_feature_columns.append(tf.feature_column.numeric_column(key=key))

Les colonnes de caractéristiques peuvent être beaucoup plus sophistiquées que celles présentées ici. Vous pouvez en savoir plus sur les colonnes de fonctionnalités dans ce guide .

Maintenant que vous avez la description de la manière dont vous souhaitez que le modèle représente les caractéristiques brutes, vous pouvez créer l'estimateur.

Instancier un estimateur

Le problème d'Iris est un problème de classification classique. Heureusement, TensorFlow fournit plusieurs estimateurs de classificateur prédéfinis, notamment :

Pour le problème Iris, tf.estimator.DNNClassifier semble être le meilleur choix. Voici comment vous avez instancié cet estimateur :

# Build a DNN with 2 hidden layers with 30 and 10 hidden nodes each.
classifier = tf.estimator.DNNClassifier(
    feature_columns=my_feature_columns,
    # Two hidden layers of 30 and 10 nodes respectively.
    hidden_units=[30, 10],
    # The model must choose between 3 classes.
    n_classes=3)
INFO:tensorflow:Using default config.
WARNING:tensorflow:Using temporary folder as model directory: /tmp/tmpxdgumb2t
INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpxdgumb2t', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_checkpoint_save_graph_def': True, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

Former, évaluer et prédire

Maintenant que vous disposez d'un objet Estimator, vous pouvez appeler des méthodes pour effectuer les opérations suivantes :

  • Entraînez le modèle.
  • Évaluez le modèle entraîné.
  • Utilisez le modèle formé pour faire des prédictions.

Former le modèle

Entraînez le modèle en appelant la méthode d' train de l'estimateur comme suit :

# Train the Model.
classifier.train(
    input_fn=lambda: input_fn(train, train_y, training=True),
    steps=5000)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/training/training_util.py:397: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/adagrad.py:84: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.
Instructions for updating:
Call initializer instance with the dtype argument instead of passing it to the constructor
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...
INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpxdgumb2t/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...
INFO:tensorflow:loss = 1.6787335, step = 0
INFO:tensorflow:global_step/sec: 305.625
INFO:tensorflow:loss = 1.1945828, step = 100 (0.328 sec)
INFO:tensorflow:global_step/sec: 375.48
INFO:tensorflow:loss = 1.0221117, step = 200 (0.266 sec)
INFO:tensorflow:global_step/sec: 376.21
INFO:tensorflow:loss = 0.9240805, step = 300 (0.266 sec)
INFO:tensorflow:global_step/sec: 377.968
INFO:tensorflow:loss = 0.85917354, step = 400 (0.265 sec)
INFO:tensorflow:global_step/sec: 376.297
INFO:tensorflow:loss = 0.81545967, step = 500 (0.265 sec)
INFO:tensorflow:global_step/sec: 367.549
INFO:tensorflow:loss = 0.7771524, step = 600 (0.272 sec)
INFO:tensorflow:global_step/sec: 378.887
INFO:tensorflow:loss = 0.74371505, step = 700 (0.264 sec)
INFO:tensorflow:global_step/sec: 379.26
INFO:tensorflow:loss = 0.717993, step = 800 (0.264 sec)
INFO:tensorflow:global_step/sec: 370.102
INFO:tensorflow:loss = 0.6952705, step = 900 (0.270 sec)
INFO:tensorflow:global_step/sec: 373.034
INFO:tensorflow:loss = 0.68044865, step = 1000 (0.268 sec)
INFO:tensorflow:global_step/sec: 372.193
INFO:tensorflow:loss = 0.65181077, step = 1100 (0.269 sec)
INFO:tensorflow:global_step/sec: 339.238
INFO:tensorflow:loss = 0.6319051, step = 1200 (0.295 sec)
INFO:tensorflow:global_step/sec: 334.252
INFO:tensorflow:loss = 0.63433766, step = 1300 (0.299 sec)
INFO:tensorflow:global_step/sec: 343.436
INFO:tensorflow:loss = 0.61748827, step = 1400 (0.291 sec)
INFO:tensorflow:global_step/sec: 346.575
INFO:tensorflow:loss = 0.606356, step = 1500 (0.288 sec)
INFO:tensorflow:global_step/sec: 351.362
INFO:tensorflow:loss = 0.59807724, step = 1600 (0.285 sec)
INFO:tensorflow:global_step/sec: 366.628
INFO:tensorflow:loss = 0.5832784, step = 1700 (0.273 sec)
INFO:tensorflow:global_step/sec: 367.034
INFO:tensorflow:loss = 0.5664347, step = 1800 (0.273 sec)
INFO:tensorflow:global_step/sec: 372.339
INFO:tensorflow:loss = 0.5684726, step = 1900 (0.268 sec)
INFO:tensorflow:global_step/sec: 368.957
INFO:tensorflow:loss = 0.56011164, step = 2000 (0.271 sec)
INFO:tensorflow:global_step/sec: 373.128
INFO:tensorflow:loss = 0.5483226, step = 2100 (0.268 sec)
INFO:tensorflow:global_step/sec: 377.334
INFO:tensorflow:loss = 0.5447233, step = 2200 (0.265 sec)
INFO:tensorflow:global_step/sec: 370.421
INFO:tensorflow:loss = 0.5358016, step = 2300 (0.270 sec)
INFO:tensorflow:global_step/sec: 367.076
INFO:tensorflow:loss = 0.53145075, step = 2400 (0.273 sec)
INFO:tensorflow:global_step/sec: 373.596
INFO:tensorflow:loss = 0.50931674, step = 2500 (0.268 sec)
INFO:tensorflow:global_step/sec: 368.939
INFO:tensorflow:loss = 0.5253717, step = 2600 (0.271 sec)
INFO:tensorflow:global_step/sec: 354.814
INFO:tensorflow:loss = 0.52558273, step = 2700 (0.282 sec)
INFO:tensorflow:global_step/sec: 372.243
INFO:tensorflow:loss = 0.51422054, step = 2800 (0.269 sec)
INFO:tensorflow:global_step/sec: 366.891
INFO:tensorflow:loss = 0.49747026, step = 2900 (0.272 sec)
INFO:tensorflow:global_step/sec: 370.952
INFO:tensorflow:loss = 0.49974674, step = 3000 (0.270 sec)
INFO:tensorflow:global_step/sec: 364.158
INFO:tensorflow:loss = 0.4978399, step = 3100 (0.275 sec)
INFO:tensorflow:global_step/sec: 365.383
INFO:tensorflow:loss = 0.5030147, step = 3200 (0.273 sec)
INFO:tensorflow:global_step/sec: 366.791
INFO:tensorflow:loss = 0.4772169, step = 3300 (0.273 sec)
INFO:tensorflow:global_step/sec: 372.438
INFO:tensorflow:loss = 0.46993533, step = 3400 (0.269 sec)
INFO:tensorflow:global_step/sec: 371.25
INFO:tensorflow:loss = 0.47242266, step = 3500 (0.269 sec)
INFO:tensorflow:global_step/sec: 369.725
INFO:tensorflow:loss = 0.46513358, step = 3600 (0.271 sec)
INFO:tensorflow:global_step/sec: 371.002
INFO:tensorflow:loss = 0.4762191, step = 3700 (0.270 sec)
INFO:tensorflow:global_step/sec: 369.304
INFO:tensorflow:loss = 0.44923267, step = 3800 (0.271 sec)
INFO:tensorflow:global_step/sec: 369.344
INFO:tensorflow:loss = 0.45467538, step = 3900 (0.271 sec)
INFO:tensorflow:global_step/sec: 375.58
INFO:tensorflow:loss = 0.46056622, step = 4000 (0.266 sec)
INFO:tensorflow:global_step/sec: 347.461
INFO:tensorflow:loss = 0.4489282, step = 4100 (0.288 sec)
INFO:tensorflow:global_step/sec: 368.435
INFO:tensorflow:loss = 0.45647347, step = 4200 (0.272 sec)
INFO:tensorflow:global_step/sec: 369.159
INFO:tensorflow:loss = 0.4444633, step = 4300 (0.271 sec)
INFO:tensorflow:global_step/sec: 371.995
INFO:tensorflow:loss = 0.44425523, step = 4400 (0.269 sec)
INFO:tensorflow:global_step/sec: 373.586
INFO:tensorflow:loss = 0.44025964, step = 4500 (0.268 sec)
INFO:tensorflow:global_step/sec: 373.136
INFO:tensorflow:loss = 0.44341013, step = 4600 (0.269 sec)
INFO:tensorflow:global_step/sec: 369.751
INFO:tensorflow:loss = 0.42856425, step = 4700 (0.269 sec)
INFO:tensorflow:global_step/sec: 364.219
INFO:tensorflow:loss = 0.44144967, step = 4800 (0.275 sec)
INFO:tensorflow:global_step/sec: 372.675
INFO:tensorflow:loss = 0.42951846, step = 4900 (0.268 sec)
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 5000...
INFO:tensorflow:Saving checkpoints for 5000 into /tmp/tmpxdgumb2t/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 5000...
INFO:tensorflow:Loss for final step: 0.42713496.
<tensorflow_estimator.python.estimator.canned.dnn.DNNClassifierV2 at 0x7fad05e33910>

Notez que vous encapsulez votre appel input_fn dans un lambda pour capturer les arguments tout en fournissant une fonction d'entrée qui ne prend aucun argument, comme prévu par l'Estimator. L'argument steps indique à la méthode d'arrêter l'apprentissage après un certain nombre d'étapes d'apprentissage.

Évaluer le modèle formé

Maintenant que le modèle a été entraîné, vous pouvez obtenir des statistiques sur ses performances. Le bloc de code suivant évalue la précision du modèle entraîné sur les données de test :

eval_result = classifier.evaluate(
    input_fn=lambda: input_fn(test, test_y, training=False))

print('\nTest set accuracy: {accuracy:0.3f}\n'.format(**eval_result))
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2022-01-26T06:41:28
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmpxdgumb2t/model.ckpt-5000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Inference Time : 0.40087s
INFO:tensorflow:Finished evaluation at 2022-01-26-06:41:28
INFO:tensorflow:Saving dict for global step 5000: accuracy = 0.8666667, average_loss = 0.49953422, global_step = 5000, loss = 0.49953422
INFO:tensorflow:Saving 'checkpoint_path' summary for global step 5000: /tmp/tmpxdgumb2t/model.ckpt-5000

Test set accuracy: 0.867

Contrairement à l'appel à la méthode train , vous n'avez pas passé l'argument steps à évaluer. L' input_fn pour eval ne produit qu'une seule époque de données.

Le dictionnaire eval_result contient également le average_loss (perte moyenne par échantillon), le loss (perte moyenne par mini-lot) et la valeur du global_step de l'estimateur (le nombre d'itérations d'apprentissage subies).

Faire des prédictions (inférer) à partir du modèle formé

Vous avez maintenant un modèle formé qui produit de bons résultats d'évaluation. Vous pouvez maintenant utiliser le modèle formé pour prédire l'espèce d'une fleur d'iris en fonction de certaines mesures non étiquetées. Comme pour l'entraînement et l'évaluation, vous effectuez des prédictions à l'aide d'un seul appel de fonction :

# Generate predictions from the model
expected = ['Setosa', 'Versicolor', 'Virginica']
predict_x = {
    'SepalLength': [5.1, 5.9, 6.9],
    'SepalWidth': [3.3, 3.0, 3.1],
    'PetalLength': [1.7, 4.2, 5.4],
    'PetalWidth': [0.5, 1.5, 2.1],
}

def input_fn(features, batch_size=256):
    """An input function for prediction."""
    # Convert the inputs to a Dataset without labels.
    return tf.data.Dataset.from_tensor_slices(dict(features)).batch(batch_size)

predictions = classifier.predict(
    input_fn=lambda: input_fn(predict_x))

La méthode predict renvoie un itérable Python, produisant un dictionnaire de résultats de prédiction pour chaque exemple. Le code suivant imprime quelques prédictions et leurs probabilités :

for pred_dict, expec in zip(predictions, expected):
    class_id = pred_dict['class_ids'][0]
    probability = pred_dict['probabilities'][class_id]

    print('Prediction is "{}" ({:.1f}%), expected "{}"'.format(
        SPECIES[class_id], 100 * probability, expec))
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmpxdgumb2t/model.ckpt-5000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
Prediction is "Setosa" (84.4%), expected "Setosa"
Prediction is "Versicolor" (49.3%), expected "Versicolor"
Prediction is "Virginica" (57.7%), expected "Virginica"