想象你是一名汽车工程师,正在对新车做长距离路测。你绝不会只踩油门往前冲——你得盯着仪表盘:速度多少、油耗多少、水温是否报警。AI 训练也是一场长途路测:模型是那辆车,数据是路况,而 Wandb 和 TensorBoard 就是两套风格迥异的仪表盘。TensorBoard 是经典机械仪表,朴素、稳定、本地直连,像一块可靠的老式速度表;Wandb 则是智能车联网系统,云端记录、实时共享、自动告警,像车载导航加上智能诊断仪。这篇指南带你从零认识这两套仪表盘,学会记录指标、设计面板、对比实验、设置告警,把训练过程中那些藏在黑盒子里的数字,变成一条一眼就能读懂的平滑曲线。

岗位关联

掌握 Wandb 与 TensorBoard,意味着你能像老司机看仪表盘一样秒懂训练状态,及时拦截梯度爆炸、Loss 不降等翻车事故。这是算法工程师做实验管理的基本功,也是迈向大模型训练工程化的关键一步。

目录
  1. 可视化演示
  2. 可视化基础概念
  3. TensorBoard入门
  4. TensorBoard高级
  5. Wandb核心用法
  6. Wandb实验管理
  7. Wandb告警体系
  8. 工程落地实践
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

动态演示Wandb与TensorBo的核心机制,通过开始/执行/监控/完成四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Wandb与TensorBo:训练指标 训练指标记录与日志架构设计 Wandb与TensorBoa 核心机制可视化 Wandb与TensorBo整体架构与关键组件

可视化基础概念

不看仪表盘开车,速度全靠“感觉”,跑长途必翻车。AI 工程师训练模型也一样:模型在并行环境里算得昏天黑地,如果没人记录 Loss、准确率这些数字,你就是蒙眼踩油门。可视化最朴素的目标,就是把训练过程变成仪表盘上的一根根指针。

训练可视化这条流水线有三个环节:采集指标,在训练循环里读取 Loss、准确率、学习率、梯度范数;日志记录,把指标按 step 或 epoch 写入本地文件或云端;展示图表,前端按时间顺序画成折线图、直方图。无论 TensorBoard 还是 Wandb,本质都是“记录—传输—展示”的分工,差别只在于仪表盘装在哪里。

指标画出来后,噪声是最大的敌人。Loss 曲线往往剧烈跳动,像颠簸路面上的油表指针,不经过处理根本看不清趋势。业界通用的做法是滑动平均(EMA):让曲线吃掉一小部分新数据,把大部分体重留给历史记忆,从而把锯齿磨平。EMA 的递归公式如下:

有了 EMA 这根“阻尼指针”,你扫一眼仪表盘就能判断训练是在下降还是平台期。后面两节的主角——TensorBoard 和 Wandb,内部都在悄悄做同一件事:把杂乱的原始指标变成可靠的仪表读数。

EMAt=β⋅EMAt−1+(1−β)⋅xt\displaystyle \text{EMA}_t = \beta \cdot \text{EMA}_{t-1} + (1-\beta) \cdot x_t
这个公式描述了“新读数 x_t”和“历史记忆 EMA_{t-1}”如何按比例混合成新的平滑值。β 越大越平滑,像液压减震器;越小越敏感,像赛车悬挂。
  1. 历史记忆EMA_{t-1} 是上一步的平滑值,相当于油表指针上一秒的位置。
    EMAt−1\text{EMA}_{t-1}
  2. 新观测值x_t 是当前最新指标,比如这一步刚算出来的 Loss,等待被“吸收”。
    xtx_t
  3. 历史权重β · EMA_{t-1} 表示新指针位置九成由历史位置决定,起到稳定作用。
    β⋅EMAt−1\beta \cdot \text{EMA}_{t-1}
  4. 新数据贡献(1-β) · x_t 表示新读数只能贡献一成影响力,β 越接近 1,响应越迟缓。
    (1−β)⋅xt(1-\beta) \cdot x_t

TensorBoard入门

TensorBoard 就像是汽车出厂自带的机械仪表盘:经典、稳定、朴素,而且完全免费。它不联网、不登录,只要你的训练代码留了日志,它就能把数据渲染成网页面板。对很多老工程师来说,第一块仪表盘就是它。

