SwanLab最全使用教程:看这篇就够了

前言

机器学习通常涉及在训练期间可视化和度量模型的性能。 有许多工具可用于此任务。 在本文中,我们将重点介绍 SwanLab 开源工具,它可以服务于各种深度学习训练任务(计算机视觉、自然语言处理、音频处理等等),也适配了PyTorch、Transformers、Keras这样的框架。

一、什么是SwanLab?

SwanLabhttps://swanlab.cn)是一个用于AI模型训练过程可视化的工具。SwanLab的主要功能包括:

  1. 跟踪模型指标,如损失和准确性等
  2. 同时支持云端和离线使用,支持远程查看训练过程,比如可以在手机上看远程服务器上跑的训练
  3. 记录训练超参数,如batch_size和learning_rate等
  4. 自动记录训练过程中的日志、硬件环境、Python库以及GPU(支持英伟达显卡)、NPU(支持华为昇腾卡)、内存的硬件信息
  5. 支持团队多人协作,很适合打Kaggle等比赛的队伍

SwanLab库来自一个中国团队(情感机器),最早的出发点是其开发团队的内部训练需求,后来逐渐开源并且发展成面向公众的产品。SwanLab库在2024年向公众发布。SwanLab刚出现时只有离线版本(对标Tensorboard),后来经过迭代和努力已经有了云端版和各项功能,并且集成了接近30+个深度学习框架,包括PyTorch、HuggingFace Transformers、Keras、XGBoost等等,其中还包括同样是中国团队开发的LLaMA Factory、Modelscope Swift、PaddleYOLO等框架,具有了很全面的功能。

二、如何安装SwanLab?

要安装 SwanLab 可以使用如下命令:

pip install swanlab

要查看是否安装成功,可以打开命令行输入:

swanlab -v

如果打印出了版本号,就说明已经安装成功。

三、登录SwanLab账号(详细)

SwanLab的云端版体验是比较好的(非常推荐),能够支持你在随时随地访问训练过程。

要使用云端版之前需要先注册一下账号:

  1. 在电脑或手机浏览器访问SwanLab官网https://swanlab.cn

  1. 点击右上角的黑色按钮「注册/登录」:

  1. 填写手机号后,点击「发送短信验证码」按钮

  1. 填写你的信息
  • 用户名称:你的个人昵称,中英文均可
  • 用户ID:你的英文名,可由数字、字母、下划线、中横线组成
  • 邮箱:你的邮箱
  • 机构/院校:你所在的企业、机构或学校
  • 您从哪了解到SwanLab? :(选填项)了解到SwanLab的渠道,比如朋友介绍

  1. 复制API Key

完成填写后点击「完成」按钮,会进入到下面的页面。然后点击左边的「设置」:

API Key 这个地方,点击复制按钮:

  1. 登录(方式一)

打开命令行,输入下面的命令:

swanlab login

在出现的提示里把API Key粘贴进去(粘贴完不显示密码是正常的,这是命令行的特性),然后按回车,完成登录。


7. 登录(方式二)

创建一个Python脚本,输入下面的代码:

import swanlab

swanlab.login(api_key="把API Key粘贴到这里")

把API Key粘贴到对应的位置,然后运行一下这个脚本,完成登录。

四、快速开始:Hello World代码

SwanLab最核心的功能是深度学习训练过程可视化。要搞清楚怎么用,其实只需要掌握 initlog 这两大法宝的用法。

  • init:负责创建一个实验
  • log:负责将学习率、损失值等指标上传到实验中。log()里传入的是一个字典。

举个简单例子:

import swanlab

# 创建1个实验
run = swanlab.init()

for i in range(10):
  # 将指标loss,上传到这个实验中
  run.log({"loss": i})

这里做了3件事:

  1. 引入swanlab​库
  2. 使用swanlab.init()​创建了1个实验
  3. 将指标loss,循环上传到这个实验中

让我们运行看看效果!点击这个链接:

可以看到,这里创建了1个叫swan-1​的实验,实验中有1个loss​折线图,里面记录了这次循环中记录的值。

让我们升级一下代码:

import swanlab
import random

