Aide à protéger la Grande barrière de corail avec tensorflow sur Kaggle Rejoignez Défi

Classer les données structurées à l'aide des couches de prétraitement Keras

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

Ce tutoriel montre comment classer des données structurées, telles que les données tabulaires, en utilisant une version simplifiée de l' ensemble de données PetFinder d'une compétition Kaggle stockée dans un fichier CSV.

Vous utiliserez Keras pour définir le modèle et les couches prétraiter Keras comme un pont vers la carte des colonnes dans un fichier CSV aux fonctions utilisées pour former le modèle. Le but est de prédire si un animal de compagnie sera adopté.

Ce tutoriel contient le code complet pour :

  • Chargement d' un fichier CSV dans une trame de données en utilisant pandas géants .
  • La construction d' un pipeline d'entrée en lot et mélanger les lignes à l' aide tf.data . (Visitez tf.data: Construire des conduites d'entrée tensorflow pour plus de détails.)
  • Mappage des colonnes du fichier CSV aux fonctionnalités utilisées pour entraîner le modèle avec les couches de prétraitement Keras.
  • Création, formation et évaluation d'un modèle à l'aide des méthodes intégrées de Keras.

Le mini jeu de données PetFinder.my

Il y a plusieurs milliers de lignes dans le fichier de jeu de données CSV de PetFinder.my mini, où chaque ligne décrit un animal de compagnie (un chien ou un chat) et chaque colonne décrit un attribut, tel que l'âge, la race, la couleur, etc.

Dans le résumé de l'ensemble de données ci-dessous, notez qu'il y a principalement des colonnes numériques et catégorielles. Dans ce tutoriel, vous ne aurez affaire à ces deux types d'entités, laissant tomber Description de (une fonctionnalité de texte libre) et AdoptionSpeed (une fonction de classement) lors du prétraitement des données.

Colonne Description de l'animal Type d'entité Type de données
Type Type d'animal ( Dog , Cat ) Catégorique Chaîne de caractères
Age Âge Numérique Entier
Breed1 Race primaire Catégorique Chaîne de caractères
Color1 Couleur 1 Catégorique Chaîne de caractères
Color2 Couleur 2 Catégorique Chaîne de caractères
MaturitySize Taille à maturité Catégorique Chaîne de caractères
FurLength Longueur de fourrure Catégorique Chaîne de caractères
Vaccinated L'animal a été vacciné Catégorique Chaîne de caractères
Sterilized L'animal a été stérilisé Catégorique Chaîne de caractères
Health État de santé Catégorique Chaîne de caractères
Fee Frais d'adoption Numérique Entier
Description Rédaction de profil Texte Chaîne de caractères
PhotoAmt Nombre total de photos téléchargées Numérique Entier
AdoptionSpeed Vitesse catégorique d'adoption Classification Entier

Importer TensorFlow et d'autres bibliothèques

import numpy as np
import pandas as pd
import tensorflow as tf

from tensorflow.keras import layers
tf.__version__
'2.7.0'

Chargez l'ensemble de données et lisez-le dans un DataFrame pandas

pandas géants est une bibliothèque Python avec de nombreux utilitaires utiles pour le chargement et le travail avec des données structurées. Utilisez tf.keras.utils.get_file pour télécharger et extraire le fichier CSV avec le jeu de données mini - PetFinder.my, et le charger dans une trame de pandas.read_csv données avec pandas.read_csv :

dataset_url = 'http://storage.googleapis.com/download.tensorflow.org/data/petfinder-mini.zip'
csv_file = 'datasets/petfinder-mini/petfinder-mini.csv'

tf.keras.utils.get_file('petfinder_mini.zip', dataset_url,
                        extract=True, cache_dir='.')
dataframe = pd.read_csv(csv_file)
Downloading data from http://storage.googleapis.com/download.tensorflow.org/data/petfinder-mini.zip
1671168/1668792 [==============================] - 0s 0us/step
1679360/1668792 [==============================] - 0s 0us/step

Inspectez l'ensemble de données en vérifiant les cinq premières lignes du DataFrame :

dataframe.head()

Créer une variable cible

La tâche originale de Kaggle PetFinder.my Adoption concours de prévision était de prédire la vitesse à laquelle un animal de compagnie sera adoptée (par exemple , dans la première semaine, le premier mois, les trois premiers mois, et ainsi de suite).