TensorBoard 的用法可以拆成两句口诀:代码里写日志,终端里起服务。写日志靠 SummaryWriter,它会把标量、图像、文本按 step 追加到指定目录;启动则只需一行 tensorboard --logdir=logs,浏览器打开 6006 端口即可查看。标量图表(Scalar)是最常看的仪表:Loss 下降曲线、学习率衰减曲线、验证集准确率曲线。

训练二分类模型时,准确率是最直观的“车速表”。它统计预测正确的样本占总样本的比例:

TensorBoard 这块机械仪表虽然不会主动喊你,但它的可靠性无可替代:日志文件就在本地,断网也能看,社区教程多、零门槛。对单机调试来说,它仍然是很多团队的第一块仪表盘。

Acc=正确预测样本数测试总样本数\displaystyle \text{Acc} = \frac{\text{正确预测样本数}}{\text{测试总样本数}}
准确率就像一个判定“你有没有跑对方向”的指标:只要它在稳步上升,就说明模型确实在从数据里学东西,而不是在空转。
  1. 正确预测样本数分子是模型输出与真实标签一致的样本数量,每轮统计一次。
    正确预测样本数\text{正确预测样本数}
  2. 测试总样本数分母是参与评估的样本总量,通常用验证集或测试集,而不是训练集自己。
    测试总样本数\text{测试总样本数}
  3. 比值归一两者相除得到 0 到 1 之间的比例,再乘 100% 就是日常说的准确率。
    Acc=正确总数\text{Acc} = \frac{\text{正确}}{\text{总数}}

TensorBoard高级

水温表只能告诉你“热不热”,修车师傅却要看发动机转速分布、传动链路是否顺畅。TensorBoard 的高级面板就是引擎盖下的视图:直方图展示权重和梯度随训练步数的分布演变,分布图则把直方图平铺成地形图;计算图呈现网络结构和梯度流,嵌入投影仪能将高维向量降维到二维空间观察聚类。

直方图最常见的用途是抓梯度异常。大模型训练最怕两件事:梯度爆炸和梯度消失。梯度爆炸时梯度的绝对值像疯牛一样冲高,直方图尾部越来越长;梯度消失时直方图缩成一根针,紧贴零值,模型彻底学不动。要量化“疯牛程度”,可以用梯度范数——把所有梯度分量平方求和再开方:

TensorBoard 高级面板的价值在于“防患于未然”:曲线还没开始飘,直方图和梯度范数已经拉响警报。就像经验丰富的修车师傅,听发动机声音就知道哪个气缸出了毛病。

∥∇θL∥2=∑i=1ngi 2\displaystyle \|\nabla_\theta \mathcal{L}\|_2 = \sqrt{\sum_{i=1}^{n} g_i^{\,2}}
梯度范数是衡量“这一脚油门踩得多狠”的总指标。范数骤然飙升,说明某个层的梯度失控了,得踩刹车(降学习率)或挂防滑链(梯度裁剪)。
  1. 梯度分量g_i 表示第 i 个参数的导数,即损失函数对该参数的敏感度,n 是参数总数。
    gig_i
  2. 平方求和对每个梯度求平方再累加,避免正负梯度互相抵消,突出异常大的梯度。
    ∑i=1ngi 2\sum_{i=1}^{n} g_i^{\,2}
  3. 开方归一对总和开平方,把“平方和”还原成有量纲的向量长度,方便设定统一阈值。
    ∥∇θL∥2=∑i=1ngi 2\|\nabla_\theta \mathcal{L}\|_2 = \sqrt{\sum_{i=1}^{n} g_i^{\,2}}

Wandb核心用法

如果说 TensorBoard 是机械仪表,Wandb 就是智能车联网——所有数据自动上传云端,换台电脑打开网页就能看到同一块仪表盘。它是 Weights & Biases 的缩写,核心定位是实验管理平台,界面比 TensorBoard 精致得多,还自带团队协作基因。

Wandb 的概念模型是“项目—实验”两级结构。一个项目好比一次路测任务,任务下每次启动训练就是一次独立的 run。三条核心 API 覆盖日常:wandb.init(project=...) 初始化项目,wandb.log({...}) 逐条记录指标,训练结束 wandb.finish() 归档。如果想在局域网或离线环境使用,可以用 WANDB_MODE=offline 开启离线模式,训练完再统一同步。

多实验跑完后,你往往需要看“同一时刻多条曲线谁更低”。Wandb 会在每个 step 把所有 run 的指标聚合成一条带置信区间的曲线。聚合逻辑就是朴素而实用的均值:

