You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Plotly绘制类似TensorBoard的三维偏移堆叠直方图?

用Plotly复现TensorBoard多直方图3D堆叠效果

要实现TensorBoard中多直方图的3D堆叠可视化,核心思路是将每个2D直方图沿Z轴(或自定义轴)分配固定偏移值,把2D坐标扩展为3D坐标后,在Plotly中逐个绘制每个直方图的轮廓或填充区域。以下是具体实现方案:

核心步骤

  • 为每个直方图分配唯一的Z轴位置(例如按时间步/epoch索引递增)
  • 将2D直方图的bin边界和计数转换为3D坐标点
  • 用Plotly的Scatter3d或Mesh3d组件绘制每个直方图的结构
  • 调整视角、透明度和样式优化视觉效果

代码示例

1. 生成模拟数据

假设我们有5个不同时间步的直方图数据,每个包含bin边界和对应计数:

import numpy as np
import plotly.graph_objects as go

# 生成模拟直方图数据:5个时间步,每个有10个bins
num_histograms = 5
num_bins = 10

# 生成bin边界(每个直方图的bin范围一致,也可自定义不同范围)
bins = np.linspace(-5, 5, num_bins + 1)
bin_width = bins[1] - bins[0]

# 生成每个直方图的计数(模拟数据)
counts_list = []
for i in range(num_histograms):
    # 模拟均值随时间步偏移的正态分布计数
    mu = -2 + i * 1.0
    counts = np.histogram(np.random.normal(mu, 1, 1000), bins=bins)[0]
    counts_list.append(counts)

2. 构建3D坐标并绘制折线式直方图

将每个2D直方图转换为3D折线,沿Z轴堆叠:

fig = go.Figure()

for idx, counts in enumerate(counts_list):
    # 为当前直方图分配Z轴偏移值
    z_offset = idx
    
    # 构建每个柱子的3D坐标点(折线模式)
    x_coords = []
    y_coords = []
    z_coords = []
    
    for bin_idx in range(num_bins):
        bin_left = bins[bin_idx]
        bin_right = bins[bin_idx + 1]
        count = counts[bin_idx]
        
        # 绘制柱子的四条边:左竖线、顶横线、右竖线、底横线
        x_coords.extend([bin_left, bin_left, bin_right, bin_right, bin_left])
        y_coords.extend([0, count, count, 0, 0])
        z_coords.extend([z_offset]*5)
    
    # 添加当前直方图的3D折线trace
    fig.add_trace(go.Scatter3d(
        x=x_coords, y=y_coords, z=z_coords,
        mode='lines',
        line=dict(color=f'hsl({idx*360/num_histograms}, 70%, 50%)', width=2),
        name=f'Histogram {idx+1}'
    ))

# 布局设置
fig.update_layout(
    scene=dict(
        xaxis_title='Bin Value',
        yaxis_title='Count',
        zaxis_title='Time Step',
        camera=dict(
            eye=dict(x=1.5, y=1.5, z=0.8)  # 调整相机视角适配堆叠效果
        )
    ),
    showlegend=True
)

fig.show()

3. 进阶:填充式直方图(更接近TensorBoard效果)

如果需要填充柱子内部区域,可使用Mesh3d组件构建每个柱子的面:

fig = go.Figure()

for idx, counts in enumerate(counts_list):
    z_offset = idx
    x_mesh = []
    y_mesh = []
    z_mesh = []
    
    for bin_idx in range(num_bins):
        bin_left = bins[bin_idx]
        bin_right = bins[bin_idx + 1]
        count = counts[bin_idx]
        
        # 构建柱子的四个顶点坐标
        vertices = [
            [bin_left, 0, z_offset],
            [bin_left, count, z_offset],
            [bin_right, count, z_offset],
            [bin_right, 0, z_offset]
        ]
        
        # 生成Mesh的面(两个三角形组成矩形)
        x_mesh.extend([v[0] for v in vertices] + [None])
        y_mesh.extend([v[1] for v in vertices] + [None])
        z_mesh.extend([v[2] for v in vertices] + [None])
    
    fig.add_trace(go.Mesh3d(
        x=x_mesh, y=y_mesh, z=z_mesh,
        color=f'hsl({idx*360/num_histograms}, 70%, 50%)',
        opacity=0.6,  # 设置透明度避免遮挡
        name=f'Histogram {idx+1}'
    ))

fig.update_layout(
    scene=dict(
        xaxis_title='Bin Value',
        yaxis_title='Count',
        zaxis_title='Time Step',
        camera=dict(eye=dict(x=1.8, y=1.8, z=0.6))
    )
)

fig.show()

关键说明

  • Z轴偏移:通过给每个直方图分配固定的z_offset实现三维堆叠,可根据需求调整偏移步长
  • 样式优化:通过opacity设置透明度,camera参数调整视角,hsl颜色模式生成渐变色彩,提升可读性
  • 数据适配:如果直方图bin范围不一致,只需为每个直方图单独生成bins即可,代码逻辑通用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 09:57:13