Dans ce tutoriel, vous allez simplifier la tâche en la transformant en un problème de classification binaire, où il vous suffit de prédire si un animal a été adopté ou non.

Après avoir modifié la AdoptionSpeed colonne, 0 indiquera l'animal n'a pas été adopté, et 1 indiquera qu'il était.

# In the original dataset, `'AdoptionSpeed'` of `4` indicates
# a pet was not adopted.
dataframe['target'] = np.where(dataframe['AdoptionSpeed']==4, 0, 1)

# Drop unused features.
dataframe = dataframe.drop(columns=['AdoptionSpeed', 'Description'])

Divisez le DataFrame en ensembles d'entraînement, de validation et de test

L'ensemble de données se trouve dans un seul DataFrame pandas. Divisez-le en ensembles d'entraînement, de validation et de test en utilisant un rapport, par exemple, 80:10:10, respectivement :

train, val, test = np.split(dataframe.sample(frac=1), [int(0.8*len(dataframe)), int(0.9*len(dataframe))])
print(len(train), 'training examples')
print(len(val), 'validation examples')
print(len(test), 'test examples')
9229 training examples
1154 validation examples
1154 test examples

Créer un pipeline d'entrée à l'aide de tf.data

Ensuite, créez une fonction utilitaire qui convertit chaque formation, validation et test dans un ensemble dataframe tf.data.Dataset , puis les remaniements et les lots données.