Wandb 的智能仪表盘最大魅力是“上车即联网”:显卡利用率、显存、CPU 负载、网络吞吐自动上报,你不用手动采集环境信息。对团队而言,它是共享的监控中心,更是实验管理的中枢。

μstep=1N∑i=1Nlossstep(i)\displaystyle \mu_{\text{step}} = \frac{1}{N}\sum_{i=1}^{N} \text{loss}^{(i)}_{\text{step}}
在同一个 step 上,把 N 次实验的 Loss 取平均,得到“这条路线上的平均体验”。配合标准差,就能看出实验间的稳定性。
  1. 实验编号loss^{(i)} 表示第 i 次独立运行在同一训练步上的损失值,N 是参与聚合的实验数。
    lossstep(i)\text{loss}^{(i)}_{\text{step}}
  2. 求和累加把所有实验的同一时刻 Loss 加总,相当于求“所有人油表读数的总和”。
    ∑i=1Nlossstep(i)\sum_{i=1}^{N} \text{loss}^{(i)}_{\text{step}}
  3. 平均归一除以 N 得到均值 μ,均值越低说明该组配置整体表现越好,也方便与单条曲线对比。
    μstep=1N∑i=1Nlossstep(i)\mu_{\text{step}} = \frac{1}{N}\sum_{i=1}^{N} \text{loss}^{(i)}_{\text{step}}

Wandb实验管理

车联网导航最实用的功能,是帮你规划多条路线并对比优劣。Wandb 的实验管理就是这样一个“路线规划器”:每个实验有不同的超参数组合,跑完后在界面上批量对比,快速选出最优路径。

多实验对比是 Wandb 的看家本领。你可以勾选任意几次 run,把 Loss 曲线叠加在同一张图上;再用平行坐标图(Parallel Coordinates)筛选超参——横轴排列学习率、批次大小、层数等参数,每条折线代表一次实验,轻松找出“哪组参数组合走到了最低点”。超参搜索则通过 Sweep 自动调度,网格搜索、随机搜索、贝叶斯搜索都可以一键开启。同事之间还能把过程打包成报表(Report)分享,把图表、结论、代码组织成一页可复现的文档。

以网格搜索为例,候选实验总量是各超参取值个数的乘积:

实验管理把“拍脑袋调参”变成了“有组织地试错”。导航不只看一条路,而是把所有可能路线画在地图上——Wandb 做的正是这件事,让团队的经验沉淀成可共享、可追溯的实验库。

Ncombos=∏j=1knj\displaystyle N_{\text{combos}} = \prod_{j=1}^{k} n_j
学习率取 5 个值、批次大小取 4 个值、层数取 3 个值,网格搜索就会组合出 5×4×3=60 种实验组合。这个乘积决定你要跑多少次实验。
  1. 超参数维度n_j 表示第 j 个超参数预设的候选个数,k 是需要搜索的超参数总数。
    njn_j
  2. 连乘组合∏ 符号把每维的候选个数相乘,得到笛卡尔积式的全部组合数。
    ∏j=1knj\prod_{j=1}^{k} n_j
  3. 组合总量N_combos 是网格搜索要执行的实验次数,组合数爆炸时就得改用随机搜索或贝叶斯搜索。
    NcombosN_{\text{combos}}

Wandb告警体系

长时间开车,最怕的是仪表盘亮了红灯你却睡着了。Wandb 的告警体系就像疲劳驾驶提醒:训练在深夜悄悄出问题时,它会主动喊醒你。

自定义告警允许你设定规则:当 Loss 超过阈值、梯度范数越界、验证准确率跌出预期区间,立即通知。通知渠道覆盖邮件、Slack、企业微信,关键时刻不用死盯屏幕。断线恢复解决的是训练中断问题:服务器宕机、网络闪断后,用 wandb.init(resume=True) 可接着上次的 step 继续上传。自动暂停则能结合早停策略,当指标连续多轮不改善时,自动终止实验、回收 GPU 资源,避免烧钱空转。

告警的触发逻辑可以用一个朴素的分段函数描述:

有了告警体系,你不再是被动盯盘,而是让仪表盘主动向你汇报。训练中 Loss 突然变成 NaN、显存被打满、GPU 掉卡——这些事故都能在第一时间通知到位,把损失降到最低。

