Skip to main content

基本简介

TensorBoard是由Google开发并随TensorFlow项目一同开源的机器学习实验可视化工具。它通过在训练过程中将结构化数据写入TFEvents格式的日志文件,再以交互式Web界面的形式进行呈现,帮助研究人员和工程师直观地观察、分析和调试机器学习模型的训练过程。

TensorBoard以独立包形式发布(pip install tensorboard),也随TensorFlow捆绑分发。除原生支持TensorFlow生态外,PyTorch1.1版本起在官方库torch.utils.tensorboard中内置了对TFEvents日志格式的写入支持,使其成为跨框架通用的实验可视化平台。

与训练代码的关系

使用TensorBoard时,训练代码不一定需要直接对接复杂的TensorBoard SDK,但必须有某种方式向日志目录写入TensorBoard能够识别的TFEvents文件。TensorBoard服务本身不会直接参与模型训练,也不会自动从普通终端输出、CSVJSON日志中推断训练指标;它只负责扫描logdir目录,读取其中的events.out.tfevents.*文件并展示可视化结果。

不同训练框架的接入方式有所差异:

框架 / 场景接入方式是否自动记录
TensorFlow / Keras使用tf.keras.callbacks.TensorBoard回调或tf.summary接口Keras回调可自动记录lossaccuracy等内置指标
PyTorch原生训练循环使用torch.utils.tensorboard.SummaryWriter显式写入标量、图像、直方图等数据不会自动记录,需要在训练循环中调用add_scalar等方法
高级训练框架使用框架内置的TensorBoard Logger或配置开关取决于框架实现,通常会自动记录常见训练指标

因此,在PyTorch项目中可以认为官方库已经内置了TensorBoard日志写入接口,但这并不等同于训练过程会被自动采集。开发者仍需在训练循环中创建SummaryWriter,并在合适的训练步或epoch调用writer.add_scalar()writer.add_histogram()等方法写入日志。启动tensorboard --logdir runs只是读取和展示这些日志;如果代码没有生成TFEvents文件,界面中就不会出现对应的指标曲线。

解决的核心问题

机器学习训练过程长期面临以下挑战:

  • 训练过程不透明:模型训练本质上是一个迭代优化过程,在没有可视化工具的情况下,从业者只能依赖终端打印的数字日志来判断训练健康度,难以及时发现梯度消失、过拟合等隐性问题。
  • 实验结果难以对比:在探索不同超参数组合和网络结构时,多次实验结果通常散落在多个日志文件中,缺乏系统化的比较手段。
  • 模型结构难以验证:复杂的计算图在代码层面难以审查,容易出现层未正确连接、张量形状不匹配等结构错误,视觉化呈现可以快速定位此类问题。
  • 高维数据难以理解:词嵌入、特征表示等高维向量天然难以解读,需要降维投影才能获得直觉性的理解。

TensorBoard通过结构化日志采集与交互式可视化这套完整方案,将上述黑盒过程系统性地透明化。

主要优点

  • 实时监控:训练进行中TensorBoard会定期自动刷新,无需等待训练结束即可观察指标趋势。
  • 多实验对比:可在同一视图中叠加来自不同训练运行(Run)的曲线,直观对比不同配置下的效果差异。
  • 多维度数据支持:统一界面支持标量、直方图、图像、音频、文本、嵌入向量等多种数据类型的可视化。
  • 框架中立性:通过TFEvents标准日志格式,TensorFlowPyTorch等主流框架均可写入并使用TensorBoard进行分析。
  • 超参数系统化调优:内置HParams插件提供结构化的超参数实验管理,支持表格视图、平行坐标图、散点矩阵图等多种分析视角。
  • 性能剖析:内置Profiler插件可分析GPU/CPU上的算子执行时间,辅助定位训练性能瓶颈。
  • 免费开源:完全开源(Apache 2.0许可),无使用成本,可本地部署。

基本架构

