Skip to content

Experiment Tracking Architecture: W&B + Hydra + DVC — The Engineering of Sweeps

Disciplining ML experiments: config-driven runs with Hydra, sweep + system metrics + offline mode with W&B, dataset/checkpoint versioning with DVC, alias/lineage tracking. The cookbook's 'reportable Lab' standard.

Şükrü Yusuf KAYA
34 min read
Intermediate
Experiment Tracking Mimarisi: Weights&Biases + Hydra + DVC — Sweep'in Mühendisliği
🎯 Bu ders ne için
İyi haber: cookbook'un her Lab'ı W&B + Hydra + DVC entegrasyonuyla gelir. Kötü haber: bu üçlüyü doğru kullanmak ML mühendisliğinin 'demir leblebisi'dir — yanlış kurulmuş tracking bazen hiç tracking olmamasından daha kötüdür ('run-shopping' davranışı). Bu derste doğrusunu kuruyoruz.

1. Niye Üç Ayrı Tool? (Ve Niye Hiçbiri Tek Başına Yetmiyor)#

Aracın işiNe yaparYokken acı
HydraConfig'i CLI override ile, YAML hiyerarşisinde, sweep-friendly tut"lr=2e-5 yerine 3e-5 deneyim" → argparse'ı boz, tüm flag'leri elle yaz
W&BMetrik + system telemetry + artifact log + sweep run"şu üç run hangisi en iyi?" → terminal log dosyalarını grep'le
DVCDataset & büyük dosya versioning, lineage"datasetin hangi versiyonu üzerinde train olmuş?" → cevap yok, run kaybolur
Üçlünün birlikte yarattığı şey: her W&B run'ı bir Hydra config + bir DVC dataset hash ile deterministically ilişkili olur. Hangi config + hangi dataset + hangi git commit = hangi sonuç triple'ı tam doluyor.
yaml
# === configs/ — Cookbook Hydra layout (her Lab aynı şema) ===
# configs/config.yaml (default)
defaults:
- model: llama3_8b
- data: tr_alpaca
- trainer: qlora
- optim: adamw_8bit
- logging: wandb
- _self_
 
run:
name: ${model.name}_${data.name}_${trainer.name}
seed: 42
output_dir: outputs/${run.name}/${now:%Y-%m-%d_%H-%M-%S}
stage: reference # spike | reference | production | research
 
# configs/model/llama3_8b.yaml
name: llama-3-8b
hf_id: meta-llama/Meta-Llama-3-8B
torch_dtype: bfloat16
quantization:
enabled: true
bnb_4bit_quant_type: nf4
bnb_4bit_use_double_quant: true
bnb_4bit_compute_dtype: bfloat16
 
# configs/data/tr_alpaca.yaml
name: tr-alpaca
hf_id: malhajar/alpaca-gpt4-tr
split: train
max_seq_len: 2048
packing: true
text_field: text
chat_template: llama3
 
# configs/trainer/qlora.yaml
name: qlora-r32
lora:
r: 32
alpha: 64
dropout: 0.05
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
training:
num_epochs: 3
per_device_train_batch_size: 2
gradient_accumulation_steps: 8
learning_rate: 2.0e-4
warmup_ratio: 0.03
lr_scheduler_type: cosine
gradient_checkpointing: true
bf16: true
logging_steps: 5
save_steps: 100
eval_steps: 100
 
# configs/logging/wandb.yaml
project: ftc-llama-tr-cookbook
entity: ${oc.env:WANDB_ENTITY,null}
mode: online # offline mode: cluster'da internet yoksa
tags: [${run.stage}, ${model.name}, ${trainer.name}]
Hydra config layout — cookbook'un her Lab'ı bu iskeleti kullanır

Hydra'nın gücü: CLI override#

# Tek run uv run python train.py # Override uv run python train.py optim=lion trainer.training.learning_rate=1e-4 # Multi-run (Hydra'nın "multirun" özelliği) uv run python train.py -m optim=adamw_8bit,lion trainer.training.learning_rate=1e-4,2e-4,5e-4 # → 6 ayrı run, her biri kendi output_dir'inde
Cookbook'taki tipik sweep komutu (5 lr × 3 lora rank × 2 dropout = 30 run):
uv run python train.py -m \ trainer.training.learning_rate=1e-5,5e-5,1e-4,2e-4,5e-4 \ trainer.lora.r=16,32,64 \ trainer.lora.dropout=0.0,0.1
python
# === train.py — W&B + Hydra entegrasyonu (cookbook iskeleti) ===
import os, json, hashlib
from pathlib import Path
 
import hydra
from omegaconf import DictConfig, OmegaConf
import wandb
import torch
 
@hydra.main(version_base=None, config_path="configs", config_name="config")
def main(cfg: DictConfig):
# 1) Config'i resolve et + freeze
cfg = OmegaConf.to_container(cfg, resolve=True)
OmegaConf.save(cfg, Path(cfg["run"]["output_dir"]) / "config.frozen.yaml")
 
