Affichage des données d'image dans TensorBoard

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

Aperçu

Utilisation de l'image de tensorflow API Résumé, vous pouvez facilement connecter tenseurs et des images arbitraires et les afficher dans TensorBoard. Cela peut être extrêmement utile pour échantillonner et examiner vos données d'entrée, ou pour visualiser le poids des couches et générées tenseurs . Vous pouvez également enregistrer les données de diagnostic sous forme d'images qui peuvent être utiles au cours du développement de votre modèle.

Dans ce didacticiel, vous apprendrez à utiliser l'API Image Summary pour visualiser les tenseurs sous forme d'images. Vous apprendrez également à prendre une image arbitraire, à la convertir en tenseur et à la visualiser dans TensorBoard. Vous travaillerez sur un exemple simple mais réel qui utilise des résumés d'images pour vous aider à comprendre les performances de votre modèle.

Installer

try:
  # %tensorflow_version only exists in Colab.
  %tensorflow_version 2.x
except Exception:
  pass

# Load the TensorBoard notebook extension.
%load_ext tensorboard
TensorFlow 2.x selected.
from datetime import datetime
import io
import itertools
from packaging import version

import tensorflow as tf
from tensorflow import keras

import matplotlib.pyplot as plt
import numpy as np
import sklearn.metrics

print("TensorFlow version: ", tf.__version__)
assert version.parse(tf.__version__).release[0] >= 2, \
    "This notebook requires TensorFlow 2.0 or above."
TensorFlow version:  2.2

Télécharger la base de données Fashion-MNIST

Vous allez construire un réseau simple de neurones aux images Classifier dans le la mode-MNIST ensemble de données. Cet ensemble de données se compose de 70 000 images en niveaux de gris 28x28 de produits de mode de 10 catégories, avec 7 000 images par catégorie.

Tout d'abord, téléchargez les données :

# Download the data. The data is already divided into train and test.
# The labels are integers representing classes.
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = \
    fashion_mnist.load_data()

# Names of the integer classes, i.e., 0 -> T-short/top, 1 -> Trouser, etc.
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 
    'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step

Visualiser une seule image

Pour comprendre le fonctionnement de l'API Image Summary, vous allez maintenant simplement enregistrer la première image d'entraînement de votre ensemble d'entraînement dans TensorBoard.

Avant de faire cela, examinez la forme de vos données d'entraînement :

print("Shape: ", train_images[0].shape)
print("Label: ", train_labels[0], "->", class_names[train_labels[0]])
Shape:  (28, 28)
Label:  9 -> Ankle boot

Notez que la forme de chaque image dans l'ensemble de données est un tenseur de forme de rang 2 (28, 28), représentant la hauteur et la largeur.

Cependant, tf.summary.image() attend un tenseur de rang 4 contenant (batch_size, height, width, channels) . Par conséquent, les tenseurs doivent être remodelés.

Vous vous connectez une seule image, de sorte batch_size est 1. Les images sont en niveaux de gris, donc définir des channels à 1.

# Reshape the image for the Summary API.
img = np.reshape(train_images[0], (-1, 28, 28, 1))

Vous êtes maintenant prêt à enregistrer cette image et à l'afficher dans TensorBoard.

# Clear out any prior log data.
!rm -rf logs

# Sets up a timestamped log directory.
logdir = "logs/train_data/" + datetime.now().strftime("%Y%m%d-%H%M%S")
# Creates a file writer for the log directory.
file_writer = tf.summary.create_file_writer(logdir)

# Using the file writer, log the reshaped image.
with file_writer.as_default():
  tf.summary.image("Training data", img, step=0)

Maintenant, utilisez TensorBoard pour examiner l'image. Attendez quelques secondes que l'interface utilisateur démarre.

%tensorboard --logdir logs/train_data

L'onglet "Images" affiche l'image que vous venez d'enregistrer. C'est une "bottine".

