DAY 47 Tensorboard的使用介绍

知识点回顾:

  1. tensorboard 的发展历史和原理
  2. tensorboard 的常见操作
  3. tensorboard 在 cifar 上的实战:MLP 和 CNN 模型

你作为零基础的 Python 和机器学习学习者,想要系统掌握 TensorBoard 的核心知识(发展历史与原理、常见操作、CIFAR 数据集上的 MLP/CNN 实战),我会用最通俗的语言、贴近生活的例子,配合完整的代码步骤,一步步拆解,确保你能完全理解。


一、TensorBoard 的发展历史和原理(零基础友好版)

1. 发展历史:一句话讲清

TensorBoard 是TensorFlow 官方配套的可视化工具,最早在 2015 年随 TensorFlow 1.x 一起发布(当时 TensorFlow 刚开源);2019 年 TensorFlow 2.x 重构后,TensorBoard 变得更易用(比如和 Keras 深度整合),现在不仅支持 TensorFlow,还能适配 PyTorch 等框架,是机器学习领域最常用的 "可视化仪表盘"。

2. 核心原理:用生活例子讲透

先给你一个核心比喻:

你可以把训练机器学习模型比作 "熬一锅汤":

  • 汤的味道(模型准确率)、火候大小(损失值)、食材比例(模型权重)是关键指标;
  • 如果只看数字(比如 "第 10 步损失 = 0.8,第 20 步 = 0.7"),很难直观判断汤熬得好不好;
  • TensorBoard 就是 "厨房仪表盘":把这些数字转换成曲线图、结构图、图片,让你一眼看清 "熬汤进度"。
原理拆解(3 个核心步骤)
  1. 数据写入:在训练代码里,告诉 TensorBoard "要记录哪些指标"(比如每步的损失、准确率),这些数据会被保存到指定文件夹的 "Event 文件" 里(类似熬汤时记的 "烹饪日志");
  2. 服务启动:在终端输入命令,让 TensorBoard "读取烹饪日志";
  3. 网页展示:打开浏览器,就能看到可视化的指标曲线、模型结构图等(类似看仪表盘)。

二、TensorBoard 的常见操作(手把手教)

前置准备:安装

TensorBoard 是 TensorFlow 的配套工具,安装 TensorFlow 后自动附带,执行以下命令安装(新手建议用 pip):

pip install tensorflow # 安装TensorFlow(含TensorBoard)

操作 1:基础使用(记录模拟的 "损失值")

先写一段极简代码,模拟训练时的损失值变化,带你走完 "写入日志→启动 TensorBoard→查看结果" 的完整流程。

步骤 1:编写代码(写入模拟损失值)
python 复制代码
# 导入TensorFlow库(零基础记:import是"拿工具")
import tensorflow as tf
# 导入时间模块,生成唯一日志文件夹(避免覆盖)
from datetime import datetime

# 1. 创建日志文件夹(格式:logs/年-月-日_时-分-秒)
log_dir = f"logs/basic/{datetime.now().strftime('%Y%m%d-%H%M%S')}"
# 2. 初始化"日志写入器"(相当于打开"烹饪日志本")
writer = tf.summary.create_file_writer(log_dir)

# 3. 模拟训练100步,记录每步的损失值(损失从10逐渐降到1)
with writer.as_default():  # 表示接下来的记录都写入这个日志
    for step in range(100):
        # 模拟损失值:step越大,损失越小(符合训练规律)
        loss = 10 - step * 0.09
        # 记录标量(scalar):参数1=指标名,参数2=指标值,参数3=步数
        tf.summary.scalar('训练损失', loss, step=step)
        # 强制写入(避免数据缓存)
        writer.flush()

# 4. 关闭写入器(相当于写完日志合上书)
writer.close()
print(f"日志已写入:{log_dir}")
步骤 2:启动 TensorBoard
  1. 打开电脑的 "终端"(Windows 是 CMD/PowerShell,Mac/Linux 是终端);
  2. 输入以下命令(注意替换log_dir为你代码里的实际路径,比如logs/basic):

tensorboard --logdir=logs/basic --port=6006

  • --logdir:指定日志文件夹路径(只需要到basic层,TensorBoard 会自动找子文件夹);
  • --port=6006:指定端口(默认 6006,避免端口冲突)。
步骤 3:查看可视化结果
  1. 终端会输出类似TensorBoard 2.15.0 at http://localhost:6006/ (Press CTRL+C to quit)的信息;
  2. 打开浏览器,输入http://localhost:6006,就能看到 TensorBoard 界面:
    • 点击左侧的Scalars(标量面板),就能看到 "训练损失" 的曲线(从 10 逐渐下降到 1);
    • 这个面板是 TensorBoard 最常用的,专门看 "损失、准确率" 等数值的变化趋势。
操作 2:常见可视化面板介绍
面板名称 作用(通俗解释) 适用场景
Scalars 看数值变化曲线(比如损失、准确率) 训练过程监控(必用)
Graphs 看模型的结构图(比如神经网络的层) 检查模型结构是否正确
Images 可视化图片样本(比如 CIFAR 的图片) 查看输入数据、模型输出的图片
Histograms 看权重 / 偏置的分布变化 分析模型参数是否合理
Projector 高维数据降维可视化(比如图片的特征向量) 分析数据的聚类效果

新手先重点掌握ScalarsGraphs,这两个是最核心的。


三、TensorBoard 在 CIFAR-10 上的实战(MLP 和 CNN)

先了解 CIFAR-10 数据集

CIFAR-10 是机器学习入门的 "标配数据集":

  • 包含 10 类彩色图片(飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船、卡车);
  • 每张图片 32×32 像素(很小,适合新手训练);
  • 分为 5 万张训练集、1 万张测试集。

实战 1:MLP(多层感知机)+ TensorBoard

MLP 是 "全连接神经网络",特点是只能处理一维数据,所以需要把 32×32×3 的图片展平成 3072 维的一维向量(32×32×3=3072)。

完整代码(带详细注释)
python 复制代码
import tensorflow as tf
from datetime import datetime

# ====================== 步骤1:加载并预处理CIFAR-10 ======================
# 加载数据集(自动下载,第一次运行会慢一点)
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()

# 预处理:
# 1. 归一化:把像素值从0-255转换成0-1(神经网络对0-1的数值更敏感)
x_train = x_train / 255.0
x_test = x_test / 255.0

# 2. MLP需要一维数据,把32×32×3的图片展平成3072维向量
x_train_flat = tf.reshape(x_train, [-1, 32*32*3])  # -1表示自动计算样本数
x_test_flat = tf.reshape(x_test, [-1, 32*32*3])

# ====================== 步骤2:构建MLP模型 ======================
def build_mlp_model():
    model = tf.keras.Sequential([
        # 输入层:指定输入形状为3072维
        tf.keras.layers.Input(shape=(32*32*3,)),
        # 隐藏层1:512个神经元,激活函数ReLU(常用)
        tf.keras.layers.Dense(512, activation='relu'),
        # 隐藏层2:256个神经元
        tf.keras.layers.Dense(256, activation='relu'),
        # 输出层:10个神经元(对应10类),激活函数softmax(分类任务专用)
        tf.keras.layers.Dense(10, activation='softmax')
    ])
    # 编译模型:指定优化器、损失函数、评估指标
    model.compile(
        optimizer='adam',  # 常用优化器,自动调整学习率
        loss='sparse_categorical_crossentropy',  # 分类任务损失函数
        metrics=['accuracy']  # 监控准确率
    )
    return model

