首页 / PyTorch 入门教程 / TensorBoard:训练过程可视化

PyTorch 入门教程

TensorBoard:训练过程可视化

本教程共 60 篇 · 第 30 篇 · 更新于 2026-08-17 · 约 4 分钟阅读

PyTorchTensorBoard可视化SummaryWriter训练监控loss曲线

本节目标:学会用 TensorBoard 记录并查看训练曲线、图片和模型结构,学会从 loss 曲线判断模型状态。

训练为什么需要可视化

训练神经网络有点像开飞机:只看仪表上的一串数字,不如看仪表盘直观。loss 在降吗?降得快还是慢?中途有没有抖动?光靠 print 一堆数字,很难有整体感觉。

TensorBoard 就是给训练装上的仪表盘。它是 Google 出品的机器学习可视化工具,PyTorch 内置了对它的支持,记录数据的接口在 torch.utils.tensorboard 里。后面几章会反复用到「记录 + 查看」这套组合,越早熟练越省事。

安装与启动

先装工具包:

pip install tensorboard

用法分两步:训练代码里写日志,然后用命令启动看板。

tensorboard --logdir=runs

浏览器打开 http://localhost:6006,就能看到界面。`—logdir` 指定日志目录,TensorBoard 会递归寻找里面的事件文件。

SummaryWriter:写日志的那支笔

往 TensorBoard 写数据,全靠一个对象 SummaryWriter

from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter("runs/exp1")   # 日志写到 runs/exp1

之后所有记录都通过它完成。一个 writer 对应一个实验目录,想对比多次实验,就开不同的子目录。writer 创建后,对应目录和事件文件会自动生成,不用手动建文件夹。

记录标量:盯住 loss 曲线

最常见的需求是记录 loss。用 add_scalar(tag, value, step)

import torch
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter("runs/linear")

x = torch.arange(-5, 5, 0.1).view(-1, 1)
y = -5 * x + 0.1 * torch.randn(x.size())

model = torch.nn.Linear(1, 1)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)

for epoch in range(50):
    y_pred = model(x)
    loss = criterion(y_pred, y)
    writer.add_scalar("Loss/train", loss.item(), epoch)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

writer.close()

跑完这段,启动 TensorBoard,在 SCALARS 页面就能看到 loss 随 epoch 下降的曲线。tag 里的斜杠会自动分组:写 Loss/trainLoss/val,两条曲线会归到同一个 Loss 组,对比起来很方便。tag 定下来就别中途改名,否则曲线会断成两截。

训练循环里怎么记

真实训练不会每个 batch 都记录,那样日志又大又慢。常见做法是每 N 步记一次,横轴用全局步数(片段示例,trainloaderrunning_loss 来自你的训练循环):

global_step = 0
for epoch in range(10):
    for i, (inputs, labels) in enumerate(trainloader):
        # 前向、反向、更新……训练代码略
        if i % 200 == 199:
            writer.add_scalar("Loss/train", running_loss / 200, global_step)
            running_loss = 0.0
        global_step += 1

横轴统一用 global_step(epoch × 每轮步数 + 当前步数),两条曲线才能对齐。训练 loss 和验证 loss 分开记:Loss/trainLoss/val,验证集每个 epoch 结束记一次。

记录图片和模型结构

add_image 能记图片。配合 make_grid,可以把一批图拼成一张大图:

from torch.utils.tensorboard import SummaryWriter
import torch
import torchvision

writer = SummaryWriter("runs/vis")

batch = torch.randn(16, 3, 32, 32)          # 假装是 16 张图片
grid = torchvision.utils.make_grid(batch, nrow=4)
writer.add_image("images/samples", grid)

net = torch.nn.Sequential(
    torch.nn.Linear(10, 32),
    torch.nn.ReLU(),
    torch.nn.Linear(32, 1),
)
writer.add_graph(net, torch.randn(8, 10))
writer.close()

add_graph 记录模型结构。在 GRAPHS 页面双击节点可以展开,看数据在各层之间的流向,检查模型是不是按你想的那样搭的。

看权重分布:add_histogram

loss 之外,参数本身也值得盯。add_histogram 记录张量的分布直方图:

# 片段:每个 epoch 记一次,model 是你的模型
for name, param in model.named_parameters():
    writer.add_histogram(name, param, epoch)