TensorBoard的整体数据流如下:

TensorBoard服务器本质上是一个Python进程,它持续监听指定的日志目录,解析TFEvents文件并通过HTTP API将数据提供给前端页面。前端为基于Angular构建的单页应用,各功能通过插件体系独立组织。

实验管理指标

TensorBoard的功能通过插件体系组织,每类数据对应一个独立的面板(Dashboard)。以下介绍各核心面板、对应指标的含义及记录方式。

Scalars(标量)

含义

Scalars面板(在新版TensorBoard中位于Time Series面板下)用于记录和展示随训练步数变化的单个数值,是最常用的实验管理手段。典型的标量指标如下:

指标名称含义
loss训练损失,反映模型在训练集上的拟合程度,应随训练逐步下降
val_loss验证集损失,反映模型的泛化能力,用于检测过拟合现象
accuracy分类任务的准确率(训练集)
val_accuracy分类任务的准确率(验证集)
learning_rate当前学习率,对于动态学习率调度(如LRScheduler)的可视化尤为重要
自定义指标任何用户自定义的标量,如AUCF1BLEUROUGE

通过对比lossval_loss的走势,可识别以下三类训练状态:

使用方式(TensorFlow / Keras)

import tensorflow as tf
import datetime

# 使用带时间戳的子目录区分不同训练运行
log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")

# Keras 回调自动记录 loss、accuracy 等内置指标
tensorboard_callback = tf.keras.callbacks.TensorBoard(
log_dir=log_dir,
histogram_freq=1, # 每 epoch 记录一次直方图
)

model.fit(
x_train, y_train,
epochs=10,
validation_data=(x_val, y_val),
callbacks=[tensorboard_callback],
)

使用tf.summary.scalar记录自定义标量:

writer = tf.summary.create_file_writer("logs/custom")

with writer.as_default():
for step in range(100):
tf.summary.scalar("custom/my_metric", value=some_value, step=step)

使用方式(PyTorch)

PyTorch提供的是官方日志写入接口,而不是自动实验采集器。以下代码需要放入训练循环中,明确告诉TensorBoard要记录哪些指标:

from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter("runs/experiment_1")

for epoch in range(num_epochs):
# ... 训练循环 ...
writer.add_scalar("Loss/train", train_loss, epoch)
writer.add_scalar("Loss/val", val_loss, epoch)
writer.add_scalar("Accuracy/train", train_acc, epoch)
writer.add_scalar("Accuracy/val", val_acc, epoch)

writer.close()

Graphs(计算图)

含义

Graphs面板展示模型的计算图,帮助开发者验证模型结构是否符合预期,识别错误的层连接关系,并理解数据在模型中的流向。TensorBoard支持两类图的展示:

  • Op-level 图TensorFlow底层算子级别的计算图
  • Conceptual 图Keras模型的高层结构图(层级视图),通常更易于阅读

使用方式(TensorFlow)

KerasTensorBoard回调在设置write_graph=True时会自动记录模型计算图。对于tf.function修饰的自定义函数,可通过trace机制记录:

# 开启图追踪
tf.summary.trace_on(graph=True)

with writer.as_default():
# 触发一次前向传播以捕获计算图
output = my_tf_function(sample_input)
tf.summary.trace_export(name="my_function", step=0)

使用方式(PyTorch)

# 传入模型和一个示例输入,TensorBoard 将推断并记录计算图
writer.add_graph(model, input_to_model=torch.zeros(1, 3, 224, 224))

Histograms(直方图)

含义

Histograms面板将张量的数值分布以直方图的形式随时间维度堆叠呈现,用于观察模型参数在训练过程中的动态变化。常见应用场景如下:

应用场景说明
权重分布变化观察各层权重是否正常更新,分布是否向合理区间收敛
梯度分布诊断梯度消失(分布向零收缩)或梯度爆炸(分布急剧扩散)等问题
偏置项分布检查偏置是否出现严重偏移或饱和
激活值分布观察激活层输出是否合理,如ReLU是否存在大量零输出(神经元死亡现象)

