TensorBoard: visualización del entrenamiento

Intermedio
TensorFlow
TensorFlow
Actualizado: 18/04/2026

¿Qué es TensorBoard?

TensorBoard es la herramienta de visualización oficial del ecosistema TensorFlow. Permite monitorizar en tiempo real el proceso de entrenamiento y depurar modelos de deep learning a través de una interfaz web.

Sus funcionalidades principales incluyen:

  • Scalars: curvas de pérdida, métricas por época/paso.
  • Graphs: grafo computacional del modelo.
  • Histograms: distribución de pesos y sesgos a lo largo del tiempo.
  • Images: visualización de imágenes de entrada o activaciones.
  • Projector: visualización de embeddings en 2D/3D (PCA, t-SNE).
  • Profile: análisis de rendimiento en CPU/GPU.

Configuración básica con el callback Keras

La forma más sencilla de integrar TensorBoard es usando el callback TensorBoard en model.fit():

import tensorflow as tf
import numpy as np
import datetime

# Datos de ejemplo
(X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()
X_train = X_train / 255.0
X_test = X_test / 255.0

# Modelo
modelo = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(10, activation='softmax')
])

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

# Directorio de logs con timestamp (evita sobreescribir experimentos anteriores)
log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")

# Callback TensorBoard
tensorboard_callback = tf.keras.callbacks.TensorBoard(
    log_dir=log_dir,
    histogram_freq=1,       # registrar histogramas de pesos cada N épocas (0 = desactivado)
    write_graph=True,       # guardar el grafo del modelo
    write_images=True,      # guardar imágenes de los pesos
    update_freq='epoch',    # 'epoch', 'batch' o número de batches
    profile_batch=0         # desactivar profiling (o '2,5' para perfilar batches 2-5)
)

historial = modelo.fit(
    X_train, y_train,
    epochs=5,
    validation_data=(X_test, y_test),
    callbacks=[tensorboard_callback]
)

print(f"Logs guardados en: {log_dir}")
print(f"Para ver TensorBoard ejecuta: tensorboard --logdir logs/fit")

Lanzar TensorBoard desde terminal:

tensorboard --logdir logs/fit

O directamente desde Jupyter/Colab:

# En Jupyter Notebook o Google Colab
%load_ext tensorboard
%tensorboard --logdir logs/fit

Registrar scalars personalizados con tf.summary

Para registrar métricas adicionales durante el entrenamiento:

import tensorflow as tf
import numpy as np

# Crear un writer de sumarios
log_dir_custom = "logs/custom"
writer = tf.summary.create_file_writer(log_dir_custom)

# Registrar métricas personalizadas
for epoca in range(10):
    perdida_simulada = 1.0 / (epoca + 1)
    precision_simulada = 1 - perdida_simulada * 0.5
    lr_simulado = 0.001 * (0.9 ** epoca)

    with writer.as_default():
        tf.summary.scalar('perdida/entrenamiento', perdida_simulada, step=epoca)
        tf.summary.scalar('precision/entrenamiento', precision_simulada, step=epoca)
        tf.summary.scalar('hiperparametros/learning_rate', lr_simulado, step=epoca)

writer.flush()
print(f"Sumarios guardados en {log_dir_custom}")

Registrar imágenes en TensorBoard

Útil para visualizar muestras del dataset o predicciones durante el entrenamiento:

import tensorflow as tf
import numpy as np

(X_train, y_train), _ = tf.keras.datasets.mnist.load_data()
X_train = X_train / 255.0

log_dir_imagenes = "logs/imagenes"
writer_img = tf.summary.create_file_writer(log_dir_imagenes)

# Tomar una muestra de imágenes
muestra = X_train[:25]
# TensorBoard espera shape (n, h, w, c)
muestra_4d = muestra[..., tf.newaxis]  # (25, 28, 28, 1)

with writer_img.as_default():
    tf.summary.image(
        "Muestras MNIST",
        muestra_4d,
        max_outputs=25,
        step=0
    )

writer_img.flush()
print("Imágenes registradas.")

Registrar histogramas de pesos

import tensorflow as tf
import numpy as np

log_dir_hist = "logs/histogramas"
writer_hist = tf.summary.create_file_writer(log_dir_hist)

# Simular evolución de pesos
for paso in range(50):
    pesos_simulados = np.random.normal(loc=0, scale=1.0/(paso+1), size=(128, 64))
    with writer_hist.as_default():
        tf.summary.histogram("capas/dense_1/kernel", pesos_simulados, step=paso)

writer_hist.flush()
print("Histogramas registrados.")

TensorBoard en bucles de entrenamiento personalizados

import tensorflow as tf
import numpy as np

