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 :
-
tf.estimator.DNNClassifier
pour les modèles approfondis qui effectuent une classification multiclasse. -
tf.estimator.DNNLinearCombinedClassifier
pour les modèles larges et profonds. -
tf.estimator.LinearClassifier
pour les classificateurs basés sur des modèles linéaires.
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"