# ====================== 步骤3:配置TensorBoard回调 ======================
# 创建MLP专属日志文件夹
log_dir_mlp = f"logs/cifar10/mlp/{datetime.now().strftime('%Y%m%d-%H%M%S')}"
# 定义TensorBoard回调(Keras内置,自动记录训练指标)
tensorboard_callback_mlp = tf.keras.callbacks.TensorBoard(
    log_dir=log_dir_mlp,  # 日志保存路径
    histogram_freq=1,    # 每1个epoch记录一次权重直方图
    write_graph=True,    # 保存模型结构图
    write_images=True    # 保存图片(如果有)
)

# ====================== 步骤4:训练模型 ======================
mlp_model = build_mlp_model()
# 开始训练(epochs=5:训练5轮,新手先少训点,快一点)
history_mlp = mlp_model.fit(
    x_train_flat, y_train,
    epochs=5,
    batch_size=64,  # 每次喂64个样本给模型
    validation_split=0.2,  # 用20%的训练集做验证
    callbacks=[tensorboard_callback_mlp]  # 加入TensorBoard回调
)

# 测试模型
test_loss, test_acc = mlp_model.evaluate(x_test_flat, y_test)
print(f"MLP模型测试准确率:{test_acc:.2f}")

实战 2:CNN(卷积神经网络)+ TensorBoard

CNN 是 "卷积神经网络",专门处理二维图片数据,不需要展平,能直接提取图片的空间特征(比如边缘、纹理),效果比 MLP 好很多。

完整代码(带详细注释)
python 复制代码
import tensorflow as tf
from datetime import datetime

# ====================== 步骤1:加载并预处理CIFAR-10(和MLP一致,无需展平) ======================
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
x_train = x_train / 255.0
x_test = x_test / 255.0

# ====================== 步骤2:构建CNN模型 ======================
def build_cnn_model():
    model = tf.keras.Sequential([
        # 输入层:32×32×3的彩色图片
        tf.keras.layers.Input(shape=(32, 32, 3)),
        # 卷积层1:提取基础特征(比如边缘)
        tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'),
        # 池化层1:缩小图片尺寸,减少计算量
        tf.keras.layers.MaxPooling2D((2, 2)),
        # 卷积层2:提取更复杂的特征(比如形状)
        tf.keras.layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
        # 池化层2
        tf.keras.layers.MaxPooling2D((2, 2)),
        # 卷积层3
        tf.keras.layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
        # 展平层:把二维特征转换成一维,供全连接层使用
        tf.keras.layers.Flatten(),
        # 全连接层
        tf.keras.layers.Dense(64, activation='relu'),
        # 输出层:10类分类
        tf.keras.layers.Dense(10, activation='softmax')
    ])
    # 编译模型
    model.compile(
        optimizer='adam',
        loss='sparse_categorical_crossentropy',
        metrics=['accuracy']
    )
    return model

# ====================== 步骤3:配置TensorBoard回调 ======================
# 创建CNN专属日志文件夹(和MLP分开,方便对比)
log_dir_cnn = f"logs/cifar10/cnn/{datetime.now().strftime('%Y%m%d-%H%M%S')}"
tensorboard_callback_cnn = tf.keras.callbacks.TensorBoard(
    log_dir=log_dir_cnn,
    histogram_freq=1,
    write_graph=True,
    write_images=True
)

# ====================== 步骤4:训练模型 ======================
cnn_model = build_cnn_model()
history_cnn = cnn_model.fit(
    x_train, y_train,
    epochs=5,
    batch_size=64,
    validation_split=0.2,
    callbacks=[tensorboard_callback_cnn]
)

# 测试模型
test_loss, test_acc = cnn_model.evaluate(x_test, y_test)
print(f"CNN模型测试准确率:{test_acc:.2f}")

实战 3:启动 TensorBoard 对比两个模型

  1. 打开终端,输入以下命令(日志文件夹是logs/cifar10,包含 MLP 和 CNN 的子文件夹):
  1. 打开浏览器http://localhost:6006,查看关键面板:
  • Scalars:能看到 MLP 和 CNN 的 "loss"(损失)、"accuracy"(准确率)曲线,你会发现 CNN 的准确率更高、损失下降更快;
  • Graphs:切换到 "mlp" 和 "cnn" 的标签,能看到两个模型的结构图,CNN 有卷积层、池化层,结构更复杂;
  • Images:能看到 CIFAR-10 的图片样本,验证输入数据是否正确。

总结(核心知识点回顾)

  1. TensorBoard 核心逻辑:代码中通过 "回调 / 写入器" 记录指标→保存到日志文件夹→启动服务→浏览器查看可视化结果;
  2. 新手必掌握操作:Scalars 面板看损失 / 准确率曲线(监控训练效果)、Graphs 面板看模型结构(检查是否搭建正确);
  3. 实战关键结论:在 CIFAR-10 上,CNN(处理二维图片)的效果远好于 MLP(处理一维数据),TensorBoard 能直观对比两者的训练差异。

用代码展示如何使用SummaryWriter写入数据?

你想要通过具体的代码示例,清晰地展示如何使用SummaryWriter向 TensorBoard 写入各类数据,作为零基础学习者,我会用最简洁的代码、最详细的注释,覆盖SummaryWriter最常用的写入场景,确保你能直接运行并看懂每一步。

注意:SummaryWriterPyTorch 生态 中用于 TensorBoard 的核心类(和上一轮 TensorFlow 的tf.summary对应),先明确这个背景,避免你混淆框架。


前置准备

首先确保安装了必要的依赖(PyTorch 和 TensorBoard),打开终端执行:

完整代码示例:SummaryWriter 写入各类数据

下面的代码会演示写入标量(最常用)、图片、直方图、文本 这 4 类核心数据,每一步都有详细注释,你可以直接复制运行。

python 复制代码
# 1. 导入核心库
import torch
# 导入SummaryWriter(PyTorch对接TensorBoard的核心类)
from torch.utils.tensorboard import SummaryWriter
import numpy as np
from datetime import datetime

# 2. 初始化SummaryWriter(关键步骤)
# 日志路径:logs/summary_writer/时间戳(避免覆盖旧日志)
log_dir = f"logs/summary_writer/{datetime.now().strftime('%Y%m%d-%H%M%S')}"
# 初始化Writer:相当于打开"日志本",所有写入操作都通过这个对象完成
writer = SummaryWriter(log_dir=log_dir)

# ====================== 场景1:写入标量(Scalar)(最常用) ======================
# 标量用于记录:损失值、准确率、学习率等单一数值的变化
# 模拟训练100步,记录"训练损失"和"验证准确率"
for step in range(100):
    # 模拟损失:从2.0逐渐下降到0.1(符合训练规律)
    train_loss = 2.0 - step * 0.019
    # 模拟验证准确率:从0.5逐渐上升到0.95
    val_acc = 0.5 + step * 0.0045
    
    # 写入标量:参数1=指标名称(支持多级目录,比如"loss/train"),参数2=数值,参数3=步数
    writer.add_scalar(tag="loss/train", scalar_value=train_loss, global_step=step)
    writer.add_scalar(tag="accuracy/val", scalar_value=val_acc, global_step=step)

# ====================== 场景2:写入图片(Image) ======================
# 用于可视化:数据集样本、模型输出图片、特征图等
# 生成3张模拟的32×32彩色图片(形状:[数量, 通道数, 高度, 宽度],PyTorch图片格式)
# np.random.randn生成随机像素值,范围(-1,1),后续调整到(0,1)
fake_images = np.random.randn(3, 3, 32, 32)  # 3张图、3通道(RGB)、32×32像素
fake_images = (fake_images - fake_images.min()) / (fake_images.max() - fake_images.min())  # 归一化到0-1

