You need to enable JavaScript to run this app. Seaborn单图可视化:映射点尺寸为loss对比三优化器训练耗时表现
优惠活动
大模型
产品
解决方案
定价
更多

Seaborn单图可视化:映射点尺寸为loss对比三优化器训练耗时表现

问题根因
  • 多次调用sns.relplot生成独立画布的本质原因:relplot是seaborn的figure级绘图接口,每次调用都会新建独立的Figure和Axes对象,即便绘图参数一致,也会生成独立的子图区域,无法自动合并到同一张画布
  • 原生plt.scatter无法实现loss尺寸映射的本质原因:逐次调用scatter时没有把对应分组的loss值和点尺寸参数做绑定,传入的s是固定数值,自然没法随loss值动态调整点的大小
可复现实现步骤

第一步:重构为长表格式

不管用哪个绘图接口,首先要把原来的宽格式实验记录(6组独立序列)转成tidy data结构,每一行对应单条观测,包含输入规模、所属优化器、训练耗时、最终loss四个字段,这是seaborn自动做视觉映射的前提。

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

# 实际使用时替换为你自己的实验采集数据
input_sizes = np.arange(1000, 10001, 1000)  # 步长1000,从1000到10001的输入规模
time_sgd = np.random.uniform(0.5, 2, 10)
time_rmsprop = np.random.uniform(0.4, 1.8, 10)
time_adam = np.random.uniform(0.6, 2.2, 10)
loss_sgd = np.random.uniform(0.2, 0.8, 10)
loss_rmsprop = np.random.uniform(0.1, 0.5, 10)
loss_adam = np.random.uniform(0.05, 0.3, 10)

# 转换为seaborn绘图要求的长表结构
records = []
for idx, size in enumerate(input_sizes):
    records.append({
        "input_size": size,
        "optimizer": "SGD",
        "train_time": time_sgd[idx],
        "final_loss": loss_sgd[idx]
    })
    records.append({
        "input_size": size,
        "optimizer": "RMSProp",
        "train_time": time_rmsprop[idx],
        "final_loss": loss_rmsprop[idx]
    })
    records.append({
        "input_size": size,
        "optimizer": "Adam",
        "train_time": time_adam[idx],
        "final_loss": loss_adam[idx]
    })
df = pd.DataFrame(records)

第二步:单图完成全维度映射

这里要避开一个常见误区:不需要为每个优化器单独调用一次绘图接口。seaborn的分类视觉映射是在同一坐标系内完成分组绘制的,只要把分类字段传给hue参数,就能自动在同一个坐标轴内画出不同类别的散点,不会生成独立画布。

sns.set_style("whitegrid")
g = sns.relplot(
    data=df,
    x="input_size",
    y="train_time",
    hue="optimizer",    # 按优化器类别自动分配区分色
    size="final_loss",   # 按最终loss值自动调整散点大小
    sizes=(40, 220),     # 约束散点尺寸范围,避免点过密或过大
    alpha=0.65,          # 加透明度减少重叠遮挡
    height=6,
    aspect=1.2
)
# 优化图表标注可读性
g.set_axis_labels("输入数据集样本规模", "10轮训练总耗时(秒)")
g.fig.suptitle("不同优化器训练效率与最终损失对比", y=1.03)
plt.show()

生成的单图会同时满足两个核心需求:

  1. 三个优化器的散点全部在同一坐标轴内,通过颜色区分系列,自动生成对应图例
  2. 每个散点的大小直接对应自身的最终loss值,seaborn会自动生成尺寸对照图例,不需要手动调整点大小

原生matplotlib等效实现

如果不想依赖seaborn的自动映射逻辑,用原生plt.scatter也可以实现同样效果,核心是把每个分组的loss值归一化到合理的尺寸范围,作为s参数传入:

fig, ax = plt.subplots(figsize=(8, 6))
# 统一取全量数据的loss极值做尺寸归一化基准
loss_min, loss_max = df["final_loss"].min(), df["final_loss"].max()
size_range_min, size_range_max = 40, 220

optimizer_config = {
    "SGD": "#1f77b4",
    "RMSProp": "#ff7f0e",
    "Adam": "#2ca02c"
}

for opt_name, color in optimizer_config.items():
    opt_subset = df[df["optimizer"] == opt_name]
    # 把loss值线性映射到指定的尺寸区间
    scaled_point_size = ((opt_subset["final_loss"] - loss_min) / (loss_max - loss_min)) * (size_range_max - size_range_min) + size_range_min
    ax.scatter(
        opt_subset["input_size"],
        opt_subset["train_time"],
        s=scaled_point_size,
        c=color,
        label=opt_name,
        alpha=0.65
    )

ax.set_xlabel("输入数据集样本规模")
ax.set_ylabel("10轮训练总耗时(秒)")
ax.legend(title="优化器类型")
plt.show()

实现时注意两个细节:

  • 尺寸归一化一定要用全量实验数据的loss极值做基准,不能每个优化器单独算归一化值,否则相同loss对应的点大小不一致,会破坏对比的公平性
  • 如果同一输入规模下三个优化器的训练耗时差异极小,点完全重叠,可以给每个优化器的x值加±20的微小偏移,让三个点在x方向错开位置,避免遮挡

内容的提问来源于stack exchange,提问作者Nitin1901

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.06 14:45:08