
Experiment Tracking Swanlab
- 358 installs
- 11.2k repo stars
- Updated June 16, 2026
- orchestra-research/ai-research-skills
experiment-tracking-swanlab is an agent skill that teaches developers to integrate SwanLab experiment tracking into PyTorch, HuggingFace Transformers, PyTorch Lightning, and Fastai training workflows for config capture,
About
experiment-tracking-swanlab is an Orchestra Research agent skill (version 1.0.0) for open-source ML experiment tracking with SwanLab. The skill documents swanlab.init, swanlab.log, run.finish, local mode with swanlab watch, and cloud or self-hosted deployment via swanlab login. It ships integration patterns for 4 frameworks—PyTorch, HuggingFace Transformers, PyTorch Lightning, and Fastai—plus media logging for images, audio, text, GIFs, point clouds, and molecules through swanlab.Image, Audio, Text, Video, Object3D, and Molecule APIs. Dependencies pin swanlab>=0.7.11 with pillow and soundfile for media examples, and two reference files cover framework callbacks and ECharts visualization. Reach for experiment-tracking-swanlab when instrumenting training scripts, comparing hyperparameter sweeps, or running offline-first experiments without a managed SaaS tracker.
- Documents SwanLab `init` / `log` / `finish` patterns aligned with public SwanLab docs
- PyTorch training-loop example with config-driven hyperparameters and batch metrics
- Minimal `SwanLabTracker` callback-style wrapper pattern for reusable logging
- Emphasizes structured `config` on run init for reproducible solo ML experiments
Experiment Tracking Swanlab by the numbers
- 358 all-time installs (skills.sh)
- +37 installs in the week ending Jul 18, 2026 (Skillselion tracking)
- Ranked #531 of 2,066 Data Science & ML skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/orchestra-research/ai-research-skills --skill experiment-tracking-swanlabAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 358 |
|---|---|
| repo stars | ★ 11.2k |
| Security audit | 3 / 3 scanners passed |
| Last updated | June 16, 2026 |
| Repository | orchestra-research/ai-research-skills ↗ |
How do you log PyTorch training metrics with SwanLab?
Wire PyTorch (and similar) training loops to SwanLab for experiment config, metrics logging, and run lifecycle.
Who is it for?
Python ML engineers who need open-source, self-hostable experiment tracking integrated into PyTorch, Transformers, Lightning, or Fastai training code.
Skip if: Teams that only need production model serving, inference monitoring, or a non-Python stack without SwanLab-compatible training frameworks.
When should I use this skill?
A developer is adding experiment tracking, hyperparameter logging, or run comparison to an existing PyTorch, Transformers, Lightning, or Fastai training script.
What you get
Instrumented training scripts, SwanLab run records with hyperparameter configs, scalar and media metric logs, and viewable local or cloud experiment dashboards.
- SwanLab-instrumented training scripts with config and metric logging
- Logged experiment runs viewable in local or cloud SwanLab dashboards
By the numbers
- Documents 4 framework integrations: PyTorch, HuggingFace Transformers, PyTorch Lightning, and Fastai
- Covers 6 media logging types: images, audio, text, GIFs, point clouds, and molecules
- Pins swanlab>=0.7.11 with 2 bundled reference files for integrations and visualization
Files
SwanLab: Open-Source Experiment Tracking
When to Use This Skill
Use SwanLab when you need to:
- Track ML experiments with metrics, configs, tags, and descriptions
- Visualize training with scalar charts and logged media
- Compare runs across seeds, checkpoints, and hyperparameters
- Work locally or self-hosted instead of depending on managed SaaS
- Integrate with PyTorch, Transformers, PyTorch Lightning, or Fastai
Deployment: Cloud, local, or self-hosted | Media: images, audio, text, GIFs, point clouds, molecules | Integrations: PyTorch, Transformers, PyTorch Lightning, Fastai
Installation
# Install SwanLab plus the media dependencies used in this skill
pip install "swanlab>=0.7.11" "pillow>=9.0.0" "soundfile>=0.12.0"
# Add local dashboard support for mode="local" and swanlab watch
pip install "swanlab[dashboard]>=0.7.11"
# Optional framework integrations
pip install transformers pytorch-lightning fastai
# Login for cloud or self-hosted usage
swanlab loginpillow and soundfile are the media dependencies used by the Image and Audio examples in this skill. swanlab[dashboard] adds the local dashboard dependency required by mode="local" and swanlab watch.
Quick Start
Basic Experiment Tracking
import swanlab
run = swanlab.init(
project="my-project",
experiment_name="baseline",
config={
"learning_rate": 1e-3,
"epochs": 10,
"batch_size": 32,
"model": "resnet18",
},
)
for epoch in range(run.config.epochs):
train_loss = train_epoch()
val_loss = validate()
swanlab.log(
{
"train/loss": train_loss,
"val/loss": val_loss,
"epoch": epoch,
}
)
run.finish()With PyTorch
import torch
import torch.nn as nn
import torch.optim as optim
import swanlab
run = swanlab.init(
project="pytorch-demo",
experiment_name="mnist-mlp",
config={
"learning_rate": 1e-3,
"batch_size": 64,
"epochs": 10,
"hidden_size": 128,
},
)
model = nn.Sequential(
nn.Flatten(),
nn.Linear(28 * 28, run.config.hidden_size),
nn.ReLU(),
nn.Linear(run.config.hidden_size, 10),
)
optimizer = optim.Adam(model.parameters(), lr=run.config.learning_rate)
criterion = nn.CrossEntropyLoss()
for epoch in range(run.config.epochs):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
logits = model(data)
loss = criterion(logits, target)
loss.backward()
optimizer.step()
if batch_idx % 100 == 0:
swanlab.log(
{
"train/loss": loss.item(),
"train/epoch": epoch,
"train/batch": batch_idx,
}
)
run.finish()Core Concepts
1. Projects and Experiments
Project: Collection of related experiments Experiment: Single execution of a training or evaluation workflow
import swanlab
run = swanlab.init(
project="image-classification",
experiment_name="resnet18-seed42",
description="Baseline run on ImageNet subset",
tags=["baseline", "resnet18"],
config={
"model": "resnet18",
"seed": 42,
"batch_size": 64,
"learning_rate": 3e-4,
},
)
print(run.id)
print(run.config.learning_rate)2. Configuration Tracking
config = {
"model": "resnet18",
"seed": 42,
"batch_size": 64,
"learning_rate": 3e-4,
"epochs": 20,
}
run = swanlab.init(project="my-project", config=config)
learning_rate = run.config.learning_rate
batch_size = run.config.batch_size3. Metric Logging
# Log scalars
swanlab.log({"loss": 0.42, "accuracy": 0.91})
# Log multiple metrics
swanlab.log(
{
"train/loss": train_loss,
"train/accuracy": train_acc,
"val/loss": val_loss,
"val/accuracy": val_acc,
"lr": current_lr,
"epoch": epoch,
}
)
# Log with custom step
swanlab.log({"loss": loss}, step=global_step)4. Media and Chart Logging
import numpy as np
import swanlab
# Image
image = np.random.randint(0, 255, (224, 224, 3), dtype=np.uint8)
swanlab.log({"examples/image": swanlab.Image(image, caption="Augmented sample")})
# Audio
wave = np.sin(np.linspace(0, 8 * np.pi, 16000)).astype("float32")
swanlab.log({"examples/audio": swanlab.Audio(wave, sample_rate=16000)})
# Text
swanlab.log({"examples/text": swanlab.Text("Training notes for this run.")})
# GIF video
swanlab.log({"examples/video": swanlab.Video("predictions.gif", caption="Validation rollout")})
# Point cloud
points = np.random.rand(128, 3).astype("float32")
swanlab.log({"examples/point_cloud": swanlab.Object3D(points, caption="Point cloud sample")})
# Molecule
swanlab.log({"examples/molecule": swanlab.Molecule.from_smiles("CCO", caption="Ethanol")})# Custom chart with swanlab.echarts
line = swanlab.echarts.Line()
line.add_xaxis(["epoch-1", "epoch-2", "epoch-3"])
line.add_yaxis("train/loss", [0.92, 0.61, 0.44])
line.set_global_opts(
title_opts=swanlab.echarts.options.TitleOpts(title="Training Loss")
)
swanlab.log({"charts/loss_curve": line})See references/visualization.md for more chart and media patterns.
5. Local and Self-Hosted Workflows
import os
import swanlab
# Self-hosted or cloud login
swanlab.login(
api_key=os.environ["SWANLAB_API_KEY"],
host="http://your-server:5092",
)
# Local-only logging
run = swanlab.init(
project="offline-demo",
mode="local",
logdir="./swanlog",
)
swanlab.log({"loss": 0.35, "epoch": 1})
run.finish()# View local logs
swanlab watch -l ./swanlog
# Sync local logs later
swanlab sync ./swanlogIntegration Examples
HuggingFace Transformers
from transformers import Trainer, TrainingArguments
training_args = TrainingArguments(
output_dir="./results",
per_device_train_batch_size=8,
evaluation_strategy="epoch",
logging_steps=50,
report_to="swanlab",
run_name="bert-finetune",
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
)
trainer.train()See references/integrations.md for callback-based setups and additional framework patterns.
PyTorch Lightning
import pytorch_lightning as pl
from swanlab.integration.pytorch_lightning import SwanLabLogger
swanlab_logger = SwanLabLogger(
project="lightning-demo",
experiment_name="mnist-classifier",
config={"batch_size": 64, "max_epochs": 10},
)
trainer = pl.Trainer(
logger=swanlab_logger,
max_epochs=10,
accelerator="auto",
)
trainer.fit(model, train_loader, val_loader)Fastai
from fastai.vision.all import accuracy, resnet34, vision_learner
from swanlab.integration.fastai import SwanLabCallback
learn = vision_learner(dls, resnet34, metrics=accuracy)
learn.fit(
5,
cbs=[
SwanLabCallback(
project="fastai-demo",
experiment_name="pets-classification",
config={"arch": "resnet34", "epochs": 5},
)
],
)See references/integrations.md for fuller framework examples.
Best Practices
1. Use Stable Metric Names
# Good: grouped metric namespaces
swanlab.log({
"train/loss": train_loss,
"train/accuracy": train_acc,
"val/loss": val_loss,
"val/accuracy": val_acc,
})
# Avoid mixing flat and grouped names for the same metric family2. Initialize Early and Capture Config Once
run = swanlab.init(
project="image-classification",
experiment_name="resnet18-baseline",
config={
"model": "resnet18",
"learning_rate": 3e-4,
"batch_size": 64,
"seed": 42,
},
)3. Save Checkpoints Locally
import torch
import swanlab
checkpoint_path = "checkpoints/best.pth"
torch.save(model.state_dict(), checkpoint_path)
swanlab.log(
{
"best/val_accuracy": best_val_accuracy,
"artifacts/checkpoint_path": swanlab.Text(checkpoint_path),
}
)4. Use Local Mode for Offline-First Workflows
run = swanlab.init(project="offline-demo", mode="local", logdir="./swanlog")
# ... training code ...
run.finish()
# Inspect later with: swanlab watch -l ./swanlog5. Keep Advanced Patterns in References
- Use references/visualization.md for advanced chart and media patterns
- Use references/integrations.md for callback-based and framework-specific integration details
Resources
See Also
- references/integrations.md - Framework-specific examples
- references/visualization.md - Charts and media logging patterns
SwanLab Framework Integrations
This document focuses on framework patterns that align with the public SwanLab docs.
PyTorch
Basic Training Loop
import torch
import torch.nn as nn
import torch.optim as optim
import swanlab
run = swanlab.init(
project="pytorch-training",
experiment_name="mnist-mlp",
config={
"learning_rate": 1e-3,
"batch_size": 64,
"epochs": 10,
"hidden_size": 128,
},
)
model = nn.Sequential(
nn.Flatten(),
nn.Linear(28 * 28, run.config.hidden_size),
nn.ReLU(),
nn.Linear(run.config.hidden_size, 10),
)
optimizer = optim.Adam(model.parameters(), lr=run.config.learning_rate)
criterion = nn.CrossEntropyLoss()
for epoch in range(run.config.epochs):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
logits = model(data)
loss = criterion(logits, target)
loss.backward()
optimizer.step()
if batch_idx % 100 == 0:
swanlab.log(
{
"train/loss": loss.item(),
"train/epoch": epoch,
"train/batch": batch_idx,
}
)
run.finish()Minimal Callback Wrapper
import swanlab
class SwanLabTracker:
def __init__(self, project, experiment_name=None, config=None):
self.run = swanlab.init(
project=project,
experiment_name=experiment_name,
config=config,
)
def log_metrics(self, metrics, step=None):
swanlab.log(metrics, step=step)
def log_images(self, name, images, captions=None):
if captions is None:
payload = [swanlab.Image(image) for image in images]
else:
payload = [
swanlab.Image(image, caption=caption)
for image, caption in zip(images, captions)
]
swanlab.log({name: payload})
def log_note(self, name, text):
swanlab.log({name: swanlab.Text(text)})
def finish(self):
self.run.finish()This wrapper deliberately omits fake histogram and file helpers that are not present in current SwanLab APIs.
Transformers
transformers>=4.50.0: official one-line integration
Prefer report_to="swanlab" on recent Transformers releases. This is the primary path documented by SwanLab.
from transformers import (
AutoModelForSequenceClassification,
AutoTokenizer,
Trainer,
TrainingArguments,
)
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModelForSequenceClassification.from_pretrained(
"bert-base-uncased",
num_labels=2,
)
training_args = TrainingArguments(
output_dir="./results",
num_train_epochs=3,
per_device_train_batch_size=16,
per_device_eval_batch_size=16,
evaluation_strategy="epoch",
logging_steps=100,
report_to="swanlab",
run_name="bert-imdb",
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
)
trainer.train()Set SWANLAB_PROJ_NAME and SWANLAB_WORKSPACE environment variables when you need custom routing without switching away from the official integration path.
transformers<4.50.0 or custom control: SwanLabCallback
Use SwanLabCallback as the fallback path for older Transformers versions, or when you want SwanLab-specific control without report_to="swanlab".
from transformers import (
AutoModelForSequenceClassification,
AutoTokenizer,
Trainer,
TrainingArguments,
)
from swanlab.integration.transformers import SwanLabCallback
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModelForSequenceClassification.from_pretrained(
"bert-base-uncased",
num_labels=2,
)
training_args = TrainingArguments(
output_dir="./results",
evaluation_strategy="epoch",
logging_steps=100,
report_to="none",
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
callbacks=[
SwanLabCallback(
project="text-classification",
experiment_name="bert-imdb",
config={
"model": "bert-base-uncased",
"batch_size": 16,
"epochs": 3,
},
)
],
)
trainer.train()PyTorch Lightning
SwanLabLogger can create the run for you. Prefer passing project metadata directly to the logger.
import pytorch_lightning as pl
import torch
import torch.nn as nn
from swanlab.integration.pytorch_lightning import SwanLabLogger
class LitClassifier(pl.LightningModule):
def __init__(self, learning_rate=1e-3):
super().__init__()
self.save_hyperparameters()
self.model = nn.Sequential(
nn.Flatten(),
nn.Linear(28 * 28, 128),
nn.ReLU(),
nn.Linear(128, 10),
)
self.criterion = nn.CrossEntropyLoss()
def forward(self, x):
return self.model(x)
def training_step(self, batch, batch_idx):
x, y = batch
logits = self(x)
loss = self.criterion(logits, y)
self.log("train/loss", loss, prog_bar=True)
return loss
def validation_step(self, batch, batch_idx):
x, y = batch
logits = self(x)
loss = self.criterion(logits, y)
acc = (torch.argmax(logits, dim=1) == y).float().mean()
self.log("val/loss", loss, prog_bar=True)
self.log("val/accuracy", acc, prog_bar=True)
def configure_optimizers(self):
return torch.optim.Adam(self.parameters(), lr=self.hparams.learning_rate)
swanlab_logger = SwanLabLogger(
project="lightning-demo",
experiment_name="mnist-classifier",
config={"learning_rate": 1e-3, "max_epochs": 10},
)
trainer = pl.Trainer(
logger=swanlab_logger,
max_epochs=10,
accelerator="auto",
)
trainer.fit(LitClassifier(), train_loader, val_loader)Fastai
SwanLabCallback accepts the same run metadata you would normally pass to swanlab.init(...).
from fastai.vision.all import URLs, ImageDataLoaders, Resize, accuracy, get_image_files, resnet34, untar_data, vision_learner
from swanlab.integration.fastai import SwanLabCallback
path = untar_data(URLs.PETS)
dls = ImageDataLoaders.from_name_func(
path,
get_image_files(path / "images"),
valid_pct=0.2,
label_func=lambda x: x[0].isupper(),
item_tfms=Resize(224),
bs=64,
)
learn = vision_learner(dls, resnet34, metrics=accuracy)
learn.fit(
5,
cbs=[
SwanLabCallback(
project="fastai-demo",
experiment_name="pets-classification",
config={"arch": "resnet34", "epochs": 5, "batch_size": 64},
)
],
)Fastai Text
from fastai.text.all import AWD_LSTM, TextDataLoaders, accuracy, text_classifier_learner, untar_data, URLs
from swanlab.integration.fastai import SwanLabCallback
path = untar_data(URLs.IMDB)
dls = TextDataLoaders.from_folder(path, valid="test", bs=64)
learn = text_classifier_learner(
dls,
AWD_LSTM,
drop_mult=0.5,
metrics=accuracy,
)
learn.fit_one_cycle(
3,
cbs=[
SwanLabCallback(
project="fastai-text",
experiment_name="imdb-sentiment",
config={"arch": "AWD_LSTM", "epochs": 3, "batch_size": 64},
)
],
)Best Practices
1. Initialize as early as possible so config and environment metadata are captured once. 2. Use stable metric names such as train/loss and val/accuracy across runs. 3. Save checkpoints locally with your framework and log the checkpoint path or score separately. 4. Prefer run.finish() when you manage the run yourself; let framework integrations finalize runs when they own the lifecycle. 5. Use mode="local" plus swanlab watch -l ./swanlog when you want an offline-first workflow.
SwanLab Visualization Guide
This guide covers chart objects and validated media types in the public SwanLab docs.
Chart Objects with swanlab.echarts
SwanLab accepts pyecharts chart objects through swanlab.echarts. Log the chart object directly instead of wrapping a raw option dictionary.
Line Chart
import swanlab
loss_chart = swanlab.echarts.Line()
loss_chart.add_xaxis(["epoch-1", "epoch-2", "epoch-3", "epoch-4"])
loss_chart.add_yaxis("train/loss", [0.95, 0.63, 0.41, 0.29])
loss_chart.set_global_opts(
title_opts=swanlab.echarts.options.TitleOpts(title="Training Loss")
)
swanlab.log({"charts/loss": loss_chart})Multi-Series Line Chart
comparison = swanlab.echarts.Line()
comparison.add_xaxis(["1", "2", "3", "4"])
comparison.add_yaxis("train/loss", [0.95, 0.63, 0.41, 0.29])
comparison.add_yaxis("val/loss", [1.02, 0.72, 0.55, 0.49])
comparison.set_global_opts(
title_opts=swanlab.echarts.options.TitleOpts(title="Train vs Val Loss")
)
swanlab.log({"charts/comparison": comparison})Bar Chart
bar = swanlab.echarts.Bar()
bar.add_xaxis(["cat", "dog", "bird", "fish"])
bar.add_yaxis("accuracy", [95, 92, 88, 91])
bar.set_global_opts(
title_opts=swanlab.echarts.options.TitleOpts(title="Per-Class Accuracy")
)
swanlab.log({"charts/per_class_accuracy": bar})HeatMap
heatmap = swanlab.echarts.HeatMap()
heatmap.add_xaxis(["Class A", "Class B", "Class C"])
heatmap.add_yaxis(
"count",
["Class A", "Class B", "Class C"],
[
[0, 0, 50], [0, 1, 2], [0, 2, 1],
[1, 0, 3], [1, 1, 45], [1, 2, 2],
[2, 0, 1], [2, 1, 3], [2, 2, 48],
],
)
heatmap.set_global_opts(
title_opts=swanlab.echarts.options.TitleOpts(title="Confusion Matrix"),
visualmap_opts=swanlab.echarts.options.VisualMapOpts(min_=0, max_=50),
)
swanlab.log({"charts/confusion_matrix": heatmap})Image Logging
Single Images
import numpy as np
import swanlab
from PIL import Image
swanlab.log({"image/path": swanlab.Image("path/to/image.png")})
image_array = np.random.randint(0, 255, (224, 224, 3), dtype=np.uint8)
swanlab.log({"image/numpy": swanlab.Image(image_array, caption="Random image")})
pil_image = Image.open("photo.jpg")
swanlab.log({"image/pil": swanlab.Image(pil_image)})Image Batches
samples = [img1, img2, img3]
captions = ["sample-1", "sample-2", "sample-3"]
swanlab.log(
{
"image/batch": [
swanlab.Image(img, caption=caption)
for img, caption in zip(samples, captions)
]
}
)swanlab.Image does not support inline box metadata in current SwanLab releases. For detection tasks, draw overlays yourself before logging the image.
Audio Logging
import numpy as np
import swanlab
swanlab.log({"audio/file": swanlab.Audio("recording.wav", sample_rate=16000)})
sample_rate = 16000
audio = np.sin(np.linspace(0, 8 * np.pi, sample_rate)).astype("float32")
swanlab.log({"audio/generated": swanlab.Audio(audio, sample_rate=sample_rate)})
swanlab.log(
{
"audio/captioned": swanlab.Audio(
"generated.wav",
sample_rate=22050,
caption="Generated speech sample",
)
}
)GIF Video Logging
Current SwanLab releases only accept GIF paths for swanlab.Video.
import swanlab
swanlab.log({"video/demo": swanlab.Video("demo.gif")})
swanlab.log(
{
"video/predictions": swanlab.Video(
"predictions.gif",
caption="Validation rollout",
)
}
)Text Logging
import swanlab
swanlab.log({"text/generated": swanlab.Text("The quick brown fox jumps over the lazy dog.")})
swanlab.log(
{
"text/llm_output": swanlab.Text(
"This is a generated response.",
caption="Prompt: summarize the dataset",
)
}
)3D Objects
Point Clouds from Numpy
import numpy as np
import swanlab
points = np.random.rand(256, 3).astype("float32")
swanlab.log({"object3d/points": swanlab.Object3D(points, caption="Random point cloud")})This guide intentionally sticks to numpy point clouds for Object3D. File-based constructors may exist in some package versions, but they are not the default public API path used in this skill. Object3D also does not accept .obj or .ply paths directly.
Molecules
Use the documented helper constructor instead of passing raw strings directly to swanlab.Molecule(...).
import swanlab
swanlab.log({"molecule/smiles": swanlab.Molecule.from_smiles("CCO", caption="Ethanol")})Some package versions expose additional molecule file helpers, but this guide does not rely on them because the public API page does not make them the default path.
Experiment Comparison
import swanlab
baseline = swanlab.init(project="comparison-demo", experiment_name="baseline")
for step in range(5):
swanlab.log({"val/loss": 1.0 / (step + 1)}, step=step)
baseline.finish()
improved = swanlab.init(project="comparison-demo", experiment_name="improved")
for step in range(5):
swanlab.log({"val/loss": 0.8 / (step + 1)}, step=step)
improved.finish()Then compare the runs in the SwanLab UI.
Troubleshooting
Chart does not render
Log a swanlab.echarts.* object directly. Do not pass raw dictionaries through an old wrapper API.
Images look wrong
Convert arrays to HWC uint8 before wrapping them in swanlab.Image.
import numpy as np
image = np.transpose(image, (1, 2, 0))
image = np.clip(image * 255, 0, 255).astype(np.uint8)Media imports fail
Install the media dependencies used in this skill:
pip install "swanlab>=0.7.11" "pillow>=9.0.0" "soundfile>=0.12.0"Related skills
How it compares
Choose experiment-tracking-swanlab when you want open-source, local or self-hosted experiment tracking wired directly into Python training code instead of a proprietary cloud-only SaaS workflow.
FAQ
Which ML frameworks does experiment-tracking-swanlab support?
experiment-tracking-swanlab documents SwanLab integrations for PyTorch training loops, HuggingFace Transformers via report_to="swanlab", PyTorch Lightning through SwanLabLogger, and Fastai via SwanLabCallback, with fuller callback patterns in references/integrations.md.
Can SwanLab run without cloud or SaaS?
experiment-tracking-swanlab shows offline-first workflows using swanlab.init with mode="local" and a logdir, then swanlab watch to inspect runs locally; cloud or self-hosted sync uses swanlab login with an API key and custom host.
What Python packages does experiment-tracking-swanlab require?
experiment-tracking-swanlab pins swanlab>=0.7.11, pillow>=9.0.0, and soundfile>=0.12.0 for media logging; optional swanlab[dashboard] adds local dashboard support, and framework packages like transformers or pytorch-lightning install separately.
Is Experiment Tracking Swanlab safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.