# 写入图片:参数1=图片标签,参数2=图片数据,参数3=步数,参数4=每行显示的图片数
writer.add_images(
    tag="fake_cifar_images",  # 标签名
    img_tensor=fake_images,   # 图片数据(必须是CHW或NCHW格式)
    global_step=0,            # 步数(固定0即可,因为只写一次)
    dataformats="NCHW"        # 数据格式:N(数量)-C(通道)-H(高)-W(宽)
)

# ====================== 场景3:写入直方图(Histogram) ======================
# 用于可视化:模型权重、偏置的分布,查看参数是否合理
# 模拟一组模型权重(正态分布)
fake_weights = torch.randn(1000)  # 1000个随机数,模拟一层神经网络的权重

# 写入直方图:参数1=标签,参数2=数据,参数3=步数
writer.add_histogram(tag="model/weight", values=fake_weights, global_step=0)

# ====================== 场景4:写入文本(Text) ======================
# 用于记录:训练参数、备注信息等
writer.add_text(
    tag="training_info",  # 标签名
    text_string=f"训练时间:{datetime.now()}\n学习率:0.001\n批次大小:64",  # 要写入的文本
    global_step=0
)

# ====================== 收尾:关闭SummaryWriter ======================
# 关闭Writer,确保所有数据都写入日志文件(避免数据丢失)
writer.close()

print(f"所有数据已写入日志文件夹:{log_dir}")
print("接下来在终端执行以下命令启动TensorBoard:")
print(f"tensorboard --logdir={log_dir} --port=6006")

运行代码 + 查看结果的步骤

步骤 1:运行代码

将上述代码保存为summary_writer_demo.py,在终端执行:

python summary_writer_demo.py

运行完成后,会在当前目录生成logs/summary_writer/时间戳文件夹,里面就是 TensorBoard 需要的日志文件。

步骤 2:启动 TensorBoard

在终端输入以下命令(路径和代码中log_dir一致):

tensorboard --logdir=logs/summary_writer --port=6006

提示:只需要指定到summary_writer层即可,TensorBoard 会自动扫描子文件夹。

步骤 3:查看可视化结果

打开浏览器,输入http://localhost:6006,就能看到对应的数据:

  • 点击左侧Scalars:能看到 "训练损失" 下降、"验证准确率" 上升的曲线(核心!);
  • 点击左侧Images:能看到 3 张随机生成的模拟图片;
  • 点击左侧Histograms:能看到模拟权重的分布直方图;
  • 点击左侧Text:能看到我们写入的训练备注信息。

关键代码解释(零基础友好)

代码行 作用解释
writer = SummaryWriter(log_dir=log_dir) 初始化日志写入器,指定日志保存路径,是所有写入操作的基础
writer.add_scalar(tag, value, step) 写入标量(最常用),tag是指标名(支持多级目录,比如loss/train),step是训练步数
writer.add_images() 写入多张图片,注意数据格式必须是NCHW(数量 - 通道 - 高 - 宽),这是 PyTorch 的标准格式
writer.close() 关闭写入器,强制将缓存的数据写入文件,避免数据丢失(新手一定要加!)

总结

  1. SummaryWriter的核心流程:初始化(指定日志路径)→ 调用 add_* 方法写入数据 → 关闭写入器
  2. 最常用的方法是add_scalar,用于监控训练损失、准确率等核心指标;
  3. 启动 TensorBoard 时,--logdir只需指定到包含日志的父文件夹,无需到具体时间戳子文件夹,方便对比多组实验。

如果运行时遇到 "端口被占用"(比如提示Port 6006 is already in use),只需把端口改成 6007 即可:tensorboard --logdir=logs/summary_writer --port=6007

用代码展示如何使用SummaryWriter写入标量数据?

你想要一份只聚焦标量数据写入 的极简代码示例,清晰展示SummaryWriter如何记录训练过程中的核心标量(比如损失、准确率),作为零基础学习者,我会剔除所有无关代码,只保留标量相关的核心逻辑,同时配上详细的操作步骤和通俗解释。

标量数据是 TensorBoard 中最常用、最核心的可视化内容(比如训练损失、验证准确率、学习率等单一数值),掌握这个就能满足 80% 的 TensorBoard 使用场景。


前置准备(仅需 1 步)

确保安装了 PyTorch 和 TensorBoard(如果已安装可跳过),打开终端执行:

完整代码(仅标量写入)

这份代码模拟了 100 步训练过程,只记录 "训练损失" 和 "验证准确率" 两个标量,每一行都有通俗注释,可直接复制运行:

python 复制代码
# 1. 导入核心工具:SummaryWriter是写入TensorBoard的核心类
from torch.utils.tensorboard import SummaryWriter
# 导入时间模块:生成唯一日志文件夹,避免覆盖旧数据
from datetime import datetime

# 2. 初始化SummaryWriter(关键!相当于打开一个"标量日志本")
# 日志保存路径:logs/scalar_demo/当前时间(比如20251226-153000)
log_dir = f"logs/scalar_demo/{datetime.now().strftime('%Y%m%d-%H%M%S')}"
writer = SummaryWriter(log_dir=log_dir)  # 传入路径,初始化写入器

# 3. 模拟训练过程,写入标量数据(核心操作)
# 循环100步,模拟每一步的训练损失和验证准确率变化
for step in range(100):
    # 模拟训练损失:从2.0逐步降到0.1(符合训练时损失下降的规律)
    train_loss = 2.0 - (step * 0.019)
    # 模拟验证准确率:从0.5逐步升到0.95(符合训练时准确率上升的规律)
    val_acc = 0.5 + (step * 0.0045)
    
    # 写入"训练损失"标量
    # 参数说明:
    # tag:标量名称(支持多级目录,比如"loss/train",方便分类)
    # scalar_value:标量的具体数值
    # global_step:训练步数(对应x轴,必须传,否则曲线无法按步骤展示)
    writer.add_scalar(tag="loss/train", scalar_value=train_loss, global_step=step)
    
    # 写入"验证准确率"标量(和损失分开,方便TensorBoard中分类查看)
    writer.add_scalar(tag="accuracy/val", scalar_value=val_acc, global_step=step)

# 4. 关闭写入器(重要!确保所有数据都写入文件,避免丢失)
writer.close()

# 打印提示信息,方便后续操作
print(f"✅ 标量数据已写入日志文件夹:{log_dir}")
print("\n📌 下一步操作(复制到终端执行):")
print(f"tensorboard --logdir=logs/scalar_demo --port=6006")

运行代码 + 查看结果(3 步搞定)

步骤 1:运行代码

将上述代码保存为scalar_writer_demo.py,打开终端,进入代码所在文件夹,执行:

python scalar_writer_demo.py

运行后会在当前目录生成logs/scalar_demo/时间戳文件夹,里面就是 TensorBoard 能识别的标量日志。

步骤 2:启动 TensorBoard

在终端执行以下命令(无需指定到具体时间戳子文件夹,TensorBoard 会自动扫描):

终端会输出类似TensorBoard 2.16.2 at http://localhost:6006/ (Press CTRL+C to quit)的提示,说明启动成功。

步骤 3:查看标量曲线