# Datos
(X_train, y_train), (X_val, y_val) = tf.keras.datasets.mnist.load_data()
X_train = X_train.reshape(-1, 784).astype('float32') / 255.0
X_val = X_val.reshape(-1, 784).astype('float32') / 255.0

train_ds = tf.data.Dataset.from_tensor_slices((X_train, y_train)).batch(256)
val_ds = tf.data.Dataset.from_tensor_slices((X_val, y_val)).batch(256)

# Modelo
modelo = tf.keras.Sequential([
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

optimizer = tf.keras.optimizers.Adam(0.001)
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy()

train_loss_metric = tf.keras.metrics.Mean(name='perdida_train')
train_acc_metric = tf.keras.metrics.SparseCategoricalAccuracy(name='acc_train')
val_loss_metric = tf.keras.metrics.Mean(name='perdida_val')
val_acc_metric = tf.keras.metrics.SparseCategoricalAccuracy(name='acc_val')

# Writers separados para train y validación (aparecen en mismo gráfico)
train_writer = tf.summary.create_file_writer("logs/custom_loop/train")
val_writer = tf.summary.create_file_writer("logs/custom_loop/val")

EPOCHS = 5

for epoca in range(EPOCHS):
    # Entrenamiento
    for X_batch, y_batch in train_ds:
        with tf.GradientTape() as tape:
            predicciones = modelo(X_batch, training=True)
            loss = loss_fn(y_batch, predicciones)

        gradientes = tape.gradient(loss, modelo.trainable_variables)
        optimizer.apply_gradients(zip(gradientes, modelo.trainable_variables))

        train_loss_metric.update_state(loss)
        train_acc_metric.update_state(y_batch, predicciones)

    # Validación
    for X_val_batch, y_val_batch in val_ds:
        val_preds = modelo(X_val_batch, training=False)
        val_loss = loss_fn(y_val_batch, val_preds)
        val_loss_metric.update_state(val_loss)
        val_acc_metric.update_state(y_val_batch, val_preds)

    # Registrar en TensorBoard
    with train_writer.as_default():
        tf.summary.scalar('loss', train_loss_metric.result(), step=epoca)
        tf.summary.scalar('accuracy', train_acc_metric.result(), step=epoca)

    with val_writer.as_default():
        tf.summary.scalar('loss', val_loss_metric.result(), step=epoca)
        tf.summary.scalar('accuracy', val_acc_metric.result(), step=epoca)

    print(f"Época {epoca+1}/{EPOCHS} | "
          f"Train Loss: {train_loss_metric.result():.4f}, Acc: {train_acc_metric.result():.4f} | "
          f"Val Loss: {val_loss_metric.result():.4f}, Acc: {val_acc_metric.result():.4f}")

    # Resetear métricas al final de cada época
    train_loss_metric.reset_state()
    train_acc_metric.reset_state()
    val_loss_metric.reset_state()
    val_acc_metric.reset_state()

train_writer.flush()
val_writer.flush()
print("\nEntrenamiento completado. Ejecuta: tensorboard --logdir logs/custom_loop")

Comparar experimentos en TensorBoard

Una de las funcionalidades más valiosas de TensorBoard es la comparación de experimentos. Basta con guardar los logs en subdirectorios distintos:

import tensorflow as tf
import numpy as np

(X, y), _ = tf.keras.datasets.mnist.load_data()
X = X / 255.0

def entrenar_experimento(lr, dropout, nombre):
    log_dir = f"logs/experimentos/{nombre}"

    modelo = tf.keras.Sequential([
        tf.keras.layers.Flatten(input_shape=(28, 28)),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dropout(dropout),
        tf.keras.layers.Dense(10, activation='softmax')
    ])
    modelo.compile(
        optimizer=tf.keras.optimizers.Adam(lr),
        loss='sparse_categorical_crossentropy',
        metrics=['accuracy']
    )

    cb = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=0)
    modelo.fit(X, y, epochs=3, validation_split=0.1, callbacks=[cb], verbose=0)
    print(f"Experimento '{nombre}' completado. Logs en {log_dir}")

entrenar_experimento(lr=0.001, dropout=0.2, nombre="lr001_drop02")
entrenar_experimento(lr=0.01,  dropout=0.2, nombre="lr01_drop02")
entrenar_experimento(lr=0.001, dropout=0.5, nombre="lr001_drop05")

print("\nComparar en TensorBoard: tensorboard --logdir logs/experimentos")
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, TensorFlow es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de TensorFlow

Explora más contenido relacionado con TensorFlow y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Configurar el callback TensorBoard en el entrenamiento con Keras. Visualizar curvas de pérdida y métricas en tiempo real. Explorar el grafo del modelo en TensorBoard. Registrar imágenes, histogramas y datos escalares personalizados. Usar tf.summary para escribir datos desde bucles de entrenamiento personalizados.