# 创建SwanLab实验
run = swanlab.init(
  # 设置将记录此次运行的项目信息
  project="my-ml-project",
  experiment_name="hello_world",
  # 跟踪超参数和运行元数据
  config={
    "learning_rate": 0.02,
    "architecture": "CNN",
    "dataset": "CIFAR-100",
    "epochs": 10
  }
)

# 模拟训练
epochs = 10
offset = random.random() / 5
for epoch in range(2, epochs):
  acc = 1 - 2 ** -epoch - random.random() / epoch - offset
  loss = 2 ** -epoch + random.random() / epoch + offset

  # 向swanlab上传训练指标
  run.log({"acc": acc, "loss": loss})

这段代码引入了几个新概念:

  • project参数:SwanLab用项目作为区分单位。实验可以理解为「文件」,项目就是「文件夹」。project参数用于指定这次的实验创建在哪个项目下。
  • experiment_name参数:这个参数用于指定本次实验的名称。实验名称也可以在网页上修改。
  • config参数:这个参数的作用是记录「超参数」,传入是1个字典。

项目、实验、图表、超参数等的关系如下:

ok,这里我们运行一下上面的代码,会得到下面的效果!

至此,我们就大致盘清楚了swanlab的基本用法,总体上来说还是非常简易好上手的。

五、SwanLab仪表板都有什么东西

SwanLab 仪表板由用于可视化数据的不同组件组成。我们将研究几个常用的组件。

上面的图只是部分可视化功能,全部可视化功能还有很多很多,如下:

1. 可视化图表

折线图

机器学习过程需要跟踪与模型性能相关的不同指标。这对于快速发现问题并确定模型是否过度拟合等非常重要。

使用 SwanLab 的 折线图看板,可以可视化这些指标并更轻松地调试模型:

折线图看板是最常用的看板,主要用于将神经网络训练过程中的acc(训练集准确率)val_acc(验证集准确率),loss(损失值),weight(权重)等等变化情况绘制成折线图。

图像图

在处理图像数据时,如果希望查看数据查找问题,或者查看样本以确保数据质量,则可以使用 SwanLab 的 Image API。

文本图

在进行NLP训练任务时,如果希望查看数据查找问题,或者查看模型的输出内容,则可以使用 SwanLab 的 Text API。


2. 日志记录

训练过程中,很多有用的信息打印在日志中。SwanLab会在实验的「日志」选项卡中展示自动记录下的完整日志。

3. 硬件监控

训练时的GPU显存变化等指标,都会被自动记录在「系统」选项卡下面,能帮你找到一些诡异的爆显存原因,分析训练效率的瓶颈在哪里。硬件监控这一块支持的英伟达和华为昇腾两种训练卡。

4. 实验对比

实验表格会把每个实验的超参数、最终指标展示在一个统一的表格中,方便对比不同参数对于实验的影响。

图表对比视图能帮直观的分析不同实验的指标差异,应该是机器学习训练时最最常用的功能。

六、将 SwanLab 与 PyTorch结合使用

PyTorch 是另一个深受研究人员欢迎的深度学习框架。 使用PyTorch来训练深度学习模型时,用SwanLab来监控非常方便。

下面展示一个使用PyTorch框架进行MNIST手写体识别训练的案例:

import os
import torch
from torch import nn, optim, utils
from torchvision.datasets import MNIST
from torchvision.transforms import ToTensor
import swanlab
from torchvision.models import resnet18

# 捕获并可视化前20张图像
def log_images(loader, num_images=16):
    images_logged = 0
    logged_images = []
    for images, labels in loader:
        # images: batch of images, labels: batch of labels
        for i in range(images.shape[0]):
            if images_logged < num_images:
                # 使用swanlab.Image将图像转换为可视化格式
                logged_images.append(swanlab.Image(images[i], caption=f"Label: {labels[i]}"))
                images_logged += 1
            else:
                break
        if images_logged >= num_images:
            break
    swanlab.log({"MNIST-Preview": logged_images})
  