打开浏览器,输入http://localhost:6006,就能看到 TensorBoard 界面:

  1. 点击左侧菜单栏的Scalars(标量面板);
  2. 右侧会显示两个曲线:
    • loss/train:从 2.0 逐渐下降到 0.1 的曲线(红色 / 蓝色);
    • accuracy/val:从 0.5 逐渐上升到 0.95 的曲线;
  3. 可以用鼠标滚轮放大 / 缩小曲线,也能拖动查看某一步的具体数值(鼠标悬停在曲线上即可显示)。

核心代码通俗解释(零基础友好)

代码行 通俗解释
writer = SummaryWriter(log_dir=log_dir) 初始化写入器,相当于 "打开一个专门记录标量的日志本",指定日志存在哪个文件夹
writer.add_scalar("loss/train", train_loss, step) 往日志本里写一行:"第 step 步,训练损失是 train_loss",tag/分隔是为了分类(比如 loss 和 accuracy 分开)
writer.close() 写完日志后 "合上本子",强制把内存中的数据写入文件,避免数据丢失(新手一定要加!)

常见小问题解决

  • 端口被占用 :如果提示Port 6006 is already in use,把端口改成 6007 即可:tensorboard --logdir=logs/scalar_demo --port=6007
  • 曲线不显示 :检查global_step是否传了(必须传,否则 x 轴无数据),或日志路径是否正确。
  • 中文乱码:如果后续要写中文标签,无需额外设置,TensorBoard 默认支持中文。

总结

  1. SummaryWriter写入标量的核心流程:初始化写入器 → 循环调用 add_scalar 写入(tag + 数值 + 步数) → 关闭写入器
  2. tag建议用分类/名称的格式(比如loss/train),方便在 TensorBoard 中分类查看;
  3. global_step是标量曲线的 x 轴,必须和训练步数对应,才能看到 "随训练过程变化" 的趋势。

这是 TensorBoard 最基础也最核心的用法,掌握后就能监控自己的模型训练效果了。

如何使用SummaryWriter在TensorBoard中可视化模型结构?

你想知道如何通过SummaryWriter在 TensorBoard 中直观可视化 PyTorch 模型的结构(比如神经网络的层、输入输出形状、参数流向),作为零基础学习者,我会用极简的代码、通俗的解释,带你完成从搭建模型到可视化结构的全流程 ------ 这是检查模型是否搭建正确的核心技巧。

核心原理:SummaryWriteradd_graph()方法能解析 PyTorch 模型的计算图,结合模拟输入数据(必须!),在 TensorBoard 中生成可视化的模型结构图,让你一眼看清 "数据从输入层→隐藏层→输出层" 的流向。


前置准备(已安装可跳过)

确保依赖齐全,终端执行:

完整代码示例(可视化 MLP+CNN 模型结构)

下面的代码会搭建两个经典模型(MLP 多层感知机、CNN 卷积神经网络),并分别可视化它们的结构,每一步都有详细注释,可直接复制运行:

python 复制代码
# 1. 导入核心库
import torch
import torch.nn as nn  # PyTorch构建模型的核心库
from torch.utils.tensorboard import SummaryWriter
from datetime import datetime

# 2. 定义要可视化的模型(先搭两个简单模型)
# 模型1:MLP(多层感知机,处理一维数据,比如展平的图片)
class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()
        # 定义模型层:输入层(3072) → 隐藏层1(512) → 隐藏层2(256) → 输出层(10)
        self.layers = nn.Sequential(
            nn.Linear(32*32*3, 512),  # 32×32×3是CIFAR-10图片展平后的维度
            nn.ReLU(),                # 激活函数
            nn.Linear(512, 256),
            nn.ReLU(),
            nn.Linear(256, 10)        # 10类分类任务的输出层
        )
    
    def forward(self, x):
        # 前向传播:定义数据如何流过模型
        return self.layers(x)

# 模型2:CNN(卷积神经网络,处理二维图片数据)
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        # 卷积层:提取图片特征
        self.conv_layers = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3, padding=1),  # 输入3通道,输出32通道
            nn.ReLU(),
            nn.MaxPool2d(2, 2),                          # 池化层缩小尺寸
            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2)
        )
        # 全连接层:分类
        self.fc_layers = nn.Sequential(
            nn.Flatten(),                                # 展平卷积特征
            nn.Linear(64*8*8, 64),                       # 8×8是池化后的尺寸
            nn.ReLU(),
            nn.Linear(64, 10)
        )
    
    def forward(self, x):
        x = self.conv_layers(x)
        x = self.fc_layers(x)
        return x

# 3. 初始化SummaryWriter(指定日志路径)
log_dir = f"logs/model_structure/{datetime.now().strftime('%Y%m%d-%H%M%S')}"
writer = SummaryWriter(log_dir=log_dir)

# 4. 可视化模型结构(核心操作)
# ========== 可视化MLP模型 ==========
# 关键:创建和模型输入形状匹配的模拟数据(MLP输入是展平的32×32×3图片)
mlp_model = MLP()  # 实例化MLP模型
mlp_dummy_input = torch.randn(1, 32*32*3)  # 模拟输入:1个样本,3072维(32×32×3)
# 写入模型结构:参数1=模型实例,参数2=模拟输入(告诉TensorBoard输入形状)
writer.add_graph(mlp_model, input_to_model=mlp_dummy_input)

# ========== 可视化CNN模型 ==========
# 关键:CNN输入是32×32×3的图片(形状:[样本数, 通道数, 高, 宽])
cnn_model = CNN()  # 实例化CNN模型
cnn_dummy_input = torch.randn(1, 3, 32, 32)  # 模拟输入:1个样本,3通道,32×32像素
writer.add_graph(cnn_model, input_to_model=cnn_dummy_input)

# 5. 关闭SummaryWriter(确保数据写入文件)
writer.close()

print(f"✅ 模型结构已写入日志文件夹:{log_dir}")
print("\n📌 启动TensorBoard(复制到终端执行):")
print(f"tensorboard --logdir=logs/model_structure --port=6006")

运行代码 + 查看模型结构(3 步搞定)

步骤 1:运行代码

将代码保存为visualize_model.py,终端执行:

运行后会生成logs/model_structure/时间戳文件夹,里面包含模型结构的日志数据。

步骤 2:启动 TensorBoard

终端执行以下命令(无需指定到具体时间戳子文件夹):

启动成功后,终端会输出http://localhost:6006的访问地址。

步骤 3:查看模型结构(核心!)

打开浏览器输入http://localhost:6006,按以下步骤操作:

核心代码通俗解释(零基础友好)

代码行 通俗解释
mlp_model = MLP() 实例化 MLP 模型,相当于 "造一个 MLP 神经网络出来"
mlp_dummy_input = torch.randn(1, 32*32*3) 造一个 "假的输入数据",告诉 TensorBoard:这个模型的输入是 "1 个样本、3072 维" 的向量(必须!因为 PyTorch 模型需要知道输入形状才能确定各层的维度)
writer.add_graph(mlp_model, mlp_dummy_input) 核心操作:让 TensorBoard "解析这个模型",结合假输入画出完整的结构流程图
cnn_dummy_input = torch.randn(1, 3, 32, 32) CNN 的假输入要匹配 "图片格式":1 个样本、3 通道(RGB)、32×32 像素

常见问题解决(新手必看)

问题 1:模型结构不显示 / 报错

  • 原因:没传模拟输入,或模拟输入的形状和模型实际输入不匹配;
  • 解决:确保input_to_model的形状和模型forward方法的输入一致(比如 CNN 必须是[N, C, H, W],MLP 必须是展平的一维)。

问题 2:结构太复杂看不清

  • 解决:切换到Hierarchical视图(顶部下拉框),或把模型拆分成多个Sequential模块(比如代码中 CNN 拆成conv_layersfc_layers),结构会更清晰。