def df_to_dataset(dataframe, shuffle=True, batch_size=32):
  df = dataframe.copy()
  labels = df.pop('target')
  df = {key: value[:,tf.newaxis] for key, value in dataframe.items()}
  ds = tf.data.Dataset.from_tensor_slices((dict(df), labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=len(dataframe))
  ds = ds.batch(batch_size)
  ds = ds.prefetch(batch_size)
  return ds

Maintenant, utilisez la fonction nouvellement créée ( df_to_dataset ) pour vérifier le format des données du pipeline d' entrée renvoie la fonction d'aide en appelant sur les données de formation, et d' utiliser une petite taille du lot pour maintenir la sortie lisible:

batch_size = 5
train_ds = df_to_dataset(train, batch_size=batch_size)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:4: FutureWarning: Support for multi-dimensional indexing (e.g. `obj[:, None]`) is deprecated and will be removed in a future version.  Convert to a numpy array before indexing instead.
  after removing the cwd from sys.path.
[(train_features, label_batch)] = train_ds.take(1)
print('Every feature:', list(train_features.keys()))
print('A batch of ages:', train_features['Age'])
print('A batch of targets:', label_batch )
Every feature: ['Type', 'Age', 'Breed1', 'Gender', 'Color1', 'Color2', 'MaturitySize', 'FurLength', 'Vaccinated', 'Sterilized', 'Health', 'Fee', 'PhotoAmt', 'target']
A batch of ages: tf.Tensor(
[[ 4]
 [ 1]
 [15]
 [ 3]
 [ 1]], shape=(5, 1), dtype=int64)
A batch of targets: tf.Tensor([0 1 1 0 1], shape=(5,), dtype=int64)

Comme le montre la sortie, l'ensemble d'apprentissage renvoie un dictionnaire de noms de colonnes (à partir du DataFrame) qui correspond aux valeurs de colonne à partir de lignes.

Appliquer les couches de prétraitement Keras

Les couches de prétraitement Keras vous permettent de créer des pipelines de traitement d'entrée natifs Keras, qui peuvent être utilisés comme code de prétraitement indépendant dans des workflows non-Keras, combinés directement avec des modèles Keras et exportés dans le cadre d'un Keras SavedModel.

Dans ce didacticiel, vous utiliserez les quatre couches de prétraitement suivantes pour montrer comment effectuer le prétraitement, le codage des données structurées et l'ingénierie des fonctionnalités :

Vous pouvez en savoir plus sur les couches disponibles dans le travail avec des couches prétraiter guide.

  • Pour connaître les caractéristiques numériques de l'ensemble de données mini - PetFinder.my, vous utiliserez une tf.keras.layers.Normalization couche pour normaliser la distribution des données.
  • Pour les caractéristiques catégoriques, comme animal de compagnie de Type s ( Dog et Cat cordes), vous les transformer en tenseurs encodées multi-chaud avec tf.keras.layers.CategoryEncoding .

Colonnes numériques

Pour chaque fonction numérique dans l'ensemble de données mini - PetFinder.my, vous utiliserez une tf.keras.layers.Normalization couche pour normaliser la distribution des données.

Définissez une nouvelle fonction utilitaire qui renvoie une couche qui applique une normalisation par entité aux entités numériques à l'aide de cette couche de prétraitement Keras :

def get_normalization_layer(name, dataset):
  # Create a Normalization layer for the feature.
  normalizer = layers.Normalization(axis=None)

  # Prepare a Dataset that only yields the feature.
  feature_ds = dataset.map(lambda x, y: x[name])

  # Learn the statistics of the data.
  normalizer.adapt(feature_ds)

  return normalizer

Ensuite, tester la nouvelle fonction en appelant sur le total téléchargé photo animaux caractéristiques de Normaliser 'PhotoAmt' :

photo_count_col = train_features['PhotoAmt']
layer = get_normalization_layer('PhotoAmt', train_ds)
layer(photo_count_col)
<tf.Tensor: shape=(5, 1), dtype=float32, numpy=
array([[-0.8390221 ],
       [ 2.3774517 ],
       [ 0.12592004],
       [-0.5173747 ],
       [-0.19572733]], dtype=float32)>

Colonnes catégorielles

Animal Type de l'ensemble de données sont représentés comme cordes- Dog s et Cat s-qui a besoin d'être codé multi-chaud avant d' être introduit dans le modèle. L' Age caractéristique

Définir une autre nouvelle fonction utilitaire qui retourne une couche qui met en correspondance les valeurs d'un vocabulaire à des indices entiers et code multi-fonctions à l' aide de chaleur les la tf.keras.layers.StringLookup , tf.keras.layers.IntegerLookup et tf.keras.CategoryEncoding prétraitement couches:

def get_category_encoding_layer(name, dataset, dtype, max_tokens=None):
  # Create a layer that turns strings into integer indices.
  if dtype == 'string':
    index = layers.StringLookup(max_tokens=max_tokens)
  # Otherwise, create a layer that turns integer values into integer indices.
  else:
    index = layers.IntegerLookup(max_tokens=max_tokens)

  # Prepare a `tf.data.Dataset` that only yields the feature.
  feature_ds = dataset.map(lambda x, y: x[name])

  # Learn the set of possible values and assign them a fixed integer index.
  index.adapt(feature_ds)

  # Encode the integer indices.
  encoder = layers.CategoryEncoding(num_tokens=index.vocabulary_size())

  # Apply multi-hot encoding to the indices. The lambda function captures the
  # layer, so you can use them, or include them in the Keras Functional model later.
  return lambda feature: encoder(index(feature))

Testez la get_category_encoding_layer fonction en appelant sur animal 'Type' caractéristiques pour les transformer en tenseurs encodées multi-chaud:

test_type_col = train_features['Type']
test_type_layer = get_category_encoding_layer(name='Type',
                                              dataset=train_ds,
                                              dtype='string')
test_type_layer(test_type_col)
<tf.Tensor: shape=(5, 3), dtype=float32, numpy=
array([[0., 1., 0.],
       [0., 0., 1.],
       [0., 1., 0.],
       [0., 0., 1.],
       [0., 1., 0.]], dtype=float32)>

Répétez le processus sur l'animal 'Age' caractéristiques:

test_age_col = train_features['Age']
test_age_layer = get_category_encoding_layer(name='Age',
                                             dataset=train_ds,
                                             dtype='int64',
                                             max_tokens=5)
test_age_layer(test_age_col)
<tf.Tensor: shape=(5, 5), dtype=float32, numpy=
array([[0., 0., 0., 0., 1.],
       [0., 0., 0., 1., 0.],
       [1., 0., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.]], dtype=float32)>

Prétraiter les fonctions sélectionnées sur lesquelles entraîner le modèle

Vous avez appris à utiliser plusieurs types de couches de prétraitement Keras. Ensuite, vous allez :

  • Appliquez les fonctions utilitaires de prétraitement définies précédemment sur 13 caractéristiques numériques et catégorielles du mini-ensemble de données PetFinder.my.
  • Ajoutez toutes les entrées de caractéristiques à une liste.

Comme mentionné au début, pour former le modèle, vous utiliserez le (le numérique de jeu de données mini - PetFinder.my 'PhotoAmt' , 'Fee' ) et catégorique ( 'Age' , 'Type' , 'Color1' , 'Color2' , 'Gender' , 'MaturitySize' , 'FurLength' , 'Vaccinated' , 'Sterilized' , 'Health' , 'Breed1' ) dispose.

Auparavant, vous utilisiez une petite taille de lot pour démontrer le pipeline d'entrée. Créons maintenant un nouveau pipeline d'entrée avec une taille de lot plus importante de 256 :

batch_size = 256
train_ds = df_to_dataset(train, batch_size=batch_size)
val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size)
test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:4: FutureWarning: Support for multi-dimensional indexing (e.g. `obj[:, None]`) is deprecated and will be removed in a future version.  Convert to a numpy array before indexing instead.
  after removing the cwd from sys.path.