使用方式(TensorFlow / Keras)

Keras回调中启用直方图记录(默认关闭,开启后会增加一定计算开销):

tensorboard_callback = tf.keras.callbacks.TensorBoard(
log_dir=log_dir,
histogram_freq=1, # 每隔 1 个 epoch 记录一次直方图,0 表示不记录
)

使用tf.summary.histogram自定义记录:

with writer.as_default():
tf.summary.histogram("layer1/kernel", model.layers[1].kernel, step=epoch)
tf.summary.histogram("layer1/bias", model.layers[1].bias, step=epoch)

使用方式(PyTorch)

for name, param in model.named_parameters():
writer.add_histogram(f"params/{name}", param, global_step)
if param.grad is not None:
writer.add_histogram(f"grads/{name}", param.grad, global_step)

Distributions(分布)

含义

Distributions面板是Histograms数据的另一种呈现形式。它将同一张量在不同训练步数下的分布叠加为带状区域图,展示5%25%50%(中位数)、75%95%等百分位数随训练步数的变化趋势。

相比Histograms面板,Distributions更适合观察:

  • 分布的中心趋势(中位数)是否随训练朝预期方向变化
  • 分布宽度(四分位距)是否随训练收缩或扩张
  • 是否出现双峰等异常分布形态

Distributions面板中的数据来源与Histograms完全相同,无需额外记录,只需在TensorBoard界面中切换面板即可查看。

Images(图像)

含义

Images面板用于展示训练过程中的图像数据,常见应用场景包括:

  • 可视化数据增强效果(验证预处理管道的正确性)
  • 展示生成式模型(GANVAE等)的输出结果随训练的演化过程
  • 记录语义分割、目标检测等任务的可视化推理结果
  • 展示注意力图(Attention Map)等中间特征的可视化

使用方式(TensorFlow)

# 输入张量形状须为 [batch, height, width, channels],像素值范围 [0, 1] 或 [0, 255]
with writer.as_default():
tf.summary.image(
"training_samples",
images_tensor,
step=epoch,
max_outputs=4, # 最多展示 4 张图
)

使用方式(PyTorch)

# 单张图像:形状 [C, H, W],像素值范围 [0, 1]
writer.add_image("sample/input", img_tensor, global_step)

# 批量图像(以网格形式展示)
from torchvision.utils import make_grid
grid = make_grid(images_batch, nrow=8, normalize=True)
writer.add_image("sample/batch_grid", grid, global_step)

Audio(音频)

含义

Audio面板支持记录和回放音频波形数据,适用于语音识别、文本转语音(TTS)、音频生成等场景,典型用途包括:

  • 验证音频预处理输出是否正确(如采样率转换、静音截断等)
  • 对比模型输出的合成语音与目标音频之间的质量差异
  • 监听语音合成模型在不同训练阶段的音质演化

使用方式(TensorFlow)

# audio_tensor 形状为 [1, num_frames, channels],sample_rate 单位为 Hz
with writer.as_default():
tf.summary.audio(
"synthesized_speech",
audio_tensor,
sample_rate=22050,
step=epoch,
max_outputs=2,
)

使用方式(PyTorch)

# audio_tensor 形状为 [1, num_frames] 或 [num_frames]
writer.add_audio("output/speech", audio_tensor, global_step, sample_rate=22050)

Text(文本)

含义

Text面板用于记录任意字符串数据,支持基本Markdown渲染,常见用途包括:

  • 记录当前实验的超参数配置摘要,便于事后回溯
  • 展示文本生成任务(翻译、摘要、对话等)在不同训练步数下的样本输出,直观评估生成质量
  • 记录数据集版本、实验说明等元数据信息

使用方式(TensorFlow)