问题 3:看不到层的参数信息

  • 解决:点击结构图中的某一层(比如Conv2d),右侧会弹出 "Attributes" 面板,显示该层的in_channels(输入通道)、out_channels(输出通道)等关键参数。

总结

  1. 可视化模型结构的核心:SummaryWriter.add_graph(模型实例, 模拟输入)模拟输入是关键(告诉 TensorBoard 模型的输入形状);
  2. 模拟输入形状必须和模型forward方法的输入一致(CNN 是[N, C, H, W],MLP 是一维向量);
  3. 在 TensorBoard 的Graphs面板中,用Hierarchical视图能更清晰地看到模型的层级结构,点击层可查看参数细节。

这个技巧能帮你快速检查模型是否搭建正确(比如层的顺序、输入输出形状是否符合预期),是机器学习调试模型的必备技能。

如何使用SummaryWriter在TensorBoard中可视化训练过程中的准确率和损失值曲线?

你想知道如何结合实际的模型训练循环 ,用SummaryWriter把训练 / 验证过程中的准确率、损失值实时写入 TensorBoard,并可视化成直观的曲线 ------ 这是监控模型训练效果的核心方法,我会用零基础友好的代码(基于 MNIST 手写数字数据集,简单易运行),带你完成从训练到可视化的全流程,每一步都有通俗解释。

核心逻辑:在训练的每一轮(epoch)每一步(step) ,调用add_scalar()将损失 / 准确率写入日志,TensorBoard 会自动根据global_step(步数 / 轮数)绘制曲线,让你一眼看清 "损失是否下降、准确率是否上升"。


前置准备(已安装可跳过)

完整代码示例(训练 + 可视化损失 / 准确率)

这份代码包含 "加载数据集→搭建简单模型→训练循环→写入 TensorBoard→可视化" 全流程,用 MNIST 数据集(手写数字,数据量小、训练快),注释详细到每一行:

python 复制代码
# 1. 导入核心库
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
from torch.utils.tensorboard import SummaryWriter
from datetime import datetime

# 2. 配置基础参数(新手可直接用,不用改)
BATCH_SIZE = 64          # 每次喂给模型的样本数
EPOCHS = 5               # 训练轮数(5轮足够看到曲线变化)
LEARNING_RATE = 0.001    # 学习率(控制模型更新速度)
DEVICE = torch.device("cpu")  # 用CPU训练(新手无需GPU)

# 3. 加载MNIST数据集(手写数字,0-9分类)
# 数据预处理:转成Tensor+归一化
transform = transforms.Compose([
    transforms.ToTensor(),  # 把图片转成PyTorch能处理的Tensor格式
    transforms.Normalize((0.1307,), (0.3081,))  # 归一化(MNIST的均值/标准差)
])

# 加载训练集和测试集
train_dataset = datasets.MNIST(
    root='./data', train=True, download=True, transform=transform
)
test_dataset = datasets.MNIST(
    root='./data', train=False, download=True, transform=transform
)

# 数据加载器(批量读取数据)
train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False)

# 4. 搭建简单的MLP模型(适合MNIST分类)
class SimpleMLP(nn.Module):
    def __init__(self):
        super(SimpleMLP, self).__init__()
        self.model = nn.Sequential(
            nn.Flatten(),          # 展平28×28的图片成784维向量
            nn.Linear(784, 128),   # 隐藏层1:784→128
            nn.ReLU(),             # 激活函数
            nn.Linear(128, 64),    # 隐藏层2:128→64
            nn.ReLU(),
            nn.Linear(64, 10)      # 输出层:64→10(对应0-9分类)
        )
    
    def forward(self, x):
        return self.model(x)

# 5. 初始化SummaryWriter(关键!指定日志保存路径)
# 路径格式:logs/train_metrics/时间戳(避免覆盖旧日志)
log_dir = f"logs/train_metrics/{datetime.now().strftime('%Y%m%d-%H%M%S')}"
writer = SummaryWriter(log_dir=log_dir)

# 6. 初始化模型、损失函数、优化器
model = SimpleMLP().to(DEVICE)  # 实例化模型并放到CPU
criterion = nn.CrossEntropyLoss()  # 分类任务的损失函数
optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)  # 优化器

# 7. 训练+验证循环(核心:写入损失/准确率到TensorBoard)
global_step = 0  # 全局步数(用于TensorBoard的x轴)

for epoch in range(EPOCHS):
    # ========== 训练阶段 ==========
    model.train()  # 模型切换到训练模式
    train_loss_sum = 0.0  # 累计训练损失
    train_correct = 0     # 累计正确数
    train_total = 0       # 累计样本数
    
    for batch_idx, (data, target) in enumerate(train_loader):
        # 数据放到CPU
        data, target = data.to(DEVICE), target.to(DEVICE)
        
        # 前向传播
        output = model(data)
        loss = criterion(output, target)  # 计算训练损失
        
        # 反向传播+更新参数
        optimizer.zero_grad()  # 清空梯度
        loss.backward()        # 反向传播
        optimizer.step()       # 更新参数
        
        # 统计训练指标
        train_loss_sum += loss.item()
        _, predicted = torch.max(output.data, 1)  # 预测结果
        train_total += target.size(0)
        train_correct += (predicted == target).sum().item()
        
        # 🔥 关键:每一批次写入训练损失(按global_step)
        writer.add_scalar('train/loss', loss.item(), global_step=global_step)
        global_step += 1  # 步数+1
    
    # 计算本轮训练的平均损失和准确率
    train_avg_loss = train_loss_sum / len(train_loader)
    train_acc = train_correct / train_total
    
    # ========== 验证阶段 ==========
    model.eval()  # 模型切换到验证模式
    val_loss_sum = 0.0
    val_correct = 0
    val_total = 0
    
    with torch.no_grad():  # 验证阶段不计算梯度(节省资源)
        for data, target in test_loader:
            data, target = data.to(DEVICE), target.to(DEVICE)
            output = model(data)
            loss = criterion(output, target)  # 计算验证损失
            
            # 统计验证指标
            val_loss_sum += loss.item()
            _, predicted = torch.max(output.data, 1)
            val_total += target.size(0)
            val_correct += (predicted == target).sum().item()
    
    # 计算本轮验证的平均损失和准确率
    val_avg_loss = val_loss_sum / len(test_loader)
    val_acc = val_correct / val_total
    
    # 🔥 关键:每一轮写入训练/验证的平均损失和准确率(按epoch)
    writer.add_scalar('train/avg_loss', train_avg_loss, global_step=epoch)
    writer.add_scalar('train/accuracy', train_acc, global_step=epoch)
    writer.add_scalar('val/avg_loss', val_avg_loss, global_step=epoch)
    writer.add_scalar('val/accuracy', val_acc, global_step=epoch)
    
    # 打印本轮结果(方便终端查看)
    print(f"Epoch [{epoch+1}/{EPOCHS}]")
    print(f"Train Loss: {train_avg_loss:.4f}, Train Acc: {train_acc:.4f}")
    print(f"Val Loss: {val_avg_loss:.4f}, Val Acc: {val_acc:.4f}\n")

# 8. 收尾:关闭SummaryWriter(确保数据全部写入)
writer.close()

# 提示后续操作
print(f"✅ 训练完成!所有指标已写入日志文件夹:{log_dir}")
print("\n📌 启动TensorBoard(复制到终端执行):")
print(f"tensorboard --logdir=logs/train_metrics --port=6006")

运行代码 + 查看可视化曲线(3 步搞定)

