Wyświetlanie danych obrazu w TensorBoard

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

Przegląd

Korzystanie z TensorFlow obrazu Podsumowanie API można tensorów i dowolnych obrazów łatwo zalogować się i wyświetlić je w TensorBoard. To może być bardzo pomocne, aby spróbować i sprawdzić swoje dane wejściowe lub wizualizację ciężary warstwy i generowanych tensorów . Możesz również rejestrować dane diagnostyczne jako obrazy, które mogą być pomocne w trakcie opracowywania modelu.

W tym samouczku dowiesz się, jak używać interfejsu Image Summary API do wizualizacji tensorów jako obrazów. Dowiesz się również, jak zrobić dowolny obraz, przekonwertować go na tensor i zwizualizować go w TensorBoard. Poznasz prosty, ale prawdziwy przykład, który wykorzystuje podsumowania obrazów, aby pomóc Ci zrozumieć, jak działa Twój model.

Ustawiać

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

Pobierz zestaw danych Fashion-MNIST

Masz zamiar zbudować prostą sieć neuronową do klasyfikacji obrazów w tej Fashion-MNIST zbiorze. Ten zbiór danych składa się z 70 000 obrazów 28 x 28 w skali szarości produktów modowych z 10 kategorii, z 7000 obrazów na kategorię.

Najpierw pobierz dane:

# 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

Wizualizacja pojedynczego obrazu

Aby zrozumieć, jak działa interfejs Image Summary API, zarejestruj teraz pierwszy obraz szkoleniowy w zestawie szkoleniowym w TensorBoard.

Zanim to zrobisz, sprawdź kształt swoich danych treningowych:

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

Zauważ, że kształt każdego obrazu w zestawie danych jest tensorem kształtu rzędu 2 (28, 28), reprezentującym wysokość i szerokość.

Jednakże tf.summary.image() oczekuje szeregowych 4 tensor zawierający (batch_size, height, width, channels) . Dlatego tensory wymagają przekształcenia.

Jesteś rejestrowania tylko jeden obraz, tak batch_size to 1. Obrazy są w skali szarości, więc ustawić channels na 1.

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

Jesteś teraz gotowy do zalogowania tego obrazu i wyświetlenia go w 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)

Teraz użyj TensorBoard do zbadania obrazu. Poczekaj kilka sekund, aż interfejs się uruchomi.

%tensorboard --logdir logs/train_data

Zakładka "Obrazy" wyświetla obraz, który właśnie zarejestrowałeś. To „buty za kostkę”.

Obraz jest skalowany do rozmiaru domyślnego, co ułatwia przeglądanie. Jeśli chcesz zobaczyć nieskalowany oryginalny obraz, zaznacz „Pokaż rzeczywisty rozmiar obrazu” w lewym górnym rogu.

Pobaw się suwakami jasności i kontrastu, aby zobaczyć, jak wpływają one na piksele obrazu.

Wizualizacja wielu obrazów

Rejestrowanie jednego tensora jest świetne, ale co, jeśli chcesz zarejestrować wiele przykładów treningu?

Wystarczy określić liczbę zdjęć, które chcesz zalogować gdy przekazywanie danych do 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

Rejestrowanie dowolnych danych obrazu

Co zrobić, jeśli chcesz wizualizować obraz, który nie jest tensor, takich jak obraz generowany przez matplotlib ?

Potrzebujesz jakiegoś standardowego kodu, aby przekonwertować fabułę na tensor, ale potem możesz już iść.

W poniższym kodzie, musisz się zalogować pierwsze 25 zdjęć jako siatki ładnym użyciu matplotlib za subplot() funkcji. Następnie zobaczysz siatkę w 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

Budowanie klasyfikatora obrazu

Teraz połącz to wszystko razem z prawdziwym przykładem. W końcu jesteś tutaj, aby uczyć się maszyn, a nie kreślić ładne obrazki!

Użyjesz podsumowań obrazów, aby zrozumieć, jak dobrze radzi sobie Twój model, podczas trenowania prostego klasyfikatora dla zbioru danych Fashion-MNIST.

Najpierw utwórz bardzo prosty model i skompiluj go, konfigurując optymalizator i funkcję straty. Krok kompilacji określa również, że po drodze chcesz rejestrować dokładność klasyfikatora.

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

Podczas szkolenia klasyfikatora, jest to przydatne, aby zobaczyć matrycę zamieszanie . Macierz pomyłek zapewnia szczegółową wiedzę o tym, jak Twój klasyfikator radzi sobie z danymi testowymi.

Zdefiniuj funkcję, która oblicza macierz pomyłek. Będziesz korzystać z dogodnym scikit-learn funkcję, aby to zrobić, a następnie wykreślić ją za pomocą 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

Jesteś teraz gotowy do trenowania klasyfikatora i regularnego rejestrowania po drodze macierzy pomyłek.

Oto, co zrobisz:

  1. Tworzenie zwrotnego Keras TensorBoard do logowania podstawowe dane
  2. Tworzenie Keras LambdaCallback zalogować matrycę zamieszanie na końcu każdej epoce
  3. Wytrenuj model za pomocą Model.fit(), upewniając się, że przekazujesz oba wywołania zwrotne

W miarę postępu treningu przewiń w dół, aby zobaczyć uruchamianie 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),
)

Zauważ, że dokładność rośnie zarówno w zestawie pociągowym, jak i walidacyjnym. To dobry znak. Ale jak model radzi sobie z określonymi podzbiorami danych?

Wybierz kartę „Obrazy”, aby zwizualizować zarejestrowane macierze pomyłek. Zaznacz „Pokaż rzeczywisty rozmiar obrazu” w lewym górnym rogu, aby zobaczyć macierz pomyłek w pełnym rozmiarze.

Domyślnie pulpit wyświetla podsumowanie obrazu dla ostatniego zarejestrowanego kroku lub epoki. Użyj suwaka, aby wyświetlić wcześniejsze macierze pomyłek. Zwróć uwagę, jak matryca zmienia się znacząco wraz z postępem treningu, przy czym ciemniejsze kwadraty łączą się wzdłuż przekątnej, a reszta matrycy zmierza w kierunku 0 i bieli. Oznacza to, że Twój klasyfikator poprawia się wraz z postępem treningu! Świetna robota!

Macierz pomyłek pokazuje, że ten prosty model ma pewne problemy. Pomimo wielkiego postępu, koszule, T-shirty i swetry są ze sobą mylone. Model wymaga więcej pracy.

Jeśli jesteś zainteresowany, spróbuj poprawić ten model z sieci splotowego (CNN).