Alertt={1,if EMAt>θ and t>twarmup0,otherwise\displaystyle \text{Alert}_t =\begin{cases}1, & \text{if } \text{EMA}_t > \theta \ \text{and} \ t > t_{\text{warmup}} \\0, & \text{otherwise}\end{cases}
EMA_t 是平滑后的指标,θ 是预设阈值,t_warmup 是预热步数——训练刚开始的剧烈抖动不触发警报,只有稳定后的异常才值得叫醒人。
  1. 平滑指标与阈值EMA_t 是当前平滑后的 Loss,θ 是工程师预设的“不能越过这条线”的红线。
    EMAt>θ\text{EMA}_t > \theta
  2. 预热窗口t > t_warmup 表示训练已跑够一定步数,此时 Loss 的抖动已收敛,异常信号更可信。
    t>twarmupt > t_{\text{warmup}}
  3. 条件触发同时满足两个条件时 Alert_t 置为 1,否则为 0,这是规则型告警的基本形态。
    Alertt={1,条件成立0,否则\text{Alert}_t = \begin{cases} 1, & \text{条件成立} \\ 0, & \text{否则} \end{cases}

工程落地实践

选仪表盘就像选车:通勤代步选省油的电动车,长途车队跑运输得更看重联网调度。TensorBoard 与 Wandb 不是二选一,而是按场景搭配。

选型对比上有三条经验:单机调试、快速看曲线,选 TensorBoard——零成本、无网络依赖;多人协作、需要沉淀实验记录,选 Wandb——云端共享、报表文档化;两者混用也毫无冲突——训练代码同时向本地日志目录和 Wandb 云端各写一份,TensorBoard 负责细节调试,Wandb 负责团队汇报。日志规范方面,固定记录间隔、统一指标命名、把 config 超参一并保存,是实验可复现的基石;大模型监控则要额外关注吞吐量(Tokens/s)、GPU 利用率、显存水位和梯度范数,模型参数动辄百亿,任何一个环节掉链子都烧钱。

训练时长估算决定了日志频率和资源规划。总训练时间由以下公式决定:

工程落地的本质是“把工具用成体系”:TensorBoard 当放大镜,Wandb 当指挥中心,日志规范当行车守则,告警当保险杠。这套组合拳,才撑得起大模型训练这种长跑级别的项目。

Ttotal=Nsamples×EBbatch×Sper sec\displaystyle T_{\text{total}} = \frac{N_{\text{samples}} \times E}{B_{\text{batch}} \times S_{\text{per sec}}}
N 是样本总量,E 是训练轮数,B 是批次大小,S 是每秒处理的批次数。比如 100 万样本、训练 3 轮、批量 32、每秒处理 4 批,时长约为 1000000×3/(32×4)≈23437 秒 ≈ 6.5 小时。
  1. 样本总量与轮数N × E 是模型总共看到的样本次数,相当于总行驶里程。
    Nsamples×EN_{\text{samples}} \times E
  2. 批量吞吐B × S 表示每秒钟处理的样本数,是训练的“平均车速”。
    Bbatch×Sper secB_{\text{batch}} \times S_{\text{per sec}}
  3. 总时长里程除以车速得到总时长 T,再除以期望的日志点数,就能确定每次 log 的间隔步数。
    Ttotal=N×EB×ST_{\text{total}} = \frac{N \times E}{B \times S}

AI 应用场景

大模型训练熔断与告警

阶段:训练监控与运维

解决的问题:大模型训练动辄数周,Loss 变 NaN、GPU 掉卡、梯度爆炸等事故往往发生在深夜。传统做法是人工盯守,人总有松懈时;AI 工程师用 Wandb 设置 Loss 阈值告警、进程崩溃检测、断线自动恢复,让异常在发生后的几十秒内通知到手机。

具体案例:某团队训练 70 亿参数模型,第四天凌晨梯度范数突然飙升 100 倍。Wandb 告警规则“梯度范数 > 50 且持续 3 个 step”立即触发,工程师收到邮件后远程暂停训练、回滚到最近 checkpoint、调低学习率并开启梯度裁剪,避免了近两天的算力浪费。

团队实验管理与报告分享

阶段:实验管理与协作

解决的问题:多人同时调参,Excel 记录实验毫无可追溯性。Wandb 的项目—实验二级结构天然适配团队协作,所有人共享同一块仪表盘,实验报告一键转发,新成员能看懂历史实验的完整上下文。

具体案例:一个 8 人的算法组同时跑 20 个微调实验,用 Wandb 的平行坐标图按数据集、学习率、LoRA rank 三组超参横截面筛选,最终把最优组合整理成一页 Report,附上 Loss 曲线、GPU 利用率和结论,直接分享给业务方,模型迭代效率提升近一倍。

超参数自动搜索

阶段:实验迭代阶段

解决的问题:手动调参就像闭眼拧收音机旋钮,碰上组合爆炸根本试不完。Wandb Sweep 自动编排实验队列,按贝叶斯策略动态挑选超参组合,最大化每一次算力投入的信息量。

具体案例:在为垂直领域微调大模型时,工程师用 Sweep 搜索学习率、批次大小、LoRA 维度和 warmup 比例四个维度,共调度 50 次实验,自动淘汰高 Loss 配置,最终在预算内找到比手工调参低 12% 验证 Loss 的配置组合。

Python 演示

python115 行
import mathimport random  class WandbMock:    """模拟 W&B 的核心接口:init/log/summary/finish"""     def __init__(self, project_name="train-viz-demo"):        self.project_name = project_name        self.logs = []        self.summary = {}     def log(self, metrics):        """模拟 wandb.log:记录一条训练指标"""        self.logs.append(dict(metrics))     def finish(self):        """模拟 wandb.finish:训练结束后归档摘要"""        last = self.logs[-1] if self.logs else {}        self.summary = {            "final_loss": last.get("loss", None),            "final_acc": last.get("accuracy", None),            "total_steps": len(self.logs),        }        print("实验归档完成:", self.project_name, self.summary)     def plot_curve(self):        """用字符画简易 loss 曲线,模拟 TensorBoard 的标量图"""        if not self.logs:            return        max_loss = max(item["loss"] for item in self.logs)        print("=" * 40)        for item in self.logs[::20]:            bar_len = int(item["loss"] / max_loss * 30)            print("loss {:6.3f} | {}".format(                item["loss"], "#" * (30 - bar_len) + " " * bar_len))        print("=" * 40)  class NaiveNN:    """两层感知机:二分类 XOR 问题"""     def __init__(self, in_dim=2, hidden_dim=4):        self.w1 = [[random.uniform(-0.5, 0.5) for _ in range(hidden_dim)]                   for _ in range(in_dim)]        self.b1 = [0.0 for _ in range(hidden_dim)]        self.w2 = [random.uniform(-0.5, 0.5) for _ in range(hidden_dim)]        self.b2 = 0.0     def forward(self, x):        """前向传播:ReLU 隐层 + sigmoid 输出"""        h = [max(0.0, sum(x[i] * self.w1[i][j] for i in range(len(x))) + self.b1[j])             for j in range(len(self.b1))]        z = sum(h[j] * self.w2[j] for j in range(len(h))) + self.b2        sig = 1.0 / (1.0 + math.exp(-z))        return sig, h     def predict(self, x):        sig, _ = self.forward(x)        return 1 if sig >= 0.5 else 0     def train_step(self, x, y, lr=0.5):        """一个步长的梯度下降,返回 loss"""        sig, h = self.forward(x)        loss = -math.log(sig) if y == 1 else -math.log(1.0 - sig)        error = sig - y        for j in range(len(self.w2)):            gw2 = error * h[j]            self.w2[j] -= lr * gw2            for i in range(len(x)):                grad = gw2 * x[i] if h[j] > 0 else 0.0                self.w1[i][j] -= lr * grad            self.b1[j] -= lr * gw2 if h[j] > 0 else 0.0        self.b2 -= lr * error        return loss  def load_xor_data():    """构造 XOR 数据集:四组输入坐标,输出为异或结果"""    xs = [[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]    ys = [0, 1, 1, 0]    return xs, ys  def main():    # 对应真实代码:wandb.init(project="train-viz-demo")    logger = WandbMock(project_name="train-viz-demo")    xs, ys = load_xor_data()    model = NaiveNN(in_dim=2, hidden_dim=8)    epochs = 200     for epoch in range(epochs):        total_loss = 0.0        correct = 0        for x, y in zip(xs, ys):            loss = model.train_step(x)            total_loss += loss            pred = model.predict(x)            correct += 1 if pred == y else 0        acc = correct / len(xs)        avg_loss = total_loss / len(xs)        # 对应真实代码:wandb.log({"loss": avg_loss, "accuracy": acc})        logger.log({            "epoch": epoch,            "loss": round(avg_loss, 4),            "accuracy": round(acc, 4),            "lr": round(0.5 / (1 + 0.01 * epoch), 4),        })     logger.plot_curve()    logger.finish()  if __name__ == "__main__":    main()
目的:用纯 Python 实现一个两层感知机训练 XOR 任务,并用 WandbMock 模拟 Wandb 的 init / log / finish 流程,演示“训练—记录—可视化”的完整闭环。换到真实项目时,只需把 WandbMock 替换为 import wandb,即可获得完整云端仪表盘。
  1. logger = WandbMock(project_name="train-viz-demo")对应真实 wandb.init(),建立一次实验的上下文,是记录所有指标的起点。
  2. loss = model.train_step(x)执行单步梯度下降,返回当前样本的损失,供外层聚合。
  3. acc = correct / len(xs)每轮统计准确率,正是正文中 Acc = 正确数 / 总数 的实现。
  4. logger.log({...})对应真实 wandb.log(),把 epoch、loss、accuracy、lr 打包成一条指标记录。
  5. logger.plot_curve()模拟 TensorBoard / Wandb 的标量图,把 Loss 序列打印成字符画曲线。
  6. logger.finish()对应真实 wandb.finish(),训练结束统一归档 summary 信息。

常见误区

误区可视化就是看训练集的 Loss 曲线,Loss 在降就是万事大吉,什么直方图、梯度范数都是锦上添花。

正解Loss 曲线只告诉你“整体油耗”,却不告诉你“哪个气缸在漏油”。大模型训练中,梯度爆炸可能让 Loss 看似下降实则权重已毁,梯度消失则让 Loss 陷入漫长平台期。直方图和梯度范数能提前几小时暴露问题,等于给训练装上了发动机故障诊断仪,而不只是一个速度表。

为何常见:入门教程最常展示的就是 Loss 曲线,新手自然先入为主,加上直方图需要多一层抽象理解,容易被跳过。

误区TensorBoard 就是个曲线绘制工具,除了 scalar 折线图没别的本事。

正解TensorBoard 的 scalar(折线)、histogram(直方图)、graph(计算图)、projector(嵌入投影仪)、image/text(图像文本)覆盖了从标量到高维向量的全部可视化需求。模型结构、权重分布、Embedding 聚类都能看,功能远比“速度表”丰富。

为何常见:多数博客示例只教 add_scalar,其他 API 曝光度低,导致功能被严重低估。

误区既然是监控,就应该每个 step 都记录一次,这样曲线最完整、信息最多。

正解每个 step 都写文件或上传网络会带来不可忽视的 I/O 开销,大模型动辄数万 step,高频日志让训练整体变慢,甚至出现 GPU 等待日志线程的“空转油耗”。正确做法是每 N 步或每个 epoch 记录一次,并配合 EMA 平滑兼顾曲线完整度与性能。

为何常见:“监控粒度越细越安全”是直觉思维,但没算上分布式训练中日志 I/O 的真实成本。

误区Wandb 是 TensorBoard 的升级替代品,生产环境直接全量切换,TensorBoard 该淘汰了。

正解两者定位不同:TensorBoard 轻量、本地、无网络依赖,适合单机快速调试;Wandb 擅长云端协作、实验管理和告警。工程上的常见组合是训练代码同时向两处写日志——本地 TB 看细节,云端 Wandb 做团队汇报,互为冗余而各司其职。

为何常见:工具对比类文章喜欢制造“二选一”的戏剧冲突,实际工程中成熟团队几乎都是混合使用。

面试题

Q1. 在 Wandb 中,记录一条训练指标最常用的 API 是?

单选题 · easy

  • A.wandb.init() 初始化项目
  • B.wandb.log() 记录指标← 正确答案
  • C.wandb.finish() 结束运行
  • D.wandb.config() 保存配置

答案:B。wandb.log() 负责将指标字典写入当前 run,是记录 Loss、准确率等标量的核心入口。init 只是初始化实验上下文,finish 用于收尾归档,config 用于保存超参数,都不是逐条记录指标的工具。

Q2. TensorBoard 启动后默认打开的端口是?

单选题 · easy

  • A.端口 6006← 正确答案
  • B.端口 8000
  • C.端口 8888
  • D.端口 3000

答案:A。TensorBoard 服务默认跑在 6006 端口,浏览器访问 http://localhost:6006 即可看到面板。8000 多用于 Django 等应用,8888 是 Jupyter Notebook 默认端口,3000 常见于 Node.js 开发服务,都不属于 TensorBoard 默认端口。

Q3. EMA 平滑系数 β 越接近 1,曲线会?

单选题 · easy

  • A.越平滑但反应越慢← 正确答案
  • B.越平滑且反应越快
  • C.越尖锐且反应越快
  • D.越尖锐且反应越慢

答案:A。β 决定历史记忆的权重。β 越接近 1,历史占比越大,曲线越平滑、对新变化的响应越迟缓,就像阻尼很强的悬挂系统。四个选项中只有 A 同时正确描述了“平滑”和“反应慢”两个维度。

Q4. 梯度范数在训练中持续飙升,最可能说明?

单选题 · mid

  • A.模型出现了梯度爆炸← 正确答案
  • B.模型出现了梯度消失
  • C.模型正在快速收敛
  • D.学习率设置偏低

答案:A。梯度范数是所有参数梯度的总长度,持续飙升意味着某层梯度失控增长,典型表现就是梯度爆炸,容易导致 Loss 变 NaN。梯度消失则相反,范数趋近于零;快速收敛时范数逐步下降而非飙升。

Q5. 在 Wandb 中把多次运行归入同一逻辑组,常用参数是?

单选题 · mid

  • A.group 参数归并← 正确答案
  • B.name 参数命名
  • C.job 参数标记
  • D.type 参数分类

答案:A。wandb.init(group="xxx") 可以把一组相关运行归并为同一个逻辑组,方便在聚合视图中总览。name 只是给单次运行起名,type 用于标记运行类型,job 并非 Wandb 的官方分组参数。

Q6. 大模型训练时设置日志记录频率,正确原则是?

单选题 · mid

  • A.平衡开销与曲线密度← 正确答案
  • B.每个 step 都必记
  • C.只记录最后结果
  • D.频率越低越好

答案:A。日志写入和网络上传都有 I/O 开销,高频记录拖慢训练、低频记录丢失细节,正确做法是每 N 步或每 epoch 记录一次,找到开销与曲线密度的平衡点。B 过于极端,C 失去了监控意义,D 则让可视化失去诊断能力。

Q7. TensorBoard 能展示的图表类型包含哪些?

多选题 · mid

  • A.标量折线图← 正确答案
  • B.权重直方图← 正确答案
  • C.计算图结构← 正确答案
  • D.SQL 数据表格

答案:ABC。TensorBoard 的 scalar 展示标量折线、histogram 展示权重/梯度分布、graph 展示模型计算图,这些都是它的核心面板。SQL 数据表格不是 TensorBoard 的功能,关系型数据库查询由数据管理系统负责。

Q8. Wandb 告警机制支持的触发原因包括?

多选题 · mid

  • A.Loss 超过设定阈值← 正确答案
  • B.训练进程意外中断← 正确答案
  • C.模型参数量自动增多
  • D.梯度范数越过上线← 正确答案

答案:ABD。Wandb 告警可覆盖指标越线(Loss、梯度范数阈值)和进程崩溃等异常事件。模型参数量在训练过程中是静态的,不会“自动增多”,因此不属于告警触发条件。

Q9. 同时使用 Wandb 与 TensorBoard 的合理方式是?

单选题 · single

  • A.Wandb 管云端协作、TB 管本地细节← 正确答案
  • B.只用一个即可无需两者
  • C.TB 负责云端但 Wandb 负责本地
  • D.Wandb 应全权替代 TB 全部功能

答案:A。成熟团队通常让训练代码同时写两路日志:TensorBoard 留在本地做细粒度调试、断网可用;Wandb 上传云端做团队共享、实验管理和告警。两者定位不重叠,B、C、D 都违背了“各司其职、互为补充”的工程共识。

Q10. 关于大模型训练可视化,正确的工程实践有哪些?

单选题 · multiple

  • A.同时监控梯度与损失指标← 正确答案
  • B.设定告警阈值快速熔断← 正确答案
  • C.关闭平滑只看原始曲线
  • D.只用训练集 Loss 评估

答案:AB。大模型监控必须同时盯梯度范数和 Loss,前者暴露梯度爆炸/消失的早期信号,后者反映整体收敛;告警熔断能及时止损。C 错误,平滑曲线才利于看长期趋势;D 错误,只用训练集 Loss 评估会忽略过拟合,必须结合验证集指标。