Visualización de datos de imágenes en TensorBoard

Ver en TensorFlow.org Ejecutar en Google Colab Ver fuente en GitHub Descargar cuaderno

Descripción general

Utilizando el API Resumen TensorFlow imagen, puede conectarse fácilmente tensores e imágenes arbitrarias y verlos en TensorBoard. Esto puede ser extremadamente útil para muestrear y analizar los datos de entrada, o para visualizar los pesos de capa y tensores generados . También puede registrar datos de diagnóstico como imágenes que pueden ser útiles en el curso del desarrollo de su modelo.

En este tutorial, aprenderá a utilizar la API de resumen de imágenes para visualizar tensores como imágenes. También aprenderá a tomar una imagen arbitraria, convertirla en un tensor y visualizarla en TensorBoard. Trabajará con un ejemplo simple pero real que utiliza resúmenes de imágenes para ayudarlo a comprender el rendimiento de su modelo.

Configuración

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

Descargue el conjunto de datos Fashion-MNIST

Usted va a construir una red neuronal simple de imágenes classify de la la moda-MNIST conjunto de datos. Este conjunto de datos consta de 70.000 imágenes en escala de grises de 28x28 de productos de moda de 10 categorías, con 7.000 imágenes por categoría.

Primero, descargue los datos:

# 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

Visualizando una sola imagen

Para comprender cómo funciona la API de resumen de imágenes, ahora simplemente registrará la primera imagen de entrenamiento en su conjunto de entrenamiento en TensorBoard.

Antes de hacer eso, examine la forma de sus datos de entrenamiento:

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

Observe que la forma de cada imagen en el conjunto de datos es un tensor de forma de rango 2 (28, 28), que representa la altura y el ancho.

Sin embargo, tf.summary.image() espera un tensor de rango-4 que contiene (batch_size, height, width, channels) . Por lo tanto, es necesario remodelar los tensores.

Usted es el único registro de imagen, por lo batch_size es 1. Las imágenes son en escala de grises, por lo que establecer channels a 1.

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

Ahora está listo para registrar esta imagen y verla en 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)

Ahora, use TensorBoard para examinar la imagen. Espere unos segundos a que la interfaz de usuario comience a funcionar.

%tensorboard --logdir logs/train_data

La pestaña "Imágenes" muestra la imagen que acaba de iniciar sesión. Es una "bota de tobillo".

La imagen se escala a un tamaño predeterminado para facilitar la visualización. Si desea ver la imagen original sin escala, marque "Mostrar tamaño de imagen real" en la esquina superior izquierda.

Juega con los controles deslizantes de brillo y contraste para ver cómo afectan los píxeles de la imagen.

Visualización de múltiples imágenes

Registrar un tensor es genial, pero ¿y si quisiera registrar varios ejemplos de entrenamiento?

Sólo tiene que especificar el número de imágenes que desea iniciar sesión al pasar los datos a 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

Registro de datos de imágenes arbitrarios

¿Qué pasa si desea visualizar una imagen que no es un tensor, tal como una imagen generada por matplotlib ?

Necesita un código repetitivo para convertir la trama en un tensor, pero después de eso, está listo para comenzar.

En el siguiente código, podrás registrar los primeros 25 imágenes como una rejilla agradable usando matplotlib de subplot() función. Luego verá la cuadrícula en 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

Construyendo un clasificador de imágenes

Ahora pon todo esto junto con un ejemplo real. Después de todo, estás aquí para hacer aprendizaje automático y no para trazar imágenes bonitas.

Utilizará resúmenes de imágenes para comprender qué tan bien le está yendo a su modelo mientras entrena un clasificador simple para el conjunto de datos Fashion-MNIST.

Primero, cree un modelo muy simple y compílelo, configurando el optimizador y la función de pérdida. El paso de compilación también especifica que desea registrar la precisión del clasificador a lo largo del camino.

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']
)

Cuando el entrenamiento de un clasificador, es útil para ver la matriz de confusión . La matriz de confusión le brinda un conocimiento detallado de cómo se está desempeñando su clasificador en los datos de prueba.

Defina una función que calcule la matriz de confusión. Vamos a usar un cómodo scikit-learn función para hacer esto, y luego trazar usando 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

Ahora está listo para entrenar al clasificador y registrar regularmente la matriz de confusión a lo largo del camino.

Esto es lo que harás:

  1. Crear la devolución de llamada Keras TensorBoard a registrar métricas básicas
  2. Crear un Keras LambdaCallback para registrar la matriz de confusión al final de cada época
  3. Entrene el modelo usando Model.fit (), asegurándose de pasar ambas devoluciones de llamada

A medida que avanza el entrenamiento, desplácese hacia abajo para ver cómo se inicia TensorBoard.

# 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),
)

Tenga en cuenta que la precisión aumenta tanto en el tren como en los conjuntos de validación. Buena seńal. Pero, ¿cómo se está desempeñando el modelo en subconjuntos específicos de datos?

Seleccione la pestaña "Imágenes" para visualizar sus matrices de confusión registradas. Marque "Mostrar tamaño de imagen real" en la parte superior izquierda para ver la matriz de confusión a tamaño completo.

De forma predeterminada, el panel muestra el resumen de la imagen del último paso o época registrada. Utilice el control deslizante para ver matrices de confusión anteriores. Observe cómo la matriz cambia significativamente a medida que avanza el entrenamiento, los cuadrados más oscuros se fusionan a lo largo de la diagonal y el resto de la matriz tiende hacia el 0 y el blanco. ¡Esto significa que su clasificador está mejorando a medida que avanza el entrenamiento! ¡Buen trabajo!

La matriz de confusión muestra que este modelo simple tiene algunos problemas. A pesar del gran progreso, las camisas, camisetas y suéteres se están confundiendo entre sí. El modelo necesita más trabajo.

Si está interesado, tratar de mejorar este modelo con una red de convolución (CNN).