with writer.as_default():
tf.summary.text(
"experiment/config",
"lr=0.001 | batch_size=64 | optimizer=Adam | dropout=0.3",
step=0,
)

使用方式(PyTorch)

writer.add_text(
"config/hyperparams",
"lr: 0.001 | batch: 64 | optimizer: Adam",
global_step=0,
)

Embeddings(嵌入向量投影)

含义

Embeddings面板(又称Projector插件)将高维嵌入向量投影到2D3D空间进行可视化,支持PCAt-SNE两种降维算法,帮助分析:

  • 词嵌入(Word Embedding)的语义聚类结构是否符合预期
  • 图像特征嵌入的类别边界是否清晰
  • 推荐系统中用户嵌入与物品嵌入之间的空间关系

可为每个向量附加文字标签(metadata)或对应的缩略图(sprite image),使投影点具备清晰的语义标注。

使用方式(TensorFlow)

import os
import tensorflow as tf
from tensorboard.plugins import projector

log_dir = "logs/embeddings"

# 将嵌入矩阵保存为 TensorFlow Checkpoint
embedding_var = tf.Variable(embedding_matrix, name="word_embeddings")
checkpoint = tf.train.Checkpoint(embedding=embedding_var)
checkpoint.save(os.path.join(log_dir, "embedding.ckpt"))

# 配置 Projector 插件
config = projector.ProjectorConfig()
emb_cfg = config.embeddings.add()
emb_cfg.tensor_name = "embedding/.ATTRIBUTES/VARIABLE_VALUE"
emb_cfg.metadata_path = "metadata.tsv" # 每行一个标签的文本文件
projector.visualize_embeddings(log_dir, config)

使用方式(PyTorch)

writer.add_embedding(
mat=embedding_matrix, # 形状 [n, dim] 的张量
metadata=word_list, # 长度为 n 的标签列表
label_img=sprite_tensor, # 可选,形状 [n, C, H, W],每行对应的缩略图
global_step=0,
tag="word_embeddings",
)

HParams(超参数调优)

含义

HParamsHyperparameters)面板是TensorBoard中专用于系统化管理超参数实验的插件。当需要探索多组超参数组合时(如学习率、批次大小、网络层数等),HParams将每次实验的超参数配置与最终指标统一汇总,提供以下三种分析视角:

视图类型说明
表格视图(Table View)以行为单位列出所有实验运行,展示各超参数值及对应指标,支持多列排序和条件筛选
平行坐标图(Parallel Coordinates View)每条实验对应一条折线,穿越所有超参数和指标轴;拖选某轴上的区间,可快速过滤出表现最优的参数组合
散点矩阵图(Scatter Plot View)展示每对超参数与指标之间的二维相关关系,帮助识别对目标指标影响最大的关键超参数

使用方式(TensorFlow)

import tensorflow as tf
from tensorboard.plugins.hparams import api as hp

# 1. 定义超参数搜索空间
HP_UNITS = hp.HParam("num_units", hp.Discrete([64, 128, 256]))
HP_DROPOUT = hp.HParam("dropout_rate", hp.RealInterval(0.1, 0.5))
HP_LR = hp.HParam("learning_rate", hp.Discrete([1e-3, 1e-4]))

METRIC_VAL_ACC = "val_accuracy"

# 2. 声明实验配置(可选,但有助于 UI 中的过滤与展示)
with tf.summary.create_file_writer("logs/hparam_tuning").as_default():
hp.hparams_config(
hparams=[HP_UNITS, HP_DROPOUT, HP_LR],
metrics=[hp.Metric(METRIC_VAL_ACC, display_name="Validation Accuracy")],
)

# 3. 每次实验中记录超参数与指标
def run_experiment(run_dir, hparams):
with tf.summary.create_file_writer(run_dir).as_default():
hp.hparams(hparams)
val_acc = train_and_evaluate(hparams)
tf.summary.scalar(METRIC_VAL_ACC, val_acc, step=1)

