欢迎光临
我们一直在努力

DAY51 TensorBoard 使用介绍

目录

1. TensorBoard 的发展历史与原理

2. TensorBoard 的常见操作

3. CIFAR-10 实战总结:MLP vs CNN

MLP (多层感知机) 实战

CNN (卷积神经网络) 实战

附例:



1. TensorBoard 的发展历史与原理

  • 发展历史:

    • 诞生:2015年随 TensorFlow 发布,初衷是为深度学习提供可视化监控“屏幕”。

    • 演进:2016-2018年新增图像/音频、直方图及多运行对比功能;2019年后兼容 PyTorch,成为通用的可视化工具。

  • 核心原理:

    • 写日志(存):在训练过程中,将损失值、准确率、模型结构等数据写入特定的 .tfevents 日志文件。

    • 网页展示(看):启动本地网页服务(通常为 http://localhost:6006),自动读取并渲染日志文件,实现训练过程的实时监控。


2. TensorBoard 的常见操作

TensorBoard 通过 SummaryWriter 对象来记录不同类型的数据:

功能模块 代码接口 说明
日志管理 SummaryWriter(log_dir) 建议通过代码自动管理目录(如添加 _1, _2 后缀),方便对比不同实验。
标量 (Scalars) writer.add_scalar() 记录 Loss、Accuracy、学习率等随时间变化的单值曲线。
模型图 (Graphs) writer.add_graph() 可视化模型计算图,查看卷积层、全连接层等层次结构。
图像 (Images) writer.add_image() 展示训练样本或预测错误的图像,直观分析模型表现。
直方图 (Histograms) writer.add_histogram() 监控权重 (Weights) 和梯度 (Gradients) 的分布,诊断梯度消失/爆炸。
文本 (Text) writer.add_text() 记录预测标签、超参数说明等文本信息。

启动方式:在终端执行 tensorboard –logdir=runs。


3. CIFAR-10 实战总结:MLP vs CNN

在 CIFAR-10 数据集上的实战展示了 TensorBoard 如何辅助模型优化:

MLP (多层感知机) 实战

  • 特点:使用 nn.Flatten 将 32x32x3 的图像展平为 3072 维向量。

  • 可视化重点:通过 SCALARS 查看 Loss 下降是否平稳;使用 IMAGES 查看原始图像是否正确加载。

  • 表现:由于 MLP 丢失了图像的空间结构信息,其测试准确率通常低于 CNN。

CNN (卷积神经网络) 实战

  • 特点:引入卷积层 (Conv2d)、批量归一化 (BatchNorm2d) 和池化层 (MaxPool2d),通过特征图提取空间特征。

  • TensorBoard 增强功能:

    • 学习率动态监控:配合 ReduceLROnPlateau 调度器,可在 SCALARS 中看到学习率阶梯式下降的过程。

    • Badcase 分析:通过 add_image 记录测试集中预测错误的样本及其真实标签,帮助开发者定位模型弱点(如难以分辨猫和狗)。

    • 层权重监控:通过 HISTOGRAMS 观察不同卷积层的权重变化,确保模型在正常学习。

  • 表现:CNN 在图像任务中表现更优,通过 20 个 Epoch 的训练,准确率可稳步提升(实战中可达 80% 以上)。


附例:

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

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
from torchvision import models, transforms
from torch.utils.tensorboard import SummaryWriter
import os

# ==========================================
# 1. 环境配置与 SummaryWriter 初始化
# ==========================================
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 日志存放于 runs 文件夹下,包含两个阶段的记录
writer = SummaryWriter('runs/resnet18_stage_finetune')

# ==========================================
# 2. 数据准备:ResNet 预训练模型期望输入为 224×224
# ==========================================
transform = transforms.Compose([
transforms.Resize(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
# 使用 ImageNet 的均值和方差进行标准化
transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)

# ==========================================
# 3. 模型构建与微调设置
# ==========================================
# 加载预训练权重
model = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1)

# 修改分类头(fc层):CIFAR-10 有 10 个类别
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 10)
model = model.to(device)

# 记录模型计算图 (Graphs)
dummy_input = torch.randn(1, 3, 224, 224).to(device)
writer.add_graph(model, dummy_input)

# ==========================================
# 4. 训练核心函数 (集成详细监控)
# ==========================================
def train_model(epochs, start_step, stage_name, current_optimizer):
global_step = start_step
criterion = nn.CrossEntropyLoss()

for epoch in range(epochs):
model.train()
running_loss = 0.0

for i, (inputs, labels) in enumerate(trainloader):
inputs, labels = inputs.to(device), labels.to(device)

current_optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
current_optimizer.step()

# 每 100 步记录一次数据
if i % 100 == 99:
avg_loss = (running_loss + loss.item()) / 100
# 记录标量信息
writer.add_scalar(f'Loss/{stage_name}', avg_loss, global_step)

# 记录最后几层的梯度直方图 (Histograms)
for name, param in model.named_parameters():
if 'fc' in name or 'layer4' in name:
if param.requires_grad and param.grad is not None:
writer.add_histogram(f'Gradients_{stage_name}/{name}', param.grad, global_step)

print(f"[{stage_name}] Epoch {epoch+1}, Step {i+1} – Loss: {avg_loss:.4f}")
running_loss = 0.0
global_step += 1
return global_step

# ==========================================
# 阶段 1:冻结特征提取层,仅训练分类头
# ==========================================
print("\\n>>> 开始阶段 1:冻结底层,训练 FC 层…")
for param in model.parameters():
param.requires_grad = False
# 解冻最后的全连接层
for param in model.fc.parameters():
param.requires_grad = True

# 优化器仅包含 FC 层参数
optimizer_stage1 = optim.Adam(model.fc.parameters(), lr=0.001)
last_step = train_model(epochs=1, start_step=0, stage_name="Freeze", current_optimizer=optimizer_stage1)

# ==========================================
# 阶段 2:全量解冻,精细微调
# ==========================================
print("\\n>>> 开始阶段 2:全量解冻,全局微调…")
for param in model.parameters():
param.requires_grad = True

# 使用更小的学习率以保护预训练权重
optimizer_stage2 = optim.Adam(model.parameters(), lr=0.0001)
train_model(epochs=2, start_step=last_step, stage_name="Unfreeze", current_optimizer=optimizer_stage2)

# ==========================================
# 5. 资源清理
# ==========================================
writer.close()
print("\\n训练流程全部结束。")
print("查看监控:tensorboard –logdir=runs")

赞(0)
未经允许不得转载:171主机测评 » DAY51 TensorBoard 使用介绍
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址