Tutoriel de régression linéaire avec TensorFlow [Exemples]
⚡ Résumé intelligent
La régression linéaire dans TensorFlow modélise la relation entre des variables numériques et une variable cible continue. Ce tutoriel présente l'entraînement d'un prédicteur de prix de l'immobilier à Boston selon trois méthodes distinctes : avec Pandas, NumPy et les pipelines d'entrée natifs de TensorFlow utilisant l'estimateur LinearRegressor.
Qu'est-ce que la régression linéaire?
Régression Linéaire La régression linéaire est une approche statistique permettant de modéliser les relations entre deux variables. Cette modélisation s'effectue entre une variable réponse scalaire et une ou plusieurs variables explicatives. La relation avec une seule variable explicative est appelée régression linéaire simple, et celle avec plusieurs variables explicatives, régression linéaire multiple.
TensorFlow fournit des outils pour avoir un contrôle total sur les calculs. Cela se fait avec l'API de bas niveau. De plus, TensorFlow est équipé d'une vaste gamme d'API pour effectuer de nombreuses machine learning algorithmes. Il s'agit de l'API de haut niveau, et TensorFlow les appelle estimateurs.
- API de bas niveauConcevoir l'architecture et optimiser le modèle à partir de zéro est complexe pour un débutant.
- API de haut niveauDéfinissez l'algorithme. Il est convivial. TensorFlow fournit une boîte à outils appelée estimateur construire, former, évaluer et faire une prédiction.
Dans ce tutoriel, vous utiliserez le estimateurs seulementLes calculs sont plus rapides et plus faciles à mettre en œuvre. La première partie explique comment utiliser l'optimiseur de descente de gradient pour entraîner une régression linéaire dans TensorFlow. Dans la seconde partie, vous utiliserez le jeu de données Boston pour prédire le prix d'une maison à l'aide d'un estimateur TensorFlow.
Télécharger le jeu de données de Boston
Comment entraîner un modèle de régression linéaire
Avant de commencer l'entraînement du modèle, examinons ce qu'est réellement une régression linéaire.
Imaginez que vous ayez deux variables, x et y, et que votre tâche consiste à prédire la valeur de y connaissant la valeur de x. Si vous représentez graphiquement ces données, vous pouvez observer une corrélation positive entre votre variable indépendante, x, et votre variable dépendante, y, comme le montre le nuage de points ci-dessous.
Vous pouvez observer que si x=1, y sera approximativement égal à 6, et si x=2, y sera aux alentours de 8.5.
Cette méthode n'est pas très précise et est sujette à erreurs, notamment avec un ensemble de données contenant des centaines de milliers de points.
Une régression linéaire est évaluée avec une équation. La variable y s'explique par une ou plusieurs covariables. Dans votre exemple, il n'y a qu'une seule variable dépendante. Si vous devez écrire cette équation, ce sera :
Avec:
est le biais. Autrement dit, si x=0, y=
est le poids associé à x
Il s'agit du résidu, ou de l'erreur du modèle. Il comprend ce que le modèle ne peut pas apprendre des données.
Imaginez que vous adaptez le modèle et que vous trouvez la solution suivante pour :
= 3.8
= 2.78
Vous pouvez remplacer ces nombres dans l’équation et cela devient :
y= 3.8 + 2.78x
Vous disposez désormais d'une méthode plus efficace pour déterminer les valeurs de y. En effet, vous pouvez remplacer x par n'importe quelle valeur afin de prédire y. Dans l'image ci-dessous, nous avons remplacé x dans l'équation par toutes les valeurs de l'ensemble de données et tracé le résultat.
La ligne rouge représente la valeur ajustée, c'est-à-dire la valeur de y pour chaque valeur de x. Il n'est pas nécessaire de connaître la valeur de x pour prédire y ; à chaque valeur de x correspond une valeur appartenant à la ligne rouge. Vous pouvez également effectuer des prédictions pour des valeurs de x supérieures à 2.
Pour étendre la régression linéaire à davantage de covariables, il suffit d'ajouter des variables au modèle. La différence entre l'analyse traditionnelle et la régression linéaire réside dans le fait que cette dernière examine la réaction de y à chaque variable x prise indépendamment.
Prenons un exemple. Imaginez que vous souhaitiez prédire les ventes d'un glacier. L'ensemble de données contient différentes informations telles que la météo (pluie, soleil, nuages) et des informations sur les clients (salaire, sexe, situation matrimoniale).
L'analyse traditionnelle tente de prédire les ventes en calculant, par exemple, la moyenne de chaque variable et en essayant d'estimer les ventes pour différents scénarios. Cette approche conduit à des prédictions peu fiables et limite l'analyse au scénario choisi.
Si vous utilisez la régression linéaire, vous pouvez écrire cette équation :
L'algorithme trouvera la meilleure solution pour les pondérations ; cela signifie qu'il tentera de minimiser le coût, qui est la différence entre la droite d'ajustement et les points de données.
Comment fonctionne l'algorithme
Le diagramme ci-dessous résume la boucle que répète l'algorithme : choisir les poids, prédire y, mesurer l'erreur et corriger les poids.
L'algorithme choisira un nombre aléatoire pour chacun et
et remplacez la valeur de x pour obtenir la valeur prédite de y. Si l'ensemble de données contient 100 observations, l'algorithme calcule 100 valeurs prédites.
Nous pouvons calculer l'erreur, notée L'erreur type du modèle correspond à la différence entre la valeur prédite et la valeur réelle. Une erreur positive indique que le modèle sous-estime la valeur de y, tandis qu'une erreur négative indique qu'il la surestime.
Votre objectif est de minimiser le carré de l'erreur. L'algorithme calcule la moyenne des carrés des erreurs. Cette étape est appelée minimisation de l'erreur. Pour la régression linéaire, il s'agit de… Erreur quadratique moyenne, également appelé MSE. Mathématiquement, c'est :
Où? :
ce sont les poids, donc
fait référence à la valeur prédite
- y est les vraies valeurs
- m représente le nombre d'observations
Notez que signifie qu'il utilise la transposition des matrices. Le
est la notation mathématique de la moyenne.
Le but est de trouver le meilleur qui minimise l'erreur quadratique moyenne.
Si l’erreur moyenne est importante, cela signifie que le modèle fonctionne mal et que les poids ne sont pas choisis correctement. Pour corriger les poids, vous devez utiliser un optimiseur. L'optimiseur traditionnel s'appelle Descente graduelle.
La descente de gradient calcule la dérivée et ajuste le poids en conséquence. Si la dérivée est positive, le poids est diminué ; si elle est négative, il est augmenté. Le modèle met à jour les poids et recalcule l'erreur. Ce processus est répété jusqu'à ce que l'erreur se stabilise. Chaque itération est appelée une… itérationDe plus, les gradients sont multipliés par un taux d'apprentissage, qui indique la vitesse de l'apprentissage.
Si le taux d'apprentissage est trop faible, l'algorithme mettra beaucoup plus de temps à converger, car il nécessitera un nombre d'itérations beaucoup plus important. Si le taux d'apprentissage est trop élevé, l'algorithme risque de ne jamais converger. La courbe de perte ci-dessous représente l'erreur en fonction du nombre d'itérations pour cet ensemble de données.
Comme vous pouvez le constater sur l'image ci-dessus, le modèle répète le processus une vingtaine de fois avant de trouver une valeur stable pour les pondérations, atteignant ainsi l'erreur la plus faible.
Notez que l'erreur n'est pas nulle mais se stabilise autour de 5. Cela signifie que le modèle commet une erreur typique de 5. Si vous souhaitez réduire cette erreur, vous devez ajouter des informations au modèle, comme davantage de variables, ou utiliser des estimateurs différents.
Vous vous souvenez de la première équation :
Les poids finaux sont 3.8 et 2.78. La vidéo ci-dessous vous montre comment la descente de gradient optimise la fonction de perte pour trouver ces poids.
Comment entraîner une régression linéaire avec TensorFlow
Maintenant que vous comprenez mieux ce qui se passe derrière le capot, vous êtes prêt à utiliser l'API d'estimateur fournie par TensorFlow pour entraîner votre première régression linéaire à l'aide de TensorFlow.
Note de version : Le flux de travail de l'estimateur présenté ci-dessous a été écrit pour TensorFlow 1.x et les premières versions 2.x. TensorFlow a marqué le tf.estimator et tf.feature_column Les API sont entièrement obsolètes depuis la version 2.12 et les estimateurs ont été supprimés depuis la version 2.16. Sur une installation actuelle, exécutez ce code dans un environnement TensorFlow 1.15 ou 2.x.tf.compat.v1 environnement, ou le porter vers Keras, où tf.keras.layers.Dense(1) De plus, des couches de prétraitement remplacent le LinearRegressor et les colonnes de caractéristiques. Les concepts (caractéristiques, étiquettes, lots, époques, MSE et descente de gradient) restent inchangés.
Vous utiliserez l'ensemble de données de Boston, qui comprend les variables suivantes.
| Variable | Description |
| crime | taux de criminalité par habitant par ville |
| zn | proportion de terrains résidentiels zonés pour des lots de plus de 25,000 pieds carrés. |
| indus | proportion de superficies commerciales non commerciales par ville. |
| nox | concentration d'oxyde nitrique |
| rm | nombre moyen de pièces par logement |
| âge | proportion de logements occupés par leur propriétaire construits avant 1940 |
| DIS | distances pondérées jusqu'à cinq centres d'emploi de Boston |
| impôt | taux de taxe foncière pleine valeur par dollar 10,000 |
| ptratio | ratio élèves/enseignant par ville |
| avec V | Valeur médiane des maisons occupées par leur propriétaire en milliers de dollars |
Vous allez créer trois ensembles de données différents :
| jeu de données | objectif | forme |
| Formation | Entraîner le modèle et obtenir les poids | 400, 10 |
| Évaluation | Évaluer les performances du modèle sur des données invisibles | 100, 10 |
| Prédire | Utilisez le modèle pour prédire la valeur d'une maison à partir de nouvelles données | 6, 10 |
L'objectif est d'utiliser les caractéristiques de l'ensemble de données pour prédire la valeur de la maison.
Dans la deuxième partie de ce tutoriel, vous apprendrez à utiliser TensorFlow avec trois méthodes différentes pour importer les données :
- Avec des pandas
- Avec NumPy
- TensorFlow uniquement
Notez que les trois options donnent les mêmes résultats.
Vous apprendrez à utiliser l'API de haut niveau pour créer, entraîner et évaluer un modèle de régression linéaire TensorFlow. Si vous utilisiez l'API de bas niveau, vous devriez définir manuellement :
- Fonction de perte
- Optimiseur : descente de gradient
- Multiplication matricielle
- Graphique et tenseur
C'est fastidieux et plus compliqué pour un débutant.
Solution Pandas
Vous devez importer les bibliothèques nécessaires pour entraîner le modèle.
import pandas as pd from sklearn import datasets import tensorflow as tf import itertools
Étape 1) Importez les données avec Pandas.
Vous définissez les noms des colonnes et les stockez dans COLUMNS. Vous pouvez utiliser pd.read_csv() pour importer les données.
COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio", "medv"]
Chaque appel doit pointer vers les fichiers CSV que vous avez téléchargés précédemment.
training_set = pd.read_csv("E:/boston_train.csv", skipinitialspace=True,skiprows=1, names=COLUMNS) test_set = pd.read_csv("E:/boston_test.csv", skipinitialspace=True,skiprows=1, names=COLUMNS) prediction_set = pd.read_csv("E:/boston_predict.csv", skipinitialspace=True,skiprows=1, names=COLUMNS)
Vous pouvez imprimer la forme des données.
print(training_set.shape, test_set.shape, prediction_set.shape)
Sortie
(400, 10) (100, 10) (6, 10)
Notez que l'étiquette, c'est-à-dire votre variable y, est incluse dans l'ensemble de données. Vous devez donc définir deux autres listes : l'une contenant uniquement les variables explicatives, et l'autre uniquement le nom de l'étiquette. Ces deux listes indiqueront à votre estimateur quelles sont les variables explicatives de l'ensemble de données et quelle colonne contient l'étiquette.
Cela se fait avec le code ci-dessous.
FEATURES = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio"] LABEL = "medv"
Étape 2) Convertir les données
Vous devez convertir les variables numériques au format approprié. TensorFlow fournit une méthode pour convertir une variable continue : tf.feature_column.numeric_column().
À l'étape précédente, vous avez défini une liste de caractéristiques à inclure dans le modèle. Vous pouvez maintenant utiliser cette liste pour les convertir en données numériques. Si vous souhaitez exclure des caractéristiques de votre modèle, vous pouvez supprimer une ou plusieurs variables de la liste `FEATURES` avant de construire `feature_cols`.
Notez que vous utiliserez un Python Utilisez une compréhension de liste avec la liste `FEATURES` pour créer une nouvelle liste nommée `feature_cols`. Cela vous évite d'écrire `tf.feature_column.numeric_column()` neuf fois. Une compréhension de liste est une méthode plus rapide et plus élégante pour créer de nouvelles listes.
feature_cols = [tf.feature_column.numeric_column(k) for k in FEATURES]
Étape 3) Définir l'estimateur
Dans cette étape, vous devez définir l'estimateur. TensorFlow fournit six estimateurs prédéfinis : trois pour les tâches de classification et trois pour les tâches de régression TensorFlow.
- Régresseur
- DNNRégresseur
- Régresseur Linéaire
- Régresseur combiné linéaire DNN
- Classificateur
- Classificateur DNN
- Classificateur linéaire
- DNNClassificateur combiné linéaire
Dans ce didacticiel, vous utiliserez le régresseur linéaire. Pour accéder à cette fonction, vous devez utiliser tf.estimator.
La fonction a besoin de deux arguments :
- feature_columns : contient les variables à inclure dans le modèle
- model_dir : chemin d’accès pour stocker le graphe, enregistrer les paramètres du modèle, etc.
TensorFlow créera automatiquement un dossier nommé train dans votre répertoire de travail. Vous devez utiliser ce chemin pour y accéder. Tableau Tenseur, comme le montre l'exemple de régression TensorFlow ci-dessous.
estimator = tf.estimator.LinearRegressor(
feature_columns=feature_cols,
model_dir="train")
Sortie
INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'train', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1a215dc550>, '_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}
La difficulté avec TensorFlow réside dans l'alimentation du modèle. Conçu pour le calcul parallèle et les très grands ensembles de données, TensorFlow ne peut pas, en raison des limitations des ressources machine, alimenter le modèle avec toutes les données en une seule fois. Il est donc nécessaire de procéder par lots. Il s'agit ici d'ensembles de données gigantesques, contenant des millions d'enregistrements, voire plus. Sans traitement par lots, une erreur de mémoire se produira.
Par exemple, si vos données contiennent 100 observations et que vous définissez une taille de lot de 10, cela signifie que le modèle verra 10 observations pour chaque itération (10*10).
Une fois que le modèle a traité toutes les données, il termine une époque. Une époque définit le nombre de fois où le modèle doit analyser les données. Il est préférable de ne pas définir cette étape et de laisser le modèle effectuer un nombre d'itérations prédéfini.
Une autre information importante est de savoir si vous souhaitez mélanger les données avant chaque itération. Pendant l'entraînement, il est essentiel de mélanger les données afin que le modèle n'apprenne pas un schéma spécifique. Si le modèle apprend les détails de ce schéma sous-jacent, il aura des difficultés à généraliser ses prédictions à des données inconnues. C'est ce qu'on appelle le surapprentissage. Le modèle fonctionne bien sur les données d'entraînement, mais ne peut pas prédire correctement les données inconnues.
TensorFlow simplifie ces deux étapes. Lorsque les données arrivent dans le pipeline, celui-ci sait combien d'observations sont nécessaires (lot) et s'il doit mélanger les données.
Pour indiquer à TensorFlow comment alimenter le modèle, vous pouvez utiliser pandas_input_fn. Cet objet nécessite cinq paramètres :
- x : données sur les fonctionnalités
- y : données d'étiquette
- batch_size : lot. Par défaut 128
- num_epoch : nombre d'époques, par défaut 1
- shuffle : mélanger ou non les données. Par défaut, aucun.
Il est nécessaire d'alimenter le modèle à plusieurs reprises ; il faut donc définir une fonction pour répéter ce processus. Appelez cette fonction get_input_fn.
def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True): return tf.estimator.inputs.pandas_input_fn( x=pd.DataFrame({k: data_set[k].values for k in FEATURES}), y = pd.Series(data_set[LABEL].values), batch_size=n_batch, num_epochs=num_epochs, shuffle=shuffle)
La méthode habituelle pour évaluer les performances d’un modèle consiste à :
- Former le modèle
- Évaluer le modèle sur un autre ensemble de données
- Faire une prédiction
L'estimateur TensorFlow propose trois fonctions différentes pour réaliser facilement ces trois étapes.
Étape 4) Former le modèle
Vous pouvez utiliser la méthode d'entraînement de l'estimateur pour ajuster le modèle. Cette méthode nécessite une fonction d'entrée (input_fn) et un nombre d'étapes. Vous pouvez utiliser la fonction créée précédemment pour alimenter le modèle. Ensuite, vous indiquez au modèle d'itérer 1 000 fois. Notez que vous ne spécifiez pas le nombre d'époques ; le modèle s'exécutera 1 000 fois. Si vous définissez le nombre d'époques à 1, le modèle s'exécutera quatre fois, car l'ensemble d'entraînement contient 400 enregistrements et la taille du lot est de 128.
- 128 lignes
- 128 lignes
- 128 lignes
- 16 lignes
Il est donc plus simple de définir le nombre d'époques sur zéro et de définir le nombre d'itérations, comme illustré dans l'exemple de classification TensorFlow ci-dessous.
estimator.train(input_fn=get_input_fn(training_set,
num_epochs=None,
n_batch = 128,
shuffle=False),
steps=1000)
Sortie
INFO:tensorflow:Calling model_fn. 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:Saving checkpoints for 1 into train/model.ckpt. INFO:tensorflow:loss = 83729.64, step = 1 INFO:tensorflow:global_step/sec: 238.616 INFO:tensorflow:loss = 13909.657, step = 101 (0.420 sec) INFO:tensorflow:global_step/sec: 314.293 INFO:tensorflow:loss = 12881.449, step = 201 (0.320 sec) INFO:tensorflow:global_step/sec: 303.863 INFO:tensorflow:loss = 12391.541, step = 301 (0.327 sec) INFO:tensorflow:global_step/sec: 308.782 INFO:tensorflow:loss = 12050.5625, step = 401 (0.326 sec) INFO:tensorflow:global_step/sec: 244.969 INFO:tensorflow:loss = 11766.134, step = 501 (0.407 sec) INFO:tensorflow:global_step/sec: 155.966 INFO:tensorflow:loss = 11509.922, step = 601 (0.641 sec) INFO:tensorflow:global_step/sec: 263.256 INFO:tensorflow:loss = 11272.889, step = 701 (0.379 sec) INFO:tensorflow:global_step/sec: 254.112 INFO:tensorflow:loss = 11051.9795, step = 801 (0.396 sec) INFO:tensorflow:global_step/sec: 292.405 INFO:tensorflow:loss = 10845.855, step = 901 (0.341 sec) INFO:tensorflow:Saving checkpoints for 1000 into train/model.ckpt. INFO:tensorflow:Loss for final step: 5925.9873.
Vous pouvez consulter TensorBoard avec la commande suivante :
activate hello-tf # For MacOS tensorboard --logdir=./train # For Windows tensorboard --logdir=train
Étape 5) Évaluez votre modèle
Vous pouvez évaluer l'ajustement de votre modèle sur l'ensemble de test avec le code ci-dessous :
ev = estimator.evaluate(
input_fn=get_input_fn(test_set,
num_epochs=1,
n_batch = 128,
shuffle=False))
Sortie
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-05-13-01:43:13 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train/model.ckpt-1000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Finished evaluation at 2018-05-13-01:43:13 INFO:tensorflow:Saving dict for global step 1000: average_loss = 32.15896, global_step = 1000, loss = 3215.896
Vous pouvez imprimer la perte avec le code ci-dessous :
loss_score = ev["loss"] print("Loss: {0:f}".format(loss_score))
Sortie
Loss: 3215.895996
Le modèle présente une perte de 3215. Vous pouvez consulter les statistiques récapitulatives pour vous faire une idée de l'ampleur de l'erreur.
training_set['medv'].describe()
Sortie
count 400.000000 mean 22.625500 std 9.572593 min 5.000000 25% 16.600000 50% 21.400000 75% 25.025000 max 50.000000 Name: medv, dtype: float64
D'après les statistiques récapitulatives ci-dessus, le prix moyen d'une maison est de 22 000 $, avec un prix minimum de 5 000 $ et un prix maximum de 50 000 $. La perte indiquée correspondant à l'erreur quadratique moyenne, l'erreur typique dans les unités d'origine est approximativement égale à la racine carrée de 32.16, soit environ 5 700 $.
Étape 6) Faites la prédiction
Enfin, vous pouvez utiliser la méthode d'estimation TensorFlow predict pour estimer la valeur de six maisons à Boston.
y = estimator.predict(
input_fn=get_input_fn(prediction_set,
num_epochs=1,
n_batch = 128,
shuffle=False))
Pour imprimer les valeurs estimées, vous pouvez utiliser ce code :
predictions = list(p["predictions"] for p in itertools.islice(y, 6)) print("Predictions: {}".format(str(predictions)))
Sortie
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
Predictions: [array([32.297546], dtype=float32), array([18.96125], dtype=float32), array([27.270979], dtype=float32), array([29.299236], dtype=float32), array([16.436684], dtype=float32), array([21.460876], dtype=float32)]
Le modèle prévoit les valeurs suivantes :
| Maison | Prédiction |
| 1 | 32.29 |
| 2 | 18.96 |
| 3 | 27.27 |
| 4 | 29.29 |
| 5 | 16.43 |
| 6 | 21.46 |
Notez que nous ignorons la valeur réelle de ces six maisons. Dans le tutoriel sur l'apprentissage profond, vous tenterez de surpasser le modèle linéaire.
Solution NumPy
Cette section explique comment entraîner le modèle en utilisant un estimateur NumPy pour alimenter les données. La méthode est la même, à ceci près que vous utiliserez l'estimateur `numpy_input_fn`.
Lisez les trois mêmes fichiers CSV, mais ne conservez que les tableaux NumPy bruts avec .values.
training_set_n = pd.read_csv("E:/boston_train.csv").values test_set_n = pd.read_csv("E:/boston_test.csv").values prediction_set_n = pd.read_csv("E:/boston_predict.csv").values
Étape 1) Importez les données
Il faut d'abord distinguer les variables explicatives de leurs étiquettes. Cette distinction doit être faite pour les données d'entraînement et d'évaluation. Il est plus rapide de définir une fonction pour segmenter les données.
def prepare_data(df): X_train = df[:, :-3] y_train = df[:,-3] return X_train, y_train
Vous pouvez utiliser cette fonction pour séparer l'étiquette des caractéristiques des ensembles de données d'entraînement et d'évaluation.
X_train, y_train = prepare_data(training_set_n) X_test, y_test = prepare_data(test_set_n)
Vous devez exclure la dernière colonne de l'ensemble de données de prédiction car elle ne contient que des valeurs NaN.
x_predict = prediction_set_n[:, :-2]
Vérifiez la forme du tableau. Notez que l'étiquette ne doit pas avoir de deuxième dimension, c'est-à-dire (400,).
print(X_train.shape, y_train.shape, x_predict.shape)
Sortie
(400, 9) (400,) (6, 9)
Vous pouvez construire les colonnes d'entités comme suit :
feature_columns = [ tf.feature_column.numeric_column('x', shape=X_train.shape[1:])]
L'estimateur est défini comme précédemment : vous spécifiez les colonnes de caractéristiques et l'emplacement où enregistrer le graphique.
estimator = tf.estimator.LinearRegressor(
feature_columns=feature_columns,
model_dir="train1")
Sortie
INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'train1', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1a218d8f28>, '_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}
Vous pouvez utiliser l'estimateur NumPy pour alimenter le modèle avec les données, puis l'entraîner. Notez que la fonction `input_fn` est définie au préalable pour faciliter la lecture.
# Train the estimator train_input = tf.estimator.inputs.numpy_input_fn( x={"x": X_train}, y=y_train, batch_size=128, shuffle=False, num_epochs=None) estimator.train(input_fn = train_input,steps=5000)
Sortie
INFO:tensorflow:Calling model_fn. 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:Saving checkpoints for 1 into train1/model.ckpt. INFO:tensorflow:loss = 83729.64, step = 1 INFO:tensorflow:global_step/sec: 490.057 INFO:tensorflow:loss = 13909.656, step = 101 (0.206 sec) INFO:tensorflow:global_step/sec: 788.986 INFO:tensorflow:loss = 12881.45, step = 201 (0.126 sec) INFO:tensorflow:global_step/sec: 736.339 INFO:tensorflow:loss = 12391.541, step = 301 (0.136 sec) INFO:tensorflow:global_step/sec: 383.305 INFO:tensorflow:loss = 12050.561, step = 401 (0.260 sec) INFO:tensorflow:global_step/sec: 859.832 INFO:tensorflow:loss = 11766.133, step = 501 (0.117 sec) INFO:tensorflow:global_step/sec: 804.394 INFO:tensorflow:loss = 11509.918, step = 601 (0.125 sec) INFO:tensorflow:global_step/sec: 753.059 INFO:tensorflow:loss = 11272.891, step = 701 (0.134 sec) INFO:tensorflow:global_step/sec: 402.165 INFO:tensorflow:loss = 11051.979, step = 801 (0.248 sec) INFO:tensorflow:global_step/sec: 344.022 INFO:tensorflow:loss = 10845.854, step = 901 (0.288 sec) INFO:tensorflow:Saving checkpoints for 1000 into train1/model.ckpt. INFO:tensorflow:Loss for final step: 5925.985. Out[23]: <tensorflow.python.estimator.canned.linear.LinearRegressor at 0x1a1b6ea860>
Vous répétez la même étape avec une fonction d'entrée différente pour évaluer votre modèle.
eval_input = tf.estimator.inputs.numpy_input_fn(
x={"x": X_test},
y=y_test,
shuffle=False,
batch_size=128,
num_epochs=1)
estimator.evaluate(eval_input,steps=None)
Sortie
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-05-13-01:44:00 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train1/model.ckpt-1000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Finished evaluation at 2018-05-13-01:44:00 INFO:tensorflow:Saving dict for global step 1000: average_loss = 32.158947, global_step = 1000, loss = 3215.8945 Out[24]: {'average_loss': 32.158947, 'global_step': 1000, 'loss': 3215.8945}
Enfin, vous pouvez calculer la prédiction. Elle devrait être similaire au résultat obtenu avec Pandas.
test_input = tf.estimator.inputs.numpy_input_fn(
x={"x": x_predict},
batch_size=128,
num_epochs=1,
shuffle=False)
y = estimator.predict(test_input)
predictions = list(p["predictions"] for p in itertools.islice(y, 6))
print("Predictions: {}".format(str(predictions)))
Sortie
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train1/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
Predictions: [array([32.297546], dtype=float32), array([18.961248], dtype=float32), array([27.270979], dtype=float32), array([29.299242], dtype=float32), array([16.43668], dtype=float32), array([21.460878], dtype=float32)]
Solution TensorFlow
La dernière section est consacrée à une pure TensorFlow Solution. Cette méthode est légèrement plus compliquée que les deux autres.
Notez que si vous utilisez un Jupyter cahierVous devez redémarrer et effacer le noyau pour exécuter cette session.
TensorFlow propose un outil performant pour acheminer les données vers le pipeline. Dans cette section, vous allez créer vous-même la fonction `input_fn`.
Étape 1) Définir le chemin et le format des données
Vous devez tout d'abord déclarer deux variables contenant le chemin d'accès aux fichiers CSV. Notez que vous avez deux fichiers : un pour l'ensemble d'entraînement et un pour l'ensemble de test.
import tensorflow as tf
df_train = "E:/boston_train.csv"
df_eval = "E:/boston_test.csv"
Ensuite, vous devez définir les colonnes du fichier CSV que vous souhaitez utiliser. Nous les utiliserons toutes. Enfin, vous devez déclarer le type de chaque variable.
Les variables flottantes sont définies par [0.]
COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio", "medv"] RECORDS_ALL = [[0.0], [0.0], [0.0], [0.0],[0.0],[0.0],[0.0],[0.0],[0.0],[0.0]]
Étape 2) Définir la fonction input_fn
La fonction peut être divisée en trois parties :
- Importez les données
- Créer l'itérateur
- Consommer les données
Vous trouverez ci-dessous le code complet définissant la fonction. Ce code sera expliqué ultérieurement.
def input_fn(data_file, batch_size, num_epoch = None): # Step 1 def parse_csv(value): columns = tf.decode_csv(value, record_defaults= RECORDS_ALL) features = dict(zip(COLUMNS, columns)) #labels = features.pop('median_house_value') labels = features.pop('medv') return features, labels # Extract lines from input files using the Dataset API. dataset = (tf.data.TextLineDataset(data_file) # Read text file .skip(1) # Skip header row .map(parse_csv)) dataset = dataset.repeat(num_epoch) dataset = dataset.batch(batch_size) # Step 3 iterator = dataset.make_one_shot_iterator() features, labels = iterator.get_next() return features, labels
Importez les données
Pour un fichier CSV, la méthode dataset lit une ligne à la fois. Pour créer le jeu de données, vous devez utiliser l'objet TextLineJeu de données. Votre jeu de données comporte un en-tête ; vous devez donc utiliser `skip(1)` pour ignorer la première ligne. À ce stade, vous lisez uniquement les données, sans tenir compte de l'en-tête. Pour alimenter le modèle, vous devez séparer les caractéristiques de leurs étiquettes. La méthode utilisée pour appliquer une transformation aux données est `map`.
Cette méthode appelle une fonction que vous créerez afin de lui indiquer comment transformer les données. En résumé, vous devez transmettre les données à la fonction. TextLineObjet Dataset, exclure l'en-tête et appliquer une transformation commandée par une fonction.
Code explication
- tf.data.TextLineDataset(data_file) : cette ligne lit le fichier CSV
- .skip(1) : ignore l’en-tête
- .map(parse_csv) : analyse les enregistrements et les convertit en tenseurs
Vous devez définir une fonction pour donner des instructions à l'objet carte. Vous pouvez appeler cette fonction parse_csv.
Cette fonction analyse le fichier CSV avec la méthode `tf.decode_csv` et déclare les caractéristiques et les étiquettes. Les caractéristiques peuvent être déclarées sous forme de dictionnaire ou de tuple. Nous utilisons ici la méthode du dictionnaire, plus pratique.
Code explication
- tf.decode_csv(value, record_defaults= RECORDS_ALL) : la méthode decode_csv utilise la sortie du TextLineJeu de données pour lire le fichier CSV. `record_defaults` indique à TensorFlow les types de colonnes. Dans TensorFlow 2.x, ce symbole se trouve dans `tf.io.decode_csv`.
- dict(zip(COLUMNS, columns)): remplit le dictionnaire avec toutes les colonnes extracted au cours de ce traitement de données
- features.pop('medv') : exclut la variable cible des variables de caractéristiques et crée une variable d'étiquette
Le jeu de données nécessite des éléments supplémentaires pour alimenter les tenseurs de manière itérative. En effet, il est nécessaire d'ajouter la méthode `repeat` pour permettre au jeu de données de continuer à alimenter le modèle indéfiniment. Sans cette méthode, le modèle n'effectuera qu'une seule itération et générera une erreur, faute de nouvelles données dans le pipeline.
Ensuite, vous pouvez contrôler la taille des lots grâce à la méthode `batch`. Cela signifie que vous indiquez au jeu de données la quantité de données à transmettre au pipeline à chaque itération. Si vous définissez une taille de lot importante, le modèle sera lent.
Étape 3) Créer l'itérateur
Vous êtes maintenant prêt pour la deuxième étape : créer un itérateur pour renvoyer les éléments de l'ensemble de données.
La manière la plus simple de créer un opérateur consiste à utiliser la méthode make_one_shot_iterator.
Après cela, vous pouvez créer les fonctionnalités et les étiquettes à partir de l'itérateur.
Étape 4) Consommer les données
Vous pouvez vérifier le comportement de la fonction input_fn. Vous devez l'appeler dans une session pour utiliser les données. Essayez avec une taille de lot égale à 1.
Notez qu'il affiche les caractéristiques dans un dictionnaire et l'étiquette sous forme de tableau.
Il affichera la première ligne du fichier CSV. Vous pouvez exécuter ce code plusieurs fois avec différentes tailles de lots.
next_batch = input_fn(df_train, batch_size = 1, num_epoch = None) with tf.Session() as sess: first_batch = sess.run(next_batch) print(first_batch)
Sortie
({'crim': array([2.3004], dtype=float32), 'zn': array([0.], dtype=float32), 'indus': array([19.58], dtype=float32), 'nox': array([0.605], dtype=float32), 'rm': array([6.319], dtype=float32), 'age': array([96.1], dtype=float32), 'dis': array([2.1], dtype=float32), 'tax': array([403.], dtype=float32), 'ptratio': array([14.7], dtype=float32)}, array([23.8], dtype=float32))
Étape 5) Définir la colonne de fonctionnalités
Vous devez définir les colonnes numériques comme suit :
X1= tf.feature_column.numeric_column('crim') X2= tf.feature_column.numeric_column('zn') X3= tf.feature_column.numeric_column('indus') X4= tf.feature_column.numeric_column('nox') X5= tf.feature_column.numeric_column('rm') X6= tf.feature_column.numeric_column('age') X7= tf.feature_column.numeric_column('dis') X8= tf.feature_column.numeric_column('tax') X9= tf.feature_column.numeric_column('ptratio')
Notez qu'il est nécessaire de regrouper toutes les variables dans un même compartiment.
base_columns = [X1, X2, X3,X4, X5, X6,X7, X8, X9]
Étape 6) Construisez le modèle
Vous pouvez entraîner le modèle avec l'estimateur LinearRegressor.
model = tf.estimator.LinearRegressor(feature_columns=base_columns, model_dir='train3')
Sortie
INFO:tensorflow:Using default config. INFO:tensorflow:Using config: {'_model_dir': 'train3', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1820a010f0>, '_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}
Vous devez utiliser un fonction lambda pour vous permettre de spécifier les arguments de la fonction input_fn. Sans fonction lambda, l'entraînement du modèle est impossible.
# Train the estimator model.train(steps =1000, input_fn= lambda : input_fn(df_train,batch_size=128, num_epoch = None))
Sortie
INFO:tensorflow:Calling model_fn. 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:Saving checkpoints for 1 into train3/model.ckpt. INFO:tensorflow:loss = 83729.64, step = 1 INFO:tensorflow:global_step/sec: 72.5646 INFO:tensorflow:loss = 13909.657, step = 101 (1.380 sec) INFO:tensorflow:global_step/sec: 101.355 INFO:tensorflow:loss = 12881.449, step = 201 (0.986 sec) INFO:tensorflow:global_step/sec: 109.293 INFO:tensorflow:loss = 12391.541, step = 301 (0.915 sec) INFO:tensorflow:global_step/sec: 102.235 INFO:tensorflow:loss = 12050.5625, step = 401 (0.978 sec) INFO:tensorflow:global_step/sec: 104.656 INFO:tensorflow:loss = 11766.134, step = 501 (0.956 sec) INFO:tensorflow:global_step/sec: 106.697 INFO:tensorflow:loss = 11509.922, step = 601 (0.938 sec) INFO:tensorflow:global_step/sec: 118.454 INFO:tensorflow:loss = 11272.889, step = 701 (0.844 sec) INFO:tensorflow:global_step/sec: 114.947 INFO:tensorflow:loss = 11051.9795, step = 801 (0.870 sec) INFO:tensorflow:global_step/sec: 111.484 INFO:tensorflow:loss = 10845.855, step = 901 (0.897 sec) INFO:tensorflow:Saving checkpoints for 1000 into train3/model.ckpt. INFO:tensorflow:Loss for final step: 5925.9873. Out[8]: <tensorflow.python.estimator.canned.linear.LinearRegressor at 0x18225eb8d0>
Vous pouvez évaluer l'ajustement de votre modèle sur l'ensemble de test avec le code ci-dessous :
results = model.evaluate(steps =None,input_fn=lambda: input_fn(df_eval, batch_size =128, num_epoch = 1)) for key in results: print(" {}, was: {}".format(key, results[key]))
Sortie
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-05-13-02:06:02 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train3/model.ckpt-1000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Finished evaluation at 2018-05-13-02:06:02 INFO:tensorflow:Saving dict for global step 1000: average_loss = 32.15896, global_step = 1000, loss = 3215.896 average_loss, was: 32.158958435058594 loss, was: 3215.89599609375 global_step, was: 1000
La dernière étape consiste à prédire la valeur de la cible à partir des valeurs de la matrice de caractéristiques. Vous pouvez créer un dictionnaire contenant les valeurs à prédire. Votre modèle comporte neuf caractéristiques ; vous devez donc fournir une valeur pour chacune d'elles. Le modèle effectuera une prédiction pour chacune d'elles.
Dans le code ci-dessous, vous écrivez les valeurs de chaque caractéristique contenue dans le fichier CSV df_predict.
Vous devez écrire une nouvelle fonction `input_fn` car l'ensemble de données ne contient aucune étiquette. Vous pouvez utiliser l'API `from_tensors` de l'objet `Dataset`.
prediction_input = {
'crim': [0.03359,5.09017,0.12650,0.05515,8.15174,0.24522],
'zn': [75.0,0.0,25.0,33.0,0.0,0.0],
'indus': [2.95,18.10,5.13,2.18,18.10,9.90],
'nox': [0.428,0.713,0.453,0.472,0.700,0.544],
'rm': [7.024,6.297,6.762,7.236,5.390,5.782],
'age': [15.8,91.8,43.4,41.1,98.9,71.7],
'dis': [5.4011,2.3682,7.9809,4.0220,1.7281,4.0317],
'tax': [252,666,284,222,666,304],
'ptratio': [18.3,20.2,19.7,18.4,20.2,18.4]
}
def test_input_fn():
dataset = tf.data.Dataset.from_tensors(prediction_input)
return dataset
# Predict all our prediction_input
pred_results = model.predict(input_fn=test_input_fn)
Enfin, vous imprimez les prédictions.
for pred in enumerate(pred_results): print(pred)
Sortie
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train3/model.ckpt-1000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. (0, {'predictions': array([32.297546], dtype=float32)}) (1, {'predictions': array([18.96125], dtype=float32)}) (2, {'predictions': array([27.270979], dtype=float32)}) (3, {'predictions': array([29.299236], dtype=float32)}) (4, {'predictions': array([16.436684], dtype=float32)}) (5, {'predictions': array([21.460876], dtype=float32)}) INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train3/model.ckpt-5000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. (0, {'predictions': array([35.60663], dtype=float32)}) (1, {'predictions': array([22.298521], dtype=float32)}) (2, {'predictions': array([25.74533], dtype=float32)}) (3, {'predictions': array([35.126694], dtype=float32)}) (4, {'predictions': array([17.94416], dtype=float32)}) (5, {'predictions': array([22.606628], dtype=float32)})
Les trois pipelines renvoient les mêmes six prédictions, ce qui confirme que le choix entre Pandas, NumPy et un jeu de données TensorFlow natif est une question de commodité, et non de précision.