L'image est mise à l'échelle à une taille par défaut pour une visualisation plus facile. Si vous souhaitez afficher l'image originale non mise à l'échelle, cochez la case "Afficher la taille réelle de l'image" en haut à gauche.

Jouez avec les curseurs de luminosité et de contraste pour voir comment ils affectent les pixels de l'image.

Visualisation de plusieurs images

L'enregistrement d'un tenseur est génial, mais que se passe-t-il si vous vouliez enregistrer plusieurs exemples d'entraînement ?

Il suffit d' indiquer le nombre d'images que vous souhaitez enregistrer lorsque les données passant à tf.summary.image() .

with file_writer.as_default():
  # Don't forget to reshape.
  images = np.reshape(train_images[0:25], (-1, 28, 28, 1))
  tf.summary.image("25 training data examples", images, max_outputs=25, step=0)

%tensorboard --logdir logs/train_data

Enregistrement de données d'image arbitraires

Que faire si vous voulez visualiser une image qui n'est pas un tenseur, comme une image générée par matplotlib ?

Vous avez besoin d'un code passe-partout pour convertir le tracé en un tenseur, mais après cela, vous êtes prêt à partir.

Dans le code ci - dessous, vous ouvrez une session les 25 premières images comme une grille agréable à l' aide de matplotlib subplot() la fonction. Vous verrez ensuite la grille dans TensorBoard :

# Clear out prior logging data.
!rm -rf logs/plots

logdir = "logs/plots/" + datetime.now().strftime("%Y%m%d-%H%M%S")
file_writer = tf.summary.create_file_writer(logdir)

def plot_to_image(figure):
  """Converts the matplotlib plot specified by 'figure' to a PNG image and
  returns it. The supplied figure is closed and inaccessible after this call."""
  # Save the plot to a PNG in memory.
  buf = io.BytesIO()
  plt.savefig(buf, format='png')
  # Closing the figure prevents it from being displayed directly inside
  # the notebook.
  plt.close(figure)
  buf.seek(0)
  # Convert PNG buffer to TF image
  image = tf.image.decode_png(buf.getvalue(), channels=4)
  # Add the batch dimension
  image = tf.expand_dims(image, 0)
  return image

def image_grid():
  """Return a 5x5 grid of the MNIST images as a matplotlib figure."""
  # Create a figure to contain the plot.
  figure = plt.figure(figsize=(10,10))
  for i in range(25):
    # Start next subplot.
    plt.subplot(5, 5, i + 1, title=class_names[train_labels[i]])
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)

  return figure

# Prepare the plot
figure = image_grid()
# Convert to image and log
with file_writer.as_default():
  tf.summary.image("Training data", plot_to_image(figure), step=0)

%tensorboard --logdir logs/plots

Construire un classificateur d'images

Maintenant, rassemblez tout cela avec un exemple réel. Après tout, vous êtes ici pour faire du machine learning et non pour tracer de jolies images !

Vous allez utiliser des résumés d'images pour comprendre les performances de votre modèle tout en entraînant un classificateur simple pour l'ensemble de données Fashion-MNIST.

Tout d'abord, créez un modèle très simple et compilez-le, en configurant l'optimiseur et la fonction de perte. L'étape de compilation spécifie également que vous souhaitez enregistrer la précision du classificateur en cours de route.

model = keras.models.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)),
    keras.layers.Dense(32, activation='relu'),
    keras.layers.Dense(10, activation='softmax')
])

model.compile(
    optimizer='adam', 
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)

Lorsque la formation d' un classificateur, il est utile de voir la matrice de confusion . La matrice de confusion vous donne une connaissance détaillée des performances de votre classificateur sur les données de test.

Définissez une fonction qui calcule la matrice de confusion. Vous allez utiliser une pratique scikit-learn fonction de le faire, puis tracer à l'aide matplotlib.