在 HISTOGRAMS 页面能看到每个参数的分布怎么变化。权重分布一直不动,说明这层没在学;分布发散得离谱,通常是梯度爆炸的前兆。

多实验对比

对比实验是 TensorBoard 的强项。每次实验用独立子目录:runs/exp1、runs/exp2,启动时还是 tensorboard --logdir=runs。看板左侧会列出所有实验,曲线直接叠在一起对比,谁好谁坏一目了然。目录命名带点信息,比如 runs/lr_0.01runs/lr_0.001,回头找起来不费劲。

Tip

tag 命名建议统一风格:大类/小类,比如 Loss/trainLoss/valAcc/test。TensorBoard 按斜杠分层显示,命名乱了,后面找起来头疼。

记录学习率

学习率是训练里最值得盯的超参数。配合学习率调度器(第 15 章),把它也记成标量:

scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.5)

for epoch in range(50):
    # 训练代码略
    writer.add_scalar("LR", optimizer.param_groups[0]["lr"], epoch)
    scheduler.step()

把学习率曲线和 loss 曲线叠着看,能解释很多奇怪现象:loss 突然跳一下,看看是不是学习率刚好在那一步衰减了。

使用流程回顾

把整个流程串一遍,一共五步:

  1. 创建 SummaryWriter,指定日志目录。
  2. 训练循环里用 add_* 系列方法记录数据。
  3. 训练结束前 close() 收尾。
  4. 命令行运行 tensorboard --logdir=runs
  5. 浏览器打开 localhost:6006 查看。

后面章节的示例里,凡是「把 loss 记下来」的地方,都是这套流程的简写。

从曲线判断模型状态

TensorBoard 最实用的场景,是把训练 loss 和验证 loss 画在一起。看两条曲线的相对位置,就能判断模型状态:

  1. 训练 loss 降、验证 loss 也降:正常,模型在学。
  2. 训练 loss 降、验证 loss 升:过拟合,该加正则化或早停。
  3. 训练 loss 几乎不降:学习率太小,或模型太弱。
  4. loss 剧烈震荡:学习率太大,或 batch 太小。

落实到行动上:过拟合就加 Dropout 或 weight_decay(第 27 章);不收敛就调大学习率;震荡就调小学习率或增大 batch。TensorBoard 帮你发现症状,但下诊断的还是你自己——它给的是数据,不是答案。曲线太抖看不清趋势时,SCALARS 页面左下角的 smoothing 滑杆调大一点,趋势就清晰了。

Tip

验证 loss 开始转头向上的那个点,就是「模型开始背答案」的分界线。第 27 章讲的正则化手段,就是用来对付这条上翘曲线的。

还能记什么

除了标量和图片,SummaryWriter 还有一批方法:

  • add_histogram:记录权重分布,观察训练中参数怎么变化。
  • add_embedding:把高维数据投影到二维、三维空间看聚类。
  • add_figure:直接记录 matplotlib 画的图。
  • add_pr_curve:画每个类别的精确率-召回率曲线。
  • add_hparams:记录超参数,配合指标做实验对比。

这些属于「需要时再查」的能力,入门阶段掌握 add_scalar、add_image、add_graph 就够用了。

常见坑

几个小坑,提前说好:

  1. 日志目录不一致。训练时写到 runs/exp1,启动看板却指定别的目录,自然看不到数据。
  2. 忘记 writer.close()。不关闭可能丢掉最后几条记录,训练结束前调用一下最稳。
  3. 数据没落盘。写入是异步的,长训练中想立刻看到最新曲线,先调 writer.flush() 强制写盘;训练结束前 close() 把缓冲区全部写完。
  4. 端口被占用。默认端口 6006 被别的程序占了,启动时换个端口:tensorboard --logdir=runs --port=6007
Note

Jupyter Notebook 里也能用:写日志的代码完全一样,再加两行魔术命令 %load_ext tensorboard%tensorboard --logdir runs 即可。

小结

TensorBoard 是训练过程的监控仪表盘:SummaryWriter 负责记录,浏览器负责展示。先记 loss 曲线,再补图片和模型结构,就够支撑日常训练了。下一章换个角度,看看模型内部长什么样——特征图和梯度可视化。