步骤 1:运行代码

将代码保存为train_visualize.py,终端执行:

  • 第一次运行会自动下载 MNIST 数据集(约 10MB,速度快);
  • 训练过程中终端会打印每一轮的损失 / 准确率;
  • 运行完成后生成logs/train_metrics/时间戳日志文件夹。

步骤 2:启动 TensorBoard

终端执行以下命令(无需指定到具体时间戳子文件夹):

步骤 3:查看损失 / 准确率曲线(核心!)

打开浏览器输入http://localhost:6006,操作如下:

核心代码通俗解释(零基础友好)

代码行 通俗解释
writer = SummaryWriter(log_dir=log_dir) 初始化日志写入器,相当于 "打开一个专门记录训练指标的本子"
writer.add_scalar('train/loss', loss.item(), global_step) 每批数据训练完,往本子里记:"第 global_step 步,训练损失是 loss.item ()",train/loss是标签(分类用)
writer.add_scalar('val/accuracy', val_acc, epoch) 每轮验证完,记:"第 epoch 轮,验证准确率是 val_acc"
global_step += 1 每训练一批数据,步数 + 1(保证 x 轴连续,曲线不重叠)
writer.close() 训练结束,"合上本子",确保所有数据写入文件(避免丢失)

新手常见问题解决

问题 1:曲线波动太大(train/loss)

  • 原因:train/loss是单批次的损失,本身就会波动;
  • 解决:重点看train/avg_loss(每轮平均损失),这条曲线更平滑,能反映整体趋势。

问题 2:验证准确率不上升甚至下降

  • 原因:模型过拟合 / 学习率不合适 / 训练轮数不够;
  • 解决:通过 TensorBoard 曲线能快速发现这个问题,比如 "训练准确率 95%,验证准确率 70%" 就是过拟合,需要调整模型。

问题 3:TensorBoard 中看不到曲线

  • 原因 1:global_step传错(比如重复传 0);
  • 原因 2:日志路径指定错误(启动 TensorBoard 时--logdir要指向train_metrics,不是具体时间戳);
  • 解决:检查add_scalarglobal_step参数,重新启动 TensorBoard 并确认路径。

总结

  1. 可视化损失 / 准确率的核心流程:初始化 SummaryWriter → 训练 / 验证中调用 add_scalar 写入指标(标签 + 数值 + 步数 / 轮数) → 关闭 Writer → 启动 TensorBoard 查看曲线
  2. 标签建议用分类/指标名格式(如train/lossval/accuracy),方便在 TensorBoard 中分类查看;
  3. global_step(步数)用于批次级指标,epoch(轮数)用于轮级指标,确保 x 轴和训练进度对应。

这是机器学习中最常用的 TensorBoard 用法,掌握后能快速判断模型训练是否正常(比如损失是否下降、是否过拟合),是调试模型的必备技能。

除了Tensorboard,还有哪些类似的可视化工具?

TensorBoard 替代工具全览

除 TensorBoard 外,机器学习领域有多种可视化工具,它们在功能、易用性和适用场景上各有侧重。下面按功能类型分类介绍主流替代工具:

一、实验跟踪与可视化全能型工具

1. Weights & Biases (W&B)

核心优势

  • 云端协作:团队成员实时共享实验结果,一键生成可分享链接
  • 强大可视化:自动生成损失 / 准确率曲线,支持直方图、3D 图等高级可视化
  • 超参数优化:内置搜索工具,支持随机 / 网格 / 贝叶斯搜索 Weights & Biases
  • 模型版本控制:自动保存模型权重,方便对比不同版本

价格:个人版免费,团队版起价 $9 / 月 / 人 Weights & Biases

适用场景:深度学习研究、需要团队协作的项目、快速迭代的实验环境

极简使用示例

python 复制代码
import wandb
wandb.init(project="my-project")  # 初始化
wandb.log({"loss": 0.5, "accuracy": 0.8})  # 记录指标

2. MLflow Tracking

核心优势

  • 全生命周期管理:从实验到模型部署的完整跟踪
  • 开源自托管:可部署在私有环境,数据完全可控
  • 多框架支持:无缝集成 TensorFlow、PyTorch、scikit-learn 等 MLflow
  • 与 Databricks 深度集成:企业级大数据处理能力

价格:完全开源免费

适用场景:企业级 MLOps、需要模型部署的生产环境、大数据与 AI 结合项目

极简使用示例

python 复制代码
import mlflow
mlflow.log_metric("loss", 0.5)  # 记录标量指标
mlflow.log_param("learning_rate", 0.001)  # 记录参数

3. Comet.ml

核心优势

  • 可视化 + 数据洞察:一键生成专业图表和报告
  • 内置 A/B 测试:自动对比不同实验效果
  • LLM 支持:专门优化的提示词工程和评估功能
  • CI/CD 集成:自动化测试与部署流程

价格:个人版免费 (5 个团队成员限制),专业版 $179 / 月起

适用场景:快速迭代的 AI 产品开发、需要精细化实验对比的团队

极简使用示例

python 复制代码
from comet_ml import Experiment
experiment = Experiment(project_name="my-project")
experiment.log_metric("loss", 0.5)

4. Neptune.ai

核心优势

  • 轻量级与可扩展性:专为大规模模型训练设计,无延迟监控
  • 自定义仪表盘:支持 Bokeh、Altair、Plotly 等多种可视化库
  • 模型内部监控:可深入查看每一层的损失、梯度和激活值
  • 比较功能:提供参数差异表、并行坐标图等对比视图

价格:个人版免费,团队版按需定价

适用场景:大规模深度学习模型训练、需要深入分析模型内部状态的研究

极简使用示例

python 复制代码
import neptune
run = neptune.init(project="my-project")
run["metrics/loss"] = 0.5

二、轻量级 / 本地可视化工具

1. SwanLab (国产)

核心优势

  • 离线 + 云端双模式:弥补 TensorBoard 只能离线的不足
  • 现代化 UI:界面简洁直观,交互体验优秀
  • 多框架支持:集成 30 + 深度学习框架,包括 PyTorch、TensorFlow 等
  • 多媒体支持:可视化图像、音频、文本等多种数据类型

价格:开源免费,企业版提供高级功能

适用场景:个人研究、教育环境、需要快速搭建可视化的小型团队

极简使用示例

python 复制代码
import swanlab
swanlab.log({"loss": 0.5, "accuracy": 0.8})

2. Visdom

核心优势

  • PyTorch 官方推荐:专为 PyTorch 设计的 "轻量级实时 TensorBoard"
  • 快速搭建:几行代码实现数据可视化
  • 支持多种图表:折线图、散点图、热力图等

价格:完全开源免费

适用场景:PyTorch 用户、需要快速查看训练指标的研究人员

极简使用示例

python 复制代码
from visdom import Visdom
vis = Visdom()
vis.line(Y=[0.5], X=[1], win="loss", opts=dict(title="Loss Curve"))

三、模型结构可视化专用工具

1. Netron

核心优势

  • 多框架支持:兼容 PyTorch、TensorFlow、Keras 等模型格式
  • 直观界面:清晰展示模型层次结构和参数流动
  • 轻量级:无需安装额外依赖,直接通过网页查看模型

价格:完全开源免费,提供 Web 版和桌面版

适用场景:模型架构理解、跨框架模型交流、论文写作中的模型展示

2. TensorBoardX (现已合并到 TensorBoard)

核心优势

  • PyTorch 友好:为 PyTorch 提供与 TensorBoard 相同的可视化体验
  • 支持多种数据:标量、图像、直方图、模型图等