# 2) W&B init — config'in tamamı + git fingerprint
git_sha = os.popen("git rev-parse HEAD").read().strip()
data_hash = compute_dataset_hash(cfg["data"]) # aşağıda
 
wandb.init(
project=cfg["logging"]["project"],
entity=cfg["logging"]["entity"],
name=cfg["run"]["name"],
tags=cfg["logging"]["tags"],
mode=cfg["logging"]["mode"],
config={
**cfg,
"_git_sha": git_sha,
"_data_sha256": data_hash,
"_gpu": torch.cuda.get_device_name(0),
"_torch": torch.__version__,
"_cuda": torch.version.cuda,
},
# cookbook standardı: her run unique ID, lineage'a bağlı
id=hashlib.sha256(
f"{git_sha}-{cfg['run']['seed']}-{data_hash}".encode()
).hexdigest()[:16],
resume="allow",
)
 
# 3) Sistem metriklerini agresif kaydet
wandb.define_metric("step")
wandb.define_metric("train/*", step_metric="step")
wandb.define_metric("eval/*", step_metric="step", summary="best")
wandb.define_metric("gpu_mem/peak_gb", step_metric="step", summary="max")
wandb.define_metric("throughput/tokens_per_sec", step_metric="step", summary="mean")
 
# 4) Modeli yükle, training loop
model, tokenizer = build_model_and_tokenizer(cfg["model"])
dataset = build_dataset(cfg["data"], tokenizer)
trainer = build_trainer(cfg["trainer"], model, dataset)
 
# 5) Trainer callback ile metrik log'la
trainer.add_callback(WandbDetailedCallback(cfg))
trainer.train()
 
# 6) Final artifact — model + config + frozen state
art = wandb.Artifact(name=f"model-{wandb.run.id}", type="model",
metadata={"git_sha": git_sha, "data_sha256": data_hash})
art.add_dir(cfg["run"]["output_dir"])
wandb.log_artifact(art, aliases=["latest", cfg["run"]["stage"]])
wandb.finish()
 
def compute_dataset_hash(data_cfg: dict) -> str:
"""Dataset'in 'state'ini hash'le: HF dataset id + split + version."""
key = f"{data_cfg['hf_id']}::{data_cfg['split']}::{data_cfg.get('revision', 'main')}"
return hashlib.sha256(key.encode()).hexdigest()[:32]
 
if __name__ == "__main__":
main()
W&B + Hydra entegrasyon iskeleti — cookbook'un her train.py'sinde

3. W&B Sweep — Hyperparameter Tarama#