Normaliser les caractéristiques numériques (le nombre de photos animaux et les frais d'adoption), et les ajouter à une liste des entrées appelées encoded_features :

all_inputs = []
encoded_features = []

# Numerical features.
for header in ['PhotoAmt', 'Fee']:
  numeric_col = tf.keras.Input(shape=(1,), name=header)
  normalization_layer = get_normalization_layer(header, train_ds)
  encoded_numeric_col = normalization_layer(numeric_col)
  all_inputs.append(numeric_col)
  encoded_features.append(encoded_numeric_col)

Tournez les valeurs catégoriques entier de l'ensemble de données (l'âge animal) dans des indices entiers, effectuer le codage multi-chaud, et ajoutez les entrées de caractéristiques résultant de encoded_features :

age_col = tf.keras.Input(shape=(1,), name='Age', dtype='int64')

encoding_layer = get_category_encoding_layer(name='Age',
                                             dataset=train_ds,
                                             dtype='int64',
                                             max_tokens=5)
encoded_age_col = encoding_layer(age_col)
all_inputs.append(age_col)
encoded_features.append(encoded_age_col)

Répétez la même étape pour les valeurs catégorielles de chaîne :

categorical_cols = ['Type', 'Color1', 'Color2', 'Gender', 'MaturitySize',
                    'FurLength', 'Vaccinated', 'Sterilized', 'Health', 'Breed1']

for header in categorical_cols:
  categorical_col = tf.keras.Input(shape=(1,), name=header, dtype='string')
  encoding_layer = get_category_encoding_layer(name=header,
                                               dataset=train_ds,
                                               dtype='string',
                                               max_tokens=5)
  encoded_categorical_col = encoding_layer(categorical_col)
  all_inputs.append(categorical_col)
  encoded_features.append(encoded_categorical_col)

Créer, compiler et entraîner le modèle

L'étape suivante consiste à créer un modèle en utilisant la Keras API fonctionnelle . Pour la première couche dans votre modèle, fusionner la liste des caractéristiques ENTREES encoded_features -dans un vecteur par concaténation avec tf.keras.layers.concatenate .

all_features = tf.keras.layers.concatenate(encoded_features)
x = tf.keras.layers.Dense(32, activation="relu")(all_features)
x = tf.keras.layers.Dropout(0.5)(x)
output = tf.keras.layers.Dense(1)(x)

model = tf.keras.Model(all_inputs, output)

Configurez le modèle avec Keras Model.compile :

model.compile(optimizer='adam',
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=["accuracy"])

Visualisons le graphique de connectivité :

# Use `rankdir='LR'` to make the graph horizontal.
tf.keras.utils.plot_model(model, show_shapes=True, rankdir="LR")

png

Ensuite, entraînez et testez le modèle :

model.fit(train_ds, epochs=10, validation_data=val_ds)
Epoch 1/10
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/engine/functional.py:559: UserWarning: Input dict contained keys ['target'] which did not match any model input. They will be ignored by the model.
  inputs = self._flatten_to_reference_inputs(inputs)