def plot_confusion_matrix(cm, class_names):
  """
  Returns a matplotlib figure containing the plotted confusion matrix.

  Args:
    cm (array, shape = [n, n]): a confusion matrix of integer classes
    class_names (array, shape = [n]): String names of the integer classes
  """
  figure = plt.figure(figsize=(8, 8))
  plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
  plt.title("Confusion matrix")
  plt.colorbar()
  tick_marks = np.arange(len(class_names))
  plt.xticks(tick_marks, class_names, rotation=45)
  plt.yticks(tick_marks, class_names)

  # Compute the labels from the normalized confusion matrix.
  labels = np.around(cm.astype('float') / cm.sum(axis=1)[:, np.newaxis], decimals=2)

  # Use white text if squares are dark; otherwise black.
  threshold = cm.max() / 2.
  for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
    color = "white" if cm[i, j] > threshold else "black"
    plt.text(j, i, labels[i, j], horizontalalignment="center", color=color)

  plt.tight_layout()
  plt.ylabel('True label')
  plt.xlabel('Predicted label')
  return figure

Vous êtes maintenant prêt à entraîner le classificateur et à consigner régulièrement la matrice de confusion en cours de route.

Voici ce que vous ferez :

  1. Créez le rappel Keras TensorBoard pour enregistrer des métriques de base
  2. Créer un Keras LambdaCallback pour connecter la matrice de confusion à la fin de chaque époque
  3. Entraînez le modèle à l'aide de Model.fit(), en vous assurant de passer les deux rappels

Au fur et à mesure que la formation progresse, faites défiler vers le bas pour voir TensorBoard démarrer.

# Clear out prior logging data.
!rm -rf logs/image

logdir = "logs/image/" + datetime.now().strftime("%Y%m%d-%H%M%S")
# Define the basic TensorBoard callback.
tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir)
file_writer_cm = tf.summary.create_file_writer(logdir + '/cm')
def log_confusion_matrix(epoch, logs):
  # Use the model to predict the values from the validation dataset.
  test_pred_raw = model.predict(test_images)
  test_pred = np.argmax(test_pred_raw, axis=1)

  # Calculate the confusion matrix.
  cm = sklearn.metrics.confusion_matrix(test_labels, test_pred)
  # Log the confusion matrix as an image summary.
  figure = plot_confusion_matrix(cm, class_names=class_names)
  cm_image = plot_to_image(figure)

  # Log the confusion matrix as an image summary.
  with file_writer_cm.as_default():
    tf.summary.image("Confusion Matrix", cm_image, step=epoch)

# Define the per-epoch callback.
cm_callback = keras.callbacks.LambdaCallback(on_epoch_end=log_confusion_matrix)
# Start TensorBoard.
%tensorboard --logdir logs/image

# Train the classifier.
model.fit(
    train_images,
    train_labels,
    epochs=5,
    verbose=0, # Suppress chatty output
    callbacks=[tensorboard_callback, cm_callback],
    validation_data=(test_images, test_labels),
)

Notez que la précision augmente à la fois sur les ensembles de train et de validation. C'est bon signe. Mais comment le modèle fonctionne-t-il sur des sous-ensembles spécifiques de données ?

Sélectionnez l'onglet "Images" pour visualiser vos matrices de confusion enregistrées. Cochez "Afficher la taille réelle de l'image" en haut à gauche pour voir la matrice de confusion en taille réelle.

Par défaut, le tableau de bord affiche le résumé de l'image pour la dernière étape ou époque enregistrée. Utilisez le curseur pour afficher les matrices de confusion antérieures. Remarquez comment la matrice change de manière significative au fur et à mesure que l'entraînement progresse, avec des carrés plus sombres fusionnant le long de la diagonale et le reste de la matrice tendant vers 0 et blanc. Cela signifie que votre classificateur s'améliore au fur et à mesure que l'entraînement progresse ! Bon travail!

La matrice de confusion montre que ce modèle simple pose quelques problèmes. Malgré les grands progrès, les chemises, les t-shirts et les pulls se confondent. Le modèle a besoin de plus de travail.

Si vous êtes intéressé, essayer d'améliorer ce modèle avec un réseau convolutionnel (CNN).