(cfg: dict)
| 176 | # ────────────────────────────────────────────────────────────────────────────── |
| 177 | |
| 178 | def train(cfg: dict) -> None: |
| 179 | torch.manual_seed(cfg["seed"]) |
| 180 | device = get_device() |
| 181 | print(f"Using device: {device}") |
| 182 | |
| 183 | # ── tokenizer ────────────────────────────────────────────────────────── |
| 184 | print("Loading tokenizer …") |
| 185 | tokenizer = AutoTokenizer.from_pretrained( |
| 186 | cfg["tokenizer_name"], |
| 187 | use_fast=True, |
| 188 | ) |
| 189 | if tokenizer.pad_token is None: |
| 190 | tokenizer.pad_token = tokenizer.eos_token |
| 191 | |
| 192 | # ── data ─────────────────────────────────────────────────────────────── |
| 193 | dataloader = build_dataloader(tokenizer, cfg) |
| 194 | |
| 195 | # ── model ────────────────────────────────────────────────────────────── |
| 196 | model = build_model(tokenizer, cfg) |
| 197 | model.to(device) |
| 198 | print(f"Parameters: {count_parameters(model):,}") |
| 199 | |
| 200 | # ── optimiser + schedule ─────────────────────────────────────────────── |
| 201 | # Do not apply weight decay to LayerNorm / bias parameters |
| 202 | decay_params = [p for n, p in model.named_parameters() if p.ndim >= 2] |
| 203 | nodecay_params = [p for n, p in model.named_parameters() if p.ndim < 2] |
| 204 | optim_groups = [ |
| 205 | {"params": decay_params, "weight_decay": cfg["weight_decay"]}, |
| 206 | {"params": nodecay_params, "weight_decay": 0.0}, |
| 207 | ] |
| 208 | optimizer = torch.optim.AdamW(optim_groups, lr=cfg["learning_rate"]) |
| 209 | scheduler = get_cosine_schedule_with_warmup( |
| 210 | optimizer, |
| 211 | num_warmup_steps=cfg["warmup_steps"], |
| 212 | num_training_steps=cfg["max_steps"], |
| 213 | ) |
| 214 | |
| 215 | # ── W&B (optional) ───────────────────────────────────────────────────── |
| 216 | if cfg["use_wandb"]: |
| 217 | import wandb |
| 218 | wandb.init(project=cfg["wandb_project"], name=cfg["run_name"], config=cfg) |
| 219 | |
| 220 | # ── checkpoint dir ───────────────────────────────────────────────────── |
| 221 | Path(cfg["checkpoint_dir"]).mkdir(parents=True, exist_ok=True) |
| 222 | |
| 223 | # ── training ─────────────────────────────────────────────────────────── |
| 224 | model.train() |
| 225 | step = 0 |
| 226 | optimizer.zero_grad() |
| 227 | autocast_ctx = get_autocast_ctx(device) |
| 228 | data_iter = iter(dataloader) |
| 229 | |
| 230 | print("Starting training …") |
| 231 | while step < cfg["max_steps"]: |
| 232 | # Gradient accumulation |
| 233 | accumulated_loss = 0.0 |
| 234 | for _ in range(cfg["gradient_accumulation_steps"]): |
| 235 | try: |
no test coverage detected