Если вы обучаете модели за пределами одного блокнота, то наверняка сталкивались с типичными проблемами: корректируете несколько параметров, перезапускаете обучение, и к концу недели уже не вспомните, какой запуск дал удачную кривую ROC или какой сегмент данных применялся. Weights & Biases (W&B) обеспечивает четкий след — метрики, конфигурации, графики, наборы данных и модели, — чтобы вы могли опираться на факты, а не на предположения при анализе изменений.
Далее представлен практический обзор. Он субъективен, лаконичен и ориентирован на команды, желающие вести упорядоченную историю экспериментов без разработки собственной системы. Это прямолинейное руководство без лишних деталей.
# Зачем вообще использовать W&B?
Блокноты эволюционируют в полноценные эксперименты. Эксперименты размножаются. Вскоре возникают вопросы: какой запуск задействовал тот сегмент данных? Почему сегодняшняя кривая ROC улучшилась? Можно ли воспроизвести базовую модель с прошлой недели?
W&B предоставляет пространство для:
- Регистрации метрик, конфигураций, графиков и системных показателей
- Версионирования наборов данных и моделей с помощью артефактов
- Проведения свопов гиперпараметров
- Обмена дашбордами без использования скриншотов
Начинать можно с малого и постепенно добавлять функции по мере необходимости.
# Настройка за 60 секунд
Начните с установки библиотеки и авторизации с помощью API-ключа. Если ключа еще нет, его можно получить здесь.
pip install wandb
wandb login # вставьте API-ключ один раз// Простая проверка работоспособности
import wandb, random, time
wandb.init(project="kdn-crashcourse", name="hello-run", config={"lr": 0.001, "epochs": 5})
for epoch in range(wandb.config.epochs):
loss = 1.0 / (epoch + 1) + random.random() * 0.05
wandb.log({"epoch": epoch, "loss": loss})
time.sleep(0.1)
wandb.finish()Теперь вы должны увидеть примерно такой результат:
Переходим к практически полезным аспектам.
# Отслеживание экспериментов на должном уровне
// Регистрация гиперпараметров и метрик
Считайте wandb.config единственным надежным источником для параметров эксперимента. Придавайте метрикам понятные названия, чтобы графики группировались автоматически.
cfg = dict(
arch="resnet18",
lr=3e-4,
batch=64,
seed=42
)
run = wandb.init(project="kdn-mlops", config=cfg, tags=["baseline"])
# цикл обучения
...
for step, (x, y) in enumerate(loader):
# ... вычисление loss, acc
wandb.log({
"train/loss": loss.item(),
"train/acc": acc,
"step": step
})
# запись итогового обзора
run.summary["best_val_auc"] = best_aucНесколько советов:
- Применяйте пространства имен вроде
train/lossилиval/aucдля автоматической группировки графиков - Добавляйте теги типа
"lr-finder"или"fp16", чтобы потом фильтровать запуски - Используйте
run.summary[...]для разовых результатов, которые нужно отобразить на карточке запуска
// Регистрация изображений, матриц ошибок и пользовательских графиков
wandb.log({
"val/confusion": wandb.plot.confusion_matrix(
preds=preds,
y_true=y_true,
class_names=classes
)
})Также можно сохранять любые графики Matplotlib:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(history)
wandb.log({"training/curve": fig})// Версионирование наборов данных и моделей с артефактами
Артефакты помогают отвечать на вопросы вроде "Какие именно файлы использовались в этом запуске?" и "Что именно обучалось?". Больше никаких загадок с final_final_v3.parquet.
import wandb
run = wandb.init(project="kdn-mlops")
# Создание артефакта для набора данных (один раз на версию)
raw = wandb.Artifact("imdb_reviews", type="dataset", description="raw dump v1")
raw.add_dir("data/raw") # или add_file("path")
run.log_artifact(raw)
# Позже, использование последней версии
artifact = run.use_artifact("imdb_reviews:latest")
data_dir = artifact.download() # путь к папке, привязанный к хэшуМодели регистрируют аналогично:
import torch
import wandb
run = wandb.init(project="kdn-mlops")
model_path = "models/resnet18.pt"
torch.save(model.state_dict(), model_path)
model_art = wandb.Artifact("sentiment-resnet18", type="model")
model_art.add_file(model_path)
run.log_artifact(model_art)Теперь происхождение очевидно: эта модель получилась из тех данных при том коммите кода.
// Таблицы для оценки и анализа ошибок
wandb.Table — это легковесная таблица для результатов, предсказаний и сегментов.
table = wandb.Table(columns=["id", "text", "pred", "true", "prob"])
for r in batch_results:
table.add_data(r.id, r.text, r.pred, r.true, r.prob)
wandb.log({"eval/preds": table})В интерфейсе можно фильтровать таблицу, чтобы выявить шаблоны сбоев (например, короткие отзывы, редкие классы и т.д.).
// Свопы гиперпараметров
Определите пространство поиска в YAML, запустите агенты, и W&B возьмет координацию на себя.
# sweep.yaml
method: bayes
metric:
name: val/auc
goal: maximize
parameters:
lr:
min: 1e-5
max: 1e-2
batch:
values: [32, 64, 128]
dropout:
min: 0.0
max: 0.5Запустите своп:
wandb sweep sweep.yaml # возвращает SWEEP_ID
wandb agent <your-entity>/<project>/<sweep_id> # запуск 1+ агентовСкрипт обучения должен читать wandb.config для lr, batch и т.д. Дашборд отображает лучшие пробы, параллельные координаты и оптимальную конфигурацию.
# Готовые интеграции
Выберите подходящую и продолжайте работу.
// PyTorch Lightning
from pytorch_lightning.loggers import WandbLogger
logger = WandbLogger(project="kdn-mlops")
trainer = pl.Trainer(logger=logger, max_epochs=10)// Keras
import wandb
from wandb.keras import WandbCallback
wandb.init(project="kdn-mlops", config={"epochs": 10})
model.fit(X, y, epochs=wandb.config.epochs, callbacks=[WandbCallback()])// Scikit-learn
from sklearn.metrics import roc_auc_score
wandb.init(project="kdn-mlops", config={"C": 1.0})
# ... обучение модели
wandb.log({"val/auc": roc_auc_score(y_true, y_prob)})# Реестр моделей и подготовка
Реестр можно представить как именованную полку для лучших моделей. Вы загружаете артефакт один раз, затем управляете алиасами вроде staging или production, чтобы последующие коды могли извлекать нужную версию без поиска путей к файлам.
run = wandb.init(project="kdn-mlops")
art = run.use_artifact("sentiment-resnet18:latest")
registry = wandb.sdk.artifacts.model_registry.ModelRegistry()
entry = registry.push(art, name="sentiment-classifier")
entry.aliases.add("staging")Переключайте алиас при продвижении новой сборки. Потребители всегда обращаются к sentiment-classifier:production.
# Чек-лист воспроизводимости
- Конфигурации: Храните все гиперпараметры в
wandb.config - Код и коммит: Используйте
wandb.init(settings=wandb.Settings(code_dir="."))для снимка кода или полагайтесь на CI для прикрепления SHA гита - Среда: Регистрируйте
requirements.txtили тег Docker и включайте в артефакт - Сиды: Логируйте их и устанавливайте
Простой помощник для сидов:
def set_seeds(s=42):
import random, numpy as np, torch
random.seed(s)
np.random.seed(s)
torch.manual_seed(s)
torch.cuda.manual_seed_all(s)# Сотрудничество и обмен без скриншотов
Добавляйте заметки и теги, чтобы коллеги могли искать. Используйте Reports для объединения графиков, таблиц и комментариев в ссылку, которую можно отправить в Slack или PR. Заинтересованные стороны могут следить за процессом без открытия блокнота.
# Советы по CI и автоматизации
- Запускайте
wandb agentна узлах обучения для выполнения свопов из CI - После ETL-задачи регистрируйте артефакт набора данных; задачи обучения могут явно зависеть от этой версии
- После оценки продвигайте алиасы моделей (
staging→production) в коротком пост-шаге - Передавайте
WANDB_API_KEYкак секрет и группируйте связанные запуски сWANDB_RUN_GROUP
# Советы по конфиденциальности и надежности
- По умолчанию используйте приватные проекты для команд
- Для изолированных запусков применяйте оффлайн-режим. Обучайте как обычно, затем
wandb syncпозже
export WANDB_MODE=offline- Не регистрируйте сырые PII. Если нужно, хэшируйте ID перед логированием.
- Для больших файлов храните их как артефакты, а не прикрепляйте к
wandb.log.
# Распространенные проблемы (и быстрые решения)
- "Мой запуск ничего не записал." Скрипт мог завершиться аварийно до вызова
wandb.finish(). Также проверьте, не установлен лиWANDB_DISABLED=trueв окружении. - Логирование кажется медленным. Логируйте скаляры на каждом шаге, но тяжелые активы вроде изображений или таблиц сохраняйте в конце эпохи. Можно передать
commit=Falseвwandb.log()и батчить несколько логов вместе. - В интерфейсе дубликаты запусков? Если возобновляете с чекпоинта, укажите
idиresume="allow"вwandb.init(), чтобы продолжить тот же запуск. - Сталкиваетесь с загадочным дрейфом данных? Помещайте каждый снимок набора данных в артефакт и привязывайте запуски к явным версиям.
# Карманный шпаргалка
// 1. Запуск сессии
wandb.init(project="proj", config=cfg, tags=["baseline"])// 2. Логирование метрик, изображений или таблиц
wandb.log({"train/loss": loss, "img": [wandb.Image(img)]})// 3. Версионирование набора данных или модели
art = wandb.Artifact("name", type="dataset")
art.add_dir("path")
run.log_artifact(art)// 4. Использование артефакта
path = run.use_artifact("name:latest").download()// 5. Запуск свопа
wandb sweep sweep.yaml && wandb agent <entity>/<project>/<sweep_id># Итоги
Начните с малого: инициализируйте запуск, запишите несколько метрик и загрузите файл модели как артефакт. Когда это войдет в привычку, добавьте своп и краткий отчет. В итоге вы получите воспроизводимые эксперименты, отслеживаемые данные и модели, а также дашборд, который объясняет вашу работу без презентаций.