37/37 [==============================] - 2s 18ms/step - loss: 0.6231 - accuracy: 0.5496 - val_loss: 0.5638 - val_accuracy: 0.7409
Epoch 2/10
37/37 [==============================] - 0s 7ms/step - loss: 0.5758 - accuracy: 0.6770 - val_loss: 0.5473 - val_accuracy: 0.7400
Epoch 3/10
37/37 [==============================] - 0s 7ms/step - loss: 0.5544 - accuracy: 0.7043 - val_loss: 0.5377 - val_accuracy: 0.7383
Epoch 4/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5482 - accuracy: 0.7098 - val_loss: 0.5309 - val_accuracy: 0.7348
Epoch 5/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5424 - accuracy: 0.7100 - val_loss: 0.5268 - val_accuracy: 0.7253
Epoch 6/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5336 - accuracy: 0.7130 - val_loss: 0.5221 - val_accuracy: 0.7331
Epoch 7/10
37/37 [==============================] - 0s 7ms/step - loss: 0.5289 - accuracy: 0.7258 - val_loss: 0.5189 - val_accuracy: 0.7357
Epoch 8/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5280 - accuracy: 0.7146 - val_loss: 0.5165 - val_accuracy: 0.7374
Epoch 9/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5221 - accuracy: 0.7264 - val_loss: 0.5142 - val_accuracy: 0.7331
Epoch 10/10
37/37 [==============================] - 0s 7ms/step - loss: 0.5200 - accuracy: 0.7235 - val_loss: 0.5128 - val_accuracy: 0.7357
<keras.callbacks.History at 0x7f1667fe7790>
loss, accuracy = model.evaluate(test_ds)
print("Accuracy", accuracy)
5/5 [==============================] - 0s 6ms/step - loss: 0.5032 - accuracy: 0.7513
Accuracy 0.7512997984886169

Effectuer une inférence

Le modèle que vous avez développé peut désormais classer une ligne à partir d'un fichier CSV directement après avoir inclus les couches de prétraitement à l'intérieur du modèle lui-même.

Vous pouvez maintenant sauvegarder et recharger le modèle Keras avec Model.save et Model.load_model avant d' effectuer l' inférence sur les nouvelles données:

model.save('my_pet_classifier')
reloaded_model = tf.keras.models.load_model('my_pet_classifier')
2021-11-06 01:29:25.921254: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
WARNING:absl:Function `_wrapped_model` contains input name(s) PhotoAmt, Fee, Age, Type, Color1, Color2, Gender, MaturitySize, FurLength, Vaccinated, Sterilized, Health, Breed1 with unsupported characters which will be renamed to photoamt, fee, age, type, color1, color2, gender, maturitysize, furlength, vaccinated, sterilized, health, breed1 in the SavedModel.
INFO:tensorflow:Assets written to: my_pet_classifier/assets
INFO:tensorflow:Assets written to: my_pet_classifier/assets

Pour obtenir une prédiction pour un nouvel échantillon, vous pouvez simplement appeler la Keras Model.predict méthode. Il y a juste deux choses que vous devez faire :

  1. Enveloppez dans une liste scalaires de façon à avoir une dimension de lot ( Model uniquement des lots de traitement de données, pas de simples échantillons).
  2. Appelez tf.convert_to_tensor sur chaque fonction.
sample = {
    'Type': 'Cat',
    'Age': 3,
    'Breed1': 'Tabby',
    'Gender': 'Male',
    'Color1': 'Black',
    'Color2': 'White',
    'MaturitySize': 'Small',
    'FurLength': 'Short',
    'Vaccinated': 'No',
    'Sterilized': 'No',
    'Health': 'Healthy',
    'Fee': 100,
    'PhotoAmt': 2,
}

input_dict = {name: tf.convert_to_tensor([value]) for name, value in sample.items()}
predictions = reloaded_model.predict(input_dict)
prob = tf.nn.sigmoid(predictions[0])

print(
    "This particular pet had a %.1f percent probability "
    "of getting adopted." % (100 * prob)
)
This particular pet had a 74.4 percent probability of getting adopted.

Prochaines étapes

Pour en savoir plus sur la classification des données structurées, essayez de travailler avec d'autres ensembles de données. Pour améliorer la précision lors de l'entraînement et du test de vos modèles, réfléchissez bien aux fonctionnalités à inclure dans votre modèle et à la manière dont elles doivent être représentées.

Voici quelques suggestions d'ensembles de données :

  • Tensorflow: datasets MovieLens : Un ensemble de classement des films à partir d' un service de recommandation de film.
  • Tensorflow datasets: Qualité du vin : Deux ensembles de données relatives à des variantes rouges et blanches du « Vinho Verde » portugais vin. Vous pouvez également trouver l'ensemble de données sur la qualité du vin rouge Kaggle .
  • Kaggle: arXiv Dataset : Un corpus de 1,7 millions d' articles scientifiques de arXiv, couvrant la physique, l'informatique, les mathématiques, les statistiques, génie électrique, biologie quantitative, et l' économie.