W&B Sweep'in 3 modu var:
grid
,
random
,
bayes
. Cookbook'un kullanım kuralı:
ModNe zamanBütçe
grid
2-3 hyperparam, exhaustive görmek istiyorum2550(25-50 (75 max)
random
5+ hyperparam, kabaca taramak istiyorum$50-100
bayes
8+ hyperparam, "en iyi" bulmak istiyorum$100-300
Cookbook'taki tipik sweep config'i:
yaml
# === sweep.yaml — W&B Bayesian sweep (8B QLoRA tuning) ===
program: train.py
method: bayes
metric:
name: eval/loss
goal: minimize
 
parameters:
trainer.training.learning_rate:
distribution: log_uniform_values
min: 1.0e-5
max: 5.0e-4
trainer.lora.r:
values: [8, 16, 32, 64, 128]
trainer.lora.alpha:
distribution: int_uniform
min: 8
max: 256
trainer.lora.dropout:
distribution: uniform
min: 0.0
max: 0.2
trainer.training.warmup_ratio:
distribution: uniform
min: 0.0
max: 0.1
 
early_terminate:
type: hyperband
min_iter: 100 # 100 step görmeden agent'ı erken durdurma
s: 2
 
# Run komutu
command:
- ${env}
- uv
- run
- python
- ${program}
- ${args_no_hyphens} # Hydra için "--" olmadan key=value
W&B Bayesian sweep — 8B QLoRA hyperparameter tuning

Sweep çalıştırma#

# 1) Sweep oluştur (bir kere) wandb sweep sweep.yaml # → ID: abcd1234 # 2) Agent'leri başlat (paralel) wandb agent your-entity/ftc-llama-tr-cookbook/abcd1234 & wandb agent your-entity/ftc-llama-tr-cookbook/abcd1234 & # RTX 4090 tek GPU, ama farklı saatlerde 2 process koşturmak yerine seri tercih # Tek-GPU sweep'inde: tek agent, 50-100 run # 3) Limit: 50 run, 4 saat wandb agent --count 50 your-entity/ftc-llama-tr-cookbook/abcd1234
W&B Sweep dashboard'unda parallel coordinates plot ile hangi hyperparam'ın hangi loss bandında performans yaptığını görsel olarak çıkarabilirsin. Cookbook'un her ders sonundaki "recommended hyperparams" tablosu bu sweep'lerin sonucu.

4. DVC: Dataset & Checkpoint Versioning#

W&B
Artifact
dataset'i de versiyonlayabilir — ama:
  1. W&B Artifact'ı storage'ı W&B üzerinden geçirir (büyük dataset için trafik pahalı)
  2. Local lineage için ekstra entegrasyon gerekir
  3. CI'da dataset rebuild step'i için DVC daha rahat
Cookbook'un kuralı:
  • Dataset prep çıktısı (tokenized .arrow shards) → DVC track (S3/GCS/local remote)
  • Final checkpoint → W&B Artifact (lineage W&B'de)
  • Logs + metrics → W&B (zaten)

DVC kurulumu#

uv add --dev dvc[s3] # S3 backend için dvc init dvc remote add -d s3 s3://my-bucket/ftc-data # Dataset'i track'le dvc add data/tokenized git add data/tokenized.dvc .gitignore git commit -m "data(tokenized): TR-Alpaca + OASST-TR v1" dvc push # remote'a yükle
data/tokenized.dvc
küçük bir YAML — sadece md5 + boyut + remote pointer içerir. Git'e bunu commit'lersin; dataset binary'sini değil.

DVC pipeline (reproducible dataset prep)#

# dvc.yaml stages: tokenize: cmd: uv run python scripts/tokenize.py configs/data/tr_alpaca.yaml deps: - scripts/tokenize.py - configs/data/tr_alpaca.yaml outs: - data/tokenized/tr_alpaca build_eval_set: cmd: uv run python scripts/build_eval.py deps: - scripts/build_eval.py - data/tokenized/tr_alpaca outs: - data/eval/tr_mmlu_sample.jsonl
dvc repro
çağrısı tüm pipeline'ı incremental çalıştırır — hash değişmemişse step skip. Eğitim Lab'ı için "dataset rebuild" maliyeti ~0 olur.

5. Lineage Triple: Cookbook'un "Ben Kimim" Cevabı#

Her W&B run'ının summary'sinde, cookbook'un zorunlu kıldığı 3 alan:
_git_sha: 8b9910d2c4a5... _data_sha256: a87f5e2c4d9b... _run_id: ed85420a7c63...
Bu triple ile 6 ay sonra açıp:
  1. git checkout 8b9910d2c4a5
    ile tam kodun versiyonunu geri al
  2. dvc checkout
    ile dataset'in tam versiyonunu geri al
  3. wandb artifact get ed85420a7c63
    ile model + config'i geri al
Aynı sonucu bit-exact üretebilirsin. Bu cookbook'un sertifika gereksinimi.
🐛 Failure Mode Drill #4 — '20 run yaptım, hangi config en iyiydi unutmuşum'
Senaryo: 3 gün önce 20 run koştun, W&B'de hepsi sıralı duruyor ama: (a) farklı git commit'lerden geliyor → cookbook tarafından otomatik fixlenir, `_git_sha` her run'ın config'inde. (b) Bazıları farklı dataset versiyonundan — niye → `_data_sha256` farklı. (c) Bazı run'lar `stage=spike`, bazıları `stage=reference` — tag filtre ile ayır. (d) Bazılarında W&B mode=offline kalmış, hâlâ sync olmamış → `wandb sync wandb/offline-*` ile bir kerede yükle. Drill: 20 run'ından lineage triple'larını çıkar, hangi 3 tanesi 'bit-exact reproducible' kalitesinde?

6. Bench: Tracking Overhead'i Var mı?#

Configstep/soverheadNotlar
Baseline (no logging)2.100%sadece print
+ W&B online2.08-1%hostbağımlı küçük HTTP yükü
+ W&B + system_metrics2.05-2.4%her 15 sn GPU stats
+ W&B + Hydra config2.05-2.4%Hydra resolve tek seferlik
+ W&B + Hydra + DVC track2.05-2.4%DVC checkpoint dışında bekler
Full + sweep agent2.04-2.9%tolerable
Sonuç: Disiplinli tracking'in maliyeti ~%3 throughput. Karşılığında: tek bir sweep'te 30 run hangisi en iyi, niye en iyi, hangi dataset'le, hangi commit'te — hepsi bir click uzakta. Çok cömert bir takas.
✅ Bu dersin teslimi
  1. W&B hesabı aç (free tier yeterli, 100GB artifact). 2) Yukarıdaki Hydra layout'unu `configs/`'a kopyala. 3) Minik bir 100-step Llama 3.2 1B QLoRA Lab'ını koş — W&B'de run'ın config'inde `_git_sha` ve `_data_sha256`'i gör. 4) Aynı komutu seed=43 ile bir kez daha koş; W&B'de 2 run yan yana karşılaştır. Part 0 tamamlandı — Part I'e geçiyoruz: Hardware & Memory Engineering.

Frequently Asked Questions

Evet — cookbook hiçbiriyle anlaşmalı değil. W&B'i seçme nedeni: sweep UX'i ve system metrics agresifliği. MLflow open-source self-host için daha rahat (privacy hassas takımlar için). Aim local-first, hızlı. Cookbook'un train.py iskeleti backend-agnostic; \`wandb.init\` çağrısını \`mlflow.start_run\` ile değiştirip benzer detay seviyesini koruyabilirsin.

Yorumlar & Soru-Cevap

(0)
Yorum yazmak için giriş yap.
Yorumlar yükleniyor...

Related Content