How To Customize Trees and Dendrograms in Weights & Biases
In this article, we take a look at how to customize charts of trees and graphs in Weights & Biases.
Created on December 1|Last edited on November 28
Comment
Circular Dendrogram
Input format: at minimum, each node needs an id. Most nodes except the root should have parent ids. Names/labels are optional.
This example is taken directly from the Vega documentation, and this chart renders a code/variable type tree. See the end of this report for the full Vega spec.
Display Configuration
Click on the gear icon in the top right to adjust the chart settings interactively.
- labels: show/hide node names
- radius: spacing between concentric layers
- extent: 0-360 degrees of the circle in which to render the chart
- rotate: circle orientation (pivot chart around the root)
- layout: visual spacing of child nodes
- links: how the edges are rendered (lines, curves, orthogonal)
Full dendrogram
1
Full Code
data = [[a["id"], a["name"], a["parent"], a["size"]] for a in raw_data]table = wandb.Table(columns=["node_id", "node_name", "parent", "size"], data=data)fields = {"node_name" : "node_name", "node_id" : "node_id", "parent" : "parent", "size" : "size"}dendro = wandb.plot_table(vega_spec_name="stacey/dendrogram", data_table=table, fields=fields)wandb.log({"custom_tree" : dendro})
where raw_data has the form:
raw_data = [{"id": 126,"name": "Variable","parent": 67,"size": 1124},{"id": 127,"name": "Variance","parent": 67,"size": 1876},{"id": 128,"name": "Xor","parent": 67,"size": 1101},{"id": 129,"name": "scale","parent": 1}, ...]
Tree (Regular Dendrogram)
Here the same sample data is rendered as a regular tree to show the space of possibilities (see the original in Vega).
The only change to the plotting code above requires changing the vega_spec_name.
Flat tree
1
Next Steps
Custom Chart Features
- show how to save a fixed version once someone is happy with the display settings
- include useful information on node hover, esp URLs
- adjust node color/appearance based on size/relative weight
- examples where not all nodes are named (closer to a traditional dendrogram)
- generalize to displaying smaller DAGs/PGMs/labeled nodes
- allow the user more control over the clustering algorithm
Datasets/Research to Showcase
- new directions
- evolution of concepts/terms from machine learning across time in papers ("batch norm", "reinforcement learning" algorithms)
- evolution of hashtags/memes/article headlines as they spread online
- W&B features: artifacts graph, run graph, error type graph, sweeps & hyperparameter importance exploration
Useful References
Circular Dendrogram Full Vega Spec
{"$schema": "https://vega.github.io/schema/vega/v5.json","description": "An example of a radial layout for a node-link diagram of hierarchical data.","width": 720,"height": 720,"padding": 5,"autosize": "none","signals": [{"name": "labels", "value": true,"bind": {"input": "checkbox"}},{"name": "radius", "value": 280,"bind": {"input": "range", "min": 20, "max": 600}},{"name": "extent", "value": 360,"bind": {"input": "range", "min": 0, "max": 360, "step": 1}},{"name": "rotate", "value": 0,"bind": {"input": "range", "min": 0, "max": 360, "step": 1}},{"name": "layout", "value": "tidy","bind": {"input": "radio", "options": ["tidy", "cluster"]}},{"name": "links", "value": "line","bind": {"input": "select","options": ["line", "curve", "diagonal", "orthogonal"]}},{ "name": "originX", "update": "width / 2" },{ "name": "originY", "update": "height / 2" }],"data": [{"name": "wandb","transform": [{"type": "stratify","key": "${field:node_id}","parentKey": "${field:parent}"},{"type": "tree","sort" : {"field": "${field:size}", "order": "descending"},"method": {"signal": "layout"},"size": [1, {"signal": "radius"}],"as": ["alpha", "radius", "depth", "children"]},{"type": "formula","expr": "(rotate + extent * datum.alpha + 270) % 360","as": "angle"},{"type": "formula","expr": "PI * datum.angle / 180","as": "radians"},{"type": "formula","expr": "inrange(datum.angle, [90, 270])","as": "leftside"},{"type": "formula","expr": "originX + datum.radius * cos(datum.radians)","as": "x"},{"type": "formula","expr": "originY + datum.radius * sin(datum.radians)","as": "y"}]},{"name": "links","source": "wandb","transform": [{ "type": "treelinks" },{"type": "linkpath","shape": {"signal": "links"}, "orient": "radial","sourceX": "source.radians", "sourceY": "source.radius","targetX": "target.radians", "targetY": "target.radius"}]}],"scales": [{"name": "color","type": "linear","range": {"scheme": "magma"},"domain": {"data": "wandb", "field": "depth"},"zero": true}],"marks": [{"type": "path","from": {"data": "links"},"encode": {"update": {"x": {"signal": "originX"},"y": {"signal": "originY"},"path": {"field": "path"},"stroke": {"value": "#ccc"}}}},{"type": "symbol","from": {"data": "wandb"},"encode": {"enter": {"size": {"value": 100},"stroke": {"value": "#fff"}},"update": {"x": {"field": "x"},"y": {"field": "y"},"fill": {"scale": "color", "field": "depth"}}}},{"type": "text","from": {"data": "wandb"},"encode": {"enter": {"text": {"field": "${field:node_name}"},"fontSize": {"value": 9},"baseline": {"value": "middle"}},"update": {"x": {"field": "x"},"y": {"field": "y"},"dx": {"signal": "(datum.leftside ? -1 : 1) * 6"},"angle": {"signal": "datum.leftside ? datum.angle - 180 : datum.angle"},"align": {"signal": "datum.leftside ? 'right' : 'left'"},"opacity": {"signal": "labels ? 1 : 0"}}}}]
Add a comment
Iterate on AI agents and models faster. Try Weights & Biases today.