价格:开源免费

适用场景:PyTorch 用户想使用 TensorBoard 风格可视化的情况

四、其他实用工具

1. ClearML

核心优势

  • 资源监控:自动跟踪 CPU/GPU 使用情况,优化资源分配
  • 任务调度:支持分布式训练任务管理
  • 可自托管:支持本地部署或云服务

价格:社区版免费,企业版付费

2. ML Visuals

核心优势

  • 免费专业图表:专为机器学习设计的高质量可视化模板
  • 科学交流优化:生成适合论文发表的图表

价格:完全免费

3. DVC Live

核心优势

  • 与 DVC 集成:数据版本控制与可视化无缝结合
  • 轻量级:无需额外服务,直接在终端生成可视化

价格:开源免费

五、功能对比速查表

工具 云端支持 团队协作 自动可视化 模型结构 轻量级 价格
TensorBoard ✅(基础) 免费 (开源)
W&B ✅(强) ✅(丰富) 个人免费
MLflow ⚠️(需自部署) ✅(基础) ⚠️ 免费 (开源)
Comet.ml ✅(中) ✅(丰富) 个人免费 (有限)
Neptune.ai ✅(中) ✅(可定制) ⚠️ 个人免费
SwanLab ✅(中) ✅(现代) 免费 (开源)
Visdom ✅(基础) 免费 (开源)
Netron ✅(专业) 免费 (开源)

六、如何选择适合你的工具?

1. 如果你是个人研究者 / 学生

  • 简单本地使用: 优先选 TensorBoard 或 Visdom (免费、轻量、足够基础可视化)
  • 需要云支持: 选择 W&B 或 SwanLab (个人版免费,功能强大)

2. 如果你在团队中做深度学习研究

  • 需要强协作: W&B 是首选 (实时共享、评论、对比实验)
  • 大规模模型: Neptune.ai (监控深层模型内部状态,无延迟)

3. 如果你在企业环境做 AI 开发

  • 完整 MLOps 流程: MLflow (从实验到部署全生命周期管理)
  • 合规与数据安全: 可自托管的 MLflow 或 ClearML (数据不出内网)

4. 如果你特别关注模型结构可视化

  • Netron (支持几乎所有框架,开箱即用)
  • TensorBoard (原生支持 TensorFlow/Keras 模型结构)

总结

除 TensorBoard 外,W&B、MLflow、Comet.mlNeptune.ai 是功能最全面的可视化工具,各有专长;SwanLab 和 Visdom 适合轻量级使用;Netron 专注模型结构可视化。建议根据项目规模、团队需求和技术栈选择,许多工具支持同时集成 (如 W&B+TensorBoard),取长补短。

下一步建议: 从 W&B 或 SwanLab 开始尝试 (免费且功能强大),同时保留 TensorBoard 用于模型结构可视化,体验不同工具的优势。

Weights & Biases;MLflow;SwanLab各自的核心优势分别是什么?

你想清晰区分 Weights & Biases(W&B)、MLflow、SwanLab 这三款工具的核心优势,作为零基础的机器学习学习者,我会用通俗易懂的语言(搭配生活化比喻),聚焦每款工具最核心、最实用的价值,帮你快速判断哪款适合自己的使用场景。

一、Weights & Biases(W&B):云端优先的「实验协作管家」

W&B 的核心定位是面向研究者 / 小团队的云端实验可视化与协作工具,核心优势围绕 "云端、协作、易用" 展开:

核心优势(新手最关心的 3 点)

二、MLflow:全流程覆盖的「模型生命周期管家」

MLflow 的核心定位是面向企业 / 专业团队的机器学习全流程管理工具,核心优势围绕 "全流程、开源、自托管" 展开:

核心优势(新手最关心的 3 点)

三、SwanLab:国产轻量的「本地化实验看板」

SwanLab 是国产开源工具,核心定位是兼顾本地易用性与云端协作的轻量级可视化工具,核心优势围绕 "国产、轻量、友好" 展开:

核心优势(新手最关心的 3 点)

核心优势对比表(新手速记)

工具 核心优势关键词 最适合的场景 新手友好度
W&B 云端、协作、实验对比、易用 个人学习 / 小团队研究、快速迭代实验 ⭐⭐⭐⭐⭐
MLflow 全流程、开源自托管、通用性强 企业项目、模型部署、传统 + 深度学习混合 ⭐⭐⭐ (需学基础概念)
SwanLab 国产、轻量、离线 + 云端、中文友好 国内学习者、本地化可视化、简单小项目 ⭐⭐⭐⭐⭐

总结

  1. 如果你是纯新手,只想快速可视化训练曲线、对比实验:优先选 W&B(个人免费)或 SwanLab(国产更适配),零门槛上手;
  2. 如果你想接触工业界全流程,或需要部署模型:选 MLflow(开源免费,学完能对接实际工作);
  3. 如果你在意数据隐私,不想用国外云端:选 SwanLab(本地运行)或 MLflow(自托管)。

这三款工具都支持和 TensorBoard 互补使用(比如用 W&B 看指标、用 TensorBoard 看模型结构),新手可以先从 W&B/SwanLab 入手,后续再拓展 MLflow。

作业:对resnet18 在 cifar10上采用微调策略下,用tensorboard 监控训练过程。

完整代码实现(ResNet18 微调 + TensorBoard 监控)

在 VS Code 中新建train_resnet18_cifar10.py文件,复制以下代码(每一行都有详细注释,适配 Mac OS):

python 复制代码
# ====================== 1. 导入核心库 ======================
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms, models
from torch.utils.tensorboard import SummaryWriter
from datetime import datetime
import os

# ====================== 2. 基础配置(适配Mac OS) ======================
# 设备配置:Mac M系列芯片用mps,Intel用cpu
DEVICE = torch.device("mps" if torch.backends.mps.is_available() else "cpu")
print(f"使用设备:{DEVICE}")  # 打印当前设备,确认是否正确

# 训练参数(新手可直接用,不用改)
BATCH_SIZE = 64          # 批次大小(Mac内存小的话可改32)
EPOCHS = 10              # 训练轮数(微调不用太多)
LEARNING_RATE = 0.001    # 微调学习率要小(避免覆盖预训练权重)
LOG_DIR = f"logs/resnet18_cifar10/{datetime.now().strftime('%Y%m%d-%H%M%S')}"  # TensorBoard日志路径

# ====================== 3. 数据预处理(适配ResNet18输入) ======================
# ResNet18预训练模型要求输入224×224,CIFAR10是32×32,所以需要resize
transform_train = transforms.Compose([
    transforms.RandomResizedCrop(224),  # 随机裁剪+缩放至224×224
    transforms.RandomHorizontalFlip(),  # 随机水平翻转(数据增强)
    transforms.ToTensor(),              # 转Tensor
    transforms.Normalize(mean=[0.485, 0.456, 0.406],  # ImageNet预训练的均值
                         std=[0.229, 0.224, 0.225])   # ImageNet预训练的标准差
])

transform_test = transforms.Compose([
    transforms.Resize(256),             # 缩放至256×256
    transforms.CenterCrop(224),         # 中心裁剪至224×224
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225])
])

# 加载CIFAR10数据集(Mac下自动下载到当前文件夹的data目录)
train_dataset = datasets.CIFAR10(
    root='./data', train=True, download=True, transform=transform_train
)
test_dataset = datasets.CIFAR10(
    root='./data', train=False, download=True, transform=transform_test
)

# 数据加载器
train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False)

# CIFAR10类别名称(方便后续理解)
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