# 4. 遍历参数组合(网格搜索)
session_num = 0
for num_units in HP_UNITS.domain.values:
for lr in HP_LR.domain.values:
for dropout_rate in [HP_DROPOUT.domain.min_value, HP_DROPOUT.domain.max_value]:
hparams = {HP_UNITS: num_units, HP_DROPOUT: dropout_rate, HP_LR: lr}
run_experiment(f"logs/hparam_tuning/run-{session_num:02d}", hparams)
session_num += 1

使用方式(PyTorch)

# add_hparams 在一次 writer.close() 前调用,记录超参数与对应指标
writer.add_hparams(
hparam_dict={"lr": 0.001, "batch_size": 64, "dropout": 0.3},
metric_dict={"hparam/accuracy": val_accuracy, "hparam/loss": val_loss},
)

Profiler(性能分析)

含义

Profiler插件用于分析TensorFlow程序的运算性能。它能精确记录各算子(Op)在CPU/GPU上的执行时间、内存占用和设备利用率,帮助定位训练性能瓶颈。各分析视图的说明如下:

分析视图说明
概览(Overview)展示训练步骤的时间分解,包含输入管道耗时、设备计算耗时等总体分布
输入流水线分析(Input Pipeline Analyzer)专门分析tf.data数据输入管道是否成为瓶颈,并给出优化建议
TensorFlow Stats按算子(Op)统计执行时间及调用次数,快速定位耗时最高的操作
Trace Viewer以时间轴形式展示所有CPU/GPU核心上的算子执行序列(兼容Perfetto格式)
Memory Profile展示设备内存使用随时间的变化曲线,辅助诊断显存溢出(OOM)问题

注意Profiler插件目前主要针对TensorFlow程序。PyTorch官方提供独立的torch.profiler模块,其输出可以导出为Chrome Trace格式,通过TensorBoardTrace Viewer视图进行查看,但TensorBoardProfiler面板本身不原生支持PyTorch

使用方式(TensorFlow)

# 在 Keras 回调中开启 Profiling,指定对哪些 batch 进行剖析
tensorboard_callback = tf.keras.callbacks.TensorBoard(
log_dir=log_dir,
profile_batch=(10, 20), # 对第 10 到第 20 个 batch 进行性能剖析
)

PyTorch 的 torch.profiler 集成

import torch
from torch.profiler import profile, ProfilerActivity, tensorboard_trace_handler

with profile(
activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
on_trace_ready=tensorboard_trace_handler("runs/profiler"),
record_shapes=True,
with_stack=True,
) as prof:
for step, (inputs, labels) in enumerate(train_loader):
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
optimizer.zero_grad()
prof.step()

安装与配置

安装

安装场景命令
独立安装(适用于非TensorFlow项目)pip install tensorboard
TensorFlow一同安装pip install tensorflow
Conda环境中安装conda install -c conda-forge tensorboard

TensorBoard要求Python 3.9+(具体版本随当前发布版本变化,以官方发布说明为准)。独立安装的tensorboard包不依赖完整的TensorFlow,体积更小,适合在仅使用PyTorch的环境中集成。

启动 TensorBoard

安装完成后,通过命令行启动TensorBoard服务器:

# 基本启动,--logdir 指定日志目录
tensorboard --logdir ./logs

# 指定端口(默认端口为 6006)
tensorboard --logdir ./logs --port 8080

# 同时监听多个日志目录(用于多实验对比)
tensorboard --logdir_spec run_a:./logs/run_a,run_b:./logs/run_b

# 允许外部访问(如部署在远程服务器上时)
tensorboard --logdir ./logs --host 0.0.0.0 --port 6006

启动后在浏览器中访问http://localhost:6006即可打开可视化界面。

在 Jupyter Notebook 中使用

# 加载 TensorBoard Notebook 扩展
%load_ext tensorboard

# 启动 TensorBoard,直接嵌入在 Notebook 输出单元中显示
%tensorboard --logdir logs/