def train(model, device, train_dataloader, optimizer, criterion, epoch, num_epochs):
    model.train()
    # 1. 循环调用train_dataloader,每次取出1个batch_size的图像和标签
    for iter, (inputs, labels) in enumerate(train_dataloader):
        inputs = inputs.repeat(1, 3, 1, 1)  # 将单通道图像转换为3通道
        inputs, labels = inputs.to(device), labels.to(device)
        optimizer.zero_grad()
        # 2. 传入到resnet18模型中得到预测结果
        outputs = model(inputs)
        # 3. 将结果和标签传入损失函数中计算交叉熵损失
        loss = criterion(outputs, labels)
        # 4. 根据损失计算反向传播
        loss.backward()
        # 5. 优化器执行模型参数更新
        optimizer.step()
        print('Epoch [{}/{}], Iteration [{}/{}], Loss: {:.4f}'.format(epoch, num_epochs, iter + 1, len(train_dataloader),
                                                                      loss.item()))
        # 6. 每20次迭代,用SwanLab记录一下loss的变化
        if iter % 20 == 0:
            swanlab.log({"train/loss": loss.item()})

def test(model, device, val_dataloader, epoch):
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        # 1. 循环调用val_dataloader,每次取出1个batch_size的图像和标签
        for inputs, labels in val_dataloader:
            inputs = inputs.repeat(1, 3, 1, 1)  # 将单通道图像转换为3通道
            inputs, labels = inputs.to(device), labels.to(device)
            # 2. 传入到resnet18模型中得到预测结果
            outputs = model(inputs)
            # 3. 获得预测的数字
            _, predicted = torch.max(outputs, 1)
            total += labels.size(0)
            # 4. 计算与标签一致的预测结果的数量
            correct += (predicted == labels).sum().item()
  
        # 5. 得到最终的测试准确率
        accuracy = correct / total
        # 6. 用SwanLab记录一下准确率的变化
        swanlab.log({"val/accuracy": accuracy}, step=epoch)
  

if __name__ == "__main__":

    #检测是否支持mps
    try:
        use_mps = torch.backends.mps.is_available()
    except AttributeError:
        use_mps = False

    #检测是否支持cuda
    if torch.cuda.is_available():
        device = "cuda"
    elif use_mps:
        device = "mps"
    else:
        device = "cpu"

    # 初始化swanlab
    run = swanlab.init(
        project="MNIST-example",
        experiment_name="resnet18",
        config={
            "model": "ResNet18",
            "optim": "Adam",
            "lr": 1e-4,
            "batch_size": 256,
            "num_epochs": 10,
            "device": device,
        },
    )

    # 设置MNIST训练集和验证集
    dataset = MNIST(os.getcwd(), train=True, download=True, transform=ToTensor())
    train_dataset, val_dataset = utils.data.random_split(dataset, [55000, 5000])

    train_dataloader = utils.data.DataLoader(train_dataset, batch_size=run.config.batch_size, shuffle=True)
    val_dataloader = utils.data.DataLoader(val_dataset, batch_size=8, shuffle=False)
  
    # (可选)看一下数据集的前16张图像
    log_images(train_dataloader, 16)

    # 初始化模型
    model = resnet18(pretrained=True)
    model.fc = nn.Linear(512, 10)  # 修改最后一层以适应10个类别
    model.to(torch.device(device))

    # 打印模型
    print(model)

    # 定义损失函数和优化器
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=run.config.lr)

    # 开始训练和测试循环
    for epoch in range(1, run.config.num_epochs+1):
        swanlab.log({"train/epoch": epoch}, step=epoch)
        train(model, device, train_dataloader, optimizer, criterion, epoch, run.config.num_epochs)
        if epoch % 2 == 0: 
            test(model, device, val_dataloader, epoch)

    # 保存模型
    # 如果不存在checkpoint文件夹,则自动创建一个
    if not os.path.exists("checkpoint"):
        os.makedirs("checkpoint")
    torch.save(model.state_dict(), 'checkpoint/latest_checkpoint.pth')

运行此程序后,转到 SwanLab 并查看训练过程:

参考链接

  1. SwanLab官方文档:https://docs.swanlab.cn/
posted @ 2025-01-07 11:40  ScalingLaw  阅读(1134)  评论(0)    收藏  举报