# ====================== 4. 微调ResNet18(核心步骤) ======================
# 步骤1:加载预训练的ResNet18模型
model = models.resnet18(pretrained=True)  # 加载ImageNet预训练权重

# 步骤2:冻结特征提取层(微调核心:只训练分类头)
# ResNet18的features层是特征提取部分,fc是分类头
for param in model.parameters():
    param.requires_grad = False  # 冻结所有参数

# 步骤3:修改分类头(适配CIFAR10的10类,原ResNet18是1000类)
num_ftrs = model.fc.in_features  # 获取分类头输入维度
model.fc = nn.Linear(num_ftrs, 10)  # 替换为10类分类头

# 步骤4:将模型移到Mac的设备(MPS/CPU)
model = model.to(DEVICE)

# ====================== 5. 配置训练组件 ======================
criterion = nn.CrossEntropyLoss()  # 分类损失函数
# 优化器:只优化分类头的参数(因为特征层已冻结)
optimizer = optim.Adam(model.fc.parameters(), lr=LEARNING_RATE)

# 初始化TensorBoard的SummaryWriter(Mac路径无乱码)
writer = SummaryWriter(log_dir=LOG_DIR)

# ====================== 6. 训练+验证循环(写入TensorBoard) ======================
global_step = 0  # 全局步数,用于TensorBoard的x轴

for epoch in range(EPOCHS):
    # ---------- 训练阶段 ----------
    model.train()  # 切换到训练模式
    train_loss = 0.0
    train_correct = 0
    train_total = 0

    for batch_idx, (inputs, labels) in enumerate(train_loader):
        # 数据移到设备
        inputs, labels = inputs.to(DEVICE), labels.to(DEVICE)
        
        # 前向传播
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        
        # 反向传播+优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        # 统计指标
        train_loss += loss.item()
        _, predicted = torch.max(outputs.data, 1)
        train_total += labels.size(0)
        train_correct += (predicted == labels).sum().item()
        
        # 写入TensorBoard:每批次的训练损失
        writer.add_scalar('train/batch_loss', loss.item(), global_step=global_step)
        global_step += 1

    # 计算本轮训练的平均损失和准确率
    train_avg_loss = train_loss / len(train_loader)
    train_acc = 100 * train_correct / train_total

    # ---------- 验证阶段 ----------
    model.eval()  # 切换到验证模式
    val_loss = 0.0
    val_correct = 0
    val_total = 0

    with torch.no_grad():  # 验证阶段不计算梯度,节省Mac资源
        for inputs, labels in test_loader:
            inputs, labels = inputs.to(DEVICE), labels.to(DEVICE)
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            
            val_loss += loss.item()
            _, predicted = torch.max(outputs.data, 1)
            val_total += labels.size(0)
            val_correct += (predicted == labels).sum().item()

    # 计算本轮验证的平均损失和准确率
    val_avg_loss = val_loss / len(test_loader)
    val_acc = 100 * val_correct / val_total

    # ---------- 写入TensorBoard:每轮的平均指标 ----------
    writer.add_scalar('train/avg_loss', train_avg_loss, global_step=epoch)
    writer.add_scalar('train/accuracy', train_acc, global_step=epoch)
    writer.add_scalar('val/avg_loss', val_avg_loss, global_step=epoch)
    writer.add_scalar('val/accuracy', val_acc, global_step=epoch)

    # 打印本轮结果(Mac终端可见)
    print(f'Epoch [{epoch+1}/{EPOCHS}]')
    print(f'Train Loss: {train_avg_loss:.4f}, Train Acc: {train_acc:.2f}%')
    print(f'Val Loss: {val_avg_loss:.4f}, Val Acc: {val_acc:.2f}%\n')

# ====================== 7. 收尾工作 ======================
# 关闭SummaryWriter,确保所有数据写入文件(Mac下避免数据丢失)
writer.close()

# 保存微调后的模型(Mac路径)
model_save_path = f'./resnet18_cifar10_finetuned.pth'
torch.save(model.state_dict(), model_save_path)
print(f'微调后的模型已保存到:{model_save_path}')
print(f'TensorBoard日志路径:{LOG_DIR}')
print('训练完成!请在终端执行以下命令启动TensorBoard:')
print(f'tensorboard --logdir={LOG_DIR} --port=6006')

运行代码 + 查看 TensorBoard(Mac OS + VS Code 操作)

步骤 1:运行训练代码

步骤 2:启动 TensorBoard(Mac OS 无端口冲突)

步骤 3:查看可视化结果

关键知识点解释(Mac 适配 + 微调核心)

1. Mac 设备适配

  • 代码中DEVICE = torch.device("mps" if torch.backends.mps.is_available() else "cpu"):自动识别 Mac M1/M2/M3 芯片的 MPS 加速(比 CPU 快 3-5 倍),Intel Mac 自动用 CPU;
  • Mac 的文件路径无需转义,代码中LOG_DIR和模型保存路径直接用相对路径即可。

2. ResNet18 微调核心

  • 冻结特征层for param in model.parameters(): param.requires_grad = False,只让分类头的参数参与训练,避免预训练的特征提取权重被破坏;
  • 修改分类头:ResNet18 原分类头是 1000 类(ImageNet),替换为 10 类(CIFAR10),这是微调的核心适配步骤;
  • 小学习率:微调时学习率用 0.001(比从头训练小 10 倍),避免大学习率覆盖预训练权重。

3. TensorBoard 监控重点

  • val/accuracy是否持续上升:若上升说明微调有效,若停滞说明训练轮数不够或学习率不合适;
  • 对比train/accuracyval/accuracy:若差距过大(比如训练 90%,验证 70%),说明过拟合,可增加数据增强或减小学习率。

总结

  1. Mac OS 适配关键:用 MPS 加速(M 系列芯片)、相对路径、虚拟环境避免依赖冲突;
  2. ResNet18 微调核心:冻结特征层 + 替换分类头 + 小学习率,利用预训练权重适配小数据集;
  3. TensorBoard 监控核心:写入批次 / 轮级损失 / 准确率,通过曲线判断微调效果(验证准确率上升 = 微调成功)。

如果训练中遇到 "内存不足"(Mac 内存 8G 以下),可将BATCH_SIZE改为 32;若验证准确率低,可增加训练轮数到 15,或解冻 ResNet18 的最后 1-2 层特征层(代码中取消部分层的冻结)。

浙大疏锦行

相关推荐
木卫二号Coding2 小时前
第七十篇-ComfyUI+V100-32G+运行SD3.5-文生图
人工智能
Salt_07282 小时前
DAY 40 早停策略和模型权重的保存
人工智能·python·算法·机器学习
码农小白猿2 小时前
IACheck优化电梯定期检验报告:自动化术语审核提升合规性与效率
大数据·运维·人工智能·ai·自动化·iacheck
点云SLAM2 小时前
Absence 英文单词学习
人工智能·英文单词学习·雅思备考·absence·缺席 / 不在场·缺乏 / 缺失
yenggd2 小时前
华为批量下发配置命令使用telnetlib模块
网络·python·华为
酌沧2 小时前
读懂深度学习中的梯度爆炸和梯度消失
人工智能·深度学习
DARLING Zero two♡2 小时前
接入 AI Ping 限免接口,让 GLM-4.7 与 MiniMax-M2.1 成为你的免费 C++ 审计专家
开发语言·c++·人工智能
不惑_2 小时前
通俗理解感知机(Perceptron)
人工智能·python
龙腾AI白云2 小时前
【图神经网络初探(2)】
人工智能