日志目录结构

TensorBoard通过递归扫描指定日志目录下的TFEvents文件进行数据读取。推荐使用带时间戳的子目录来区分不同训练运行:

logs/
├── fit/
│ ├── 20240101-120000/ # 实验运行 1
│ │ ├── train/
│ │ │ └── events.out.tfevents.xxxxxxxx
│ │ └── validation/
│ │ └── events.out.tfevents.xxxxxxxx
│ └── 20240102-090000/ # 实验运行 2
│ ├── train/
│ └── validation/
└── hparam_tuning/
├── run-00/
├── run-01/
└── ...

使用示例

示例一:Keras 模型训练监控

展示如何在Keras训练流程中集成TensorBoard,自动记录损失、准确率及权重直方图:

import tensorflow as tf
import datetime

# 数据集准备
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

# 模型定义
model = tf.keras.models.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"),
])
model.compile(
optimizer="adam",
loss="sparse_categorical_crossentropy",
metrics=["accuracy"],
)

# 配置 TensorBoard 回调
log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(
log_dir=log_dir,
histogram_freq=1, # 每 epoch 记录权重直方图
write_graph=True, # 记录计算图
)

# 训练并自动记录日志
model.fit(
x_train, y_train,
epochs=10,
validation_data=(x_test, y_test),
callbacks=[tensorboard_callback],
)
tensorboard --logdir logs/fit

示例二:PyTorch 自定义指标记录

展示如何在PyTorch训练循环中手动记录标量指标和权重直方图:

import torch
import torch.nn as nn
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter("runs/pytorch_experiment")

model = MyModel()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
criterion = nn.CrossEntropyLoss()

for epoch in range(20):
model.train()
running_loss = 0.0
for data, target in train_loader:
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
running_loss += loss.item()

avg_loss = running_loss / len(train_loader)
val_acc = evaluate(model, val_loader)

# 记录标量指标
writer.add_scalar("Loss/train", avg_loss, epoch)
writer.add_scalar("Accuracy/val", val_acc, epoch)

# 记录权重直方图
for name, param in model.named_parameters():
writer.add_histogram(f"weights/{name}", param, epoch)

writer.close()
tensorboard --logdir runs/pytorch_experiment

示例三:超参数搜索(HParams)

展示如何使用HParams插件对多组超参数组合进行系统化实验并在TensorBoard中对比结果:

import tensorflow as tf
from tensorboard.plugins.hparams import api as hp

# 加载数据
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

# 定义超参数空间
HP_LR = hp.HParam("learning_rate", hp.Discrete([1e-2, 1e-3, 1e-4]))
HP_UNITS = hp.HParam("dense_units", hp.Discrete([64, 128]))
METRIC_VAL_ACC = "val_accuracy"

def train_model(hparams):
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(hparams[HP_UNITS], activation="relu"),
tf.keras.layers.Dense(10, activation="softmax"),
])
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=hparams[HP_LR]),
loss="sparse_categorical_crossentropy",
metrics=["accuracy"],
)
history = model.fit(
x_train, y_train,
epochs=5,
validation_data=(x_test, y_test),
verbose=0,
)
return history.history["val_accuracy"][-1]

# 遍历所有参数组合并记录
for run_idx, (lr, units) in enumerate(
[(lr, u) for lr in HP_LR.domain.values for u in HP_UNITS.domain.values]
):
hparams = {HP_LR: lr, HP_UNITS: units}
run_dir = f"logs/hparams/run-{run_idx:02d}"
with tf.summary.create_file_writer(run_dir).as_default():
hp.hparams(hparams)
val_acc = train_model(hparams)
tf.summary.scalar(METRIC_VAL_ACC, val_acc, step=1)
tensorboard --logdir logs/hparams

启动后打开HParams面板,切换至平行坐标图视图,拖选val_accuracy轴的高值区间,即可直观筛选出最优的超参数组合。

参考资料