Upload train/train_ounce100m.py with huggingface_hub
Browse files- train/train_ounce100m.py +40 -5
train/train_ounce100m.py
CHANGED
|
@@ -125,14 +125,26 @@ class HubPush(TrainerCallback):
|
|
| 125 |
"""
|
| 126 |
|
| 127 |
def __init__(self, repo, api, token, seq_len, seed, fingerprint, seqs_per_step,
|
| 128 |
-
prune=True, min_free_gb=6.0, repo_type="dataset"):
|
| 129 |
self.repo, self.api, self.token = repo, api, token
|
| 130 |
self.seq_len, self.seed, self.fingerprint = seq_len, seed, fingerprint
|
| 131 |
self.seqs_per_step, self.repo_type = seqs_per_step, repo_type
|
| 132 |
self.prune, self.min_free_gb = prune, min_free_gb
|
|
|
|
|
|
|
| 133 |
self.n = 0
|
| 134 |
self.results = []
|
| 135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
def on_save(self, args, state, control, **kw):
|
| 137 |
if not state.is_world_process_zero:
|
| 138 |
return control
|
|
@@ -257,6 +269,10 @@ def main():
|
|
| 257 |
ap.add_argument("--val-tokens", type=int, default=2_000_000)
|
| 258 |
ap.add_argument("--log-every", type=int, default=10)
|
| 259 |
ap.add_argument("--push-every-steps", type=int, default=0, help="0 = only at 10% boundaries")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
ap.add_argument("--prune", action="store_true", help="delete local checkpoint after hub verify")
|
| 261 |
ap.add_argument("--dry-run", action="store_true", help="build everything, train 0 steps")
|
| 262 |
ap.add_argument("--benchmark", type=int, default=0,
|
|
@@ -368,6 +384,14 @@ def main():
|
|
| 368 |
|
| 369 |
# 10 checkpoints per run is §2's cadence; --push-every-steps overrides for the preflight.
|
| 370 |
ckpt_every = args.push_every_steps or max(1, steps_planned // 10)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
|
| 372 |
api = None
|
| 373 |
if args.hub_repo:
|
|
@@ -420,10 +444,13 @@ def main():
|
|
| 420 |
"decay_start": int(steps_planned * args.decay_frac),
|
| 421 |
"total_steps": steps_planned},
|
| 422 |
)
|
|
|
|
| 423 |
if api is not None:
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
|
|
|
|
|
|
| 427 |
|
| 428 |
# Precision must be ASSERTED, not configured: bf16 "works" silently on Turing and fp32 master
|
| 429 |
# weights can be lost in a refactor (docs/00-platform-notes.md §8, memory/ERRORS.md E-006). The
|
|
@@ -494,7 +521,8 @@ def main():
|
|
| 494 |
say(f"validation loss={ev['eval_loss']:.4f} ppl={ppl:.2f} over {n_val} held-out windows")
|
| 495 |
except Exception as e:
|
| 496 |
say(f"validation eval failed: {type(e).__name__}: {str(e)[:200]}")
|
| 497 |
-
|
|
|
|
| 498 |
r = hubckpt.push_and_prune(args.hub_repo, out, "final", api, repo_type=args.hub_repo_type,
|
| 499 |
token=os.environ.get("HF_TOKEN"), prune=args.prune)
|
| 500 |
# .get, not [k]: `pruned` and `free_after_gb` are only present on some paths through
|
|
@@ -502,7 +530,14 @@ def main():
|
|
| 502 |
say("final push:", json.dumps({k: r.get(k) for k in
|
| 503 |
("verify", "pruned", "free_before_gb", "free_after_gb",
|
| 504 |
"prune_blocked_reason")}, default=str)[:900])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 505 |
say("RUN_JSON " + json.dumps({"final_step": step, "val_ppl": ppl, "tokens_consumed": consumed,
|
|
|
|
| 506 |
"tok_per_s": round(consumed_this_run / max(1, elapsed)),
|
| 507 |
"final_loss": final_loss, "prior_loss": prior,
|
| 508 |
"micro_batch": args.micro_batch, "seq_len": args.seq_len,
|
|
|
|
| 125 |
"""
|
| 126 |
|
| 127 |
def __init__(self, repo, api, token, seq_len, seed, fingerprint, seqs_per_step,
|
| 128 |
+
prune=True, min_free_gb=6.0, repo_type="dataset", stop_after_steps=0):
|
| 129 |
self.repo, self.api, self.token = repo, api, token
|
| 130 |
self.seq_len, self.seed, self.fingerprint = seq_len, seed, fingerprint
|
| 131 |
self.seqs_per_step, self.repo_type = seqs_per_step, repo_type
|
| 132 |
self.prune, self.min_free_gb = prune, min_free_gb
|
| 133 |
+
self.stop_after = int(stop_after_steps or 0)
|
| 134 |
+
self.stopped_at = None
|
| 135 |
self.n = 0
|
| 136 |
self.results = []
|
| 137 |
|
| 138 |
+
def on_step_end(self, args, state, control, **kw):
|
| 139 |
+
# A session that ends ON a verified checkpoint loses nothing when the platform takes the disk.
|
| 140 |
+
# That is how the 10 % cadence is made compatible with an unknown session cap: instead of pushing
|
| 141 |
+
# extra intermediate copies (which multiplies Hub LFS storage by the number of sessions), the run
|
| 142 |
+
# is cut into segments whose length is a whole number of checkpoint intervals.
|
| 143 |
+
if self.stop_after and state.global_step >= self.stop_after:
|
| 144 |
+
self.stopped_at = state.global_step
|
| 145 |
+
control.should_training_stop = True
|
| 146 |
+
return control
|
| 147 |
+
|
| 148 |
def on_save(self, args, state, control, **kw):
|
| 149 |
if not state.is_world_process_zero:
|
| 150 |
return control
|
|
|
|
| 269 |
ap.add_argument("--val-tokens", type=int, default=2_000_000)
|
| 270 |
ap.add_argument("--log-every", type=int, default=10)
|
| 271 |
ap.add_argument("--push-every-steps", type=int, default=0, help="0 = only at 10% boundaries")
|
| 272 |
+
ap.add_argument("--stop-after-steps", type=int, default=0,
|
| 273 |
+
help="absolute global step at which THIS session stops training, so it ends on a "
|
| 274 |
+
"verified checkpoint instead of being killed between two of them. Must be a "
|
| 275 |
+
"whole multiple of the checkpoint interval; 0 = run to the horizon.")
|
| 276 |
ap.add_argument("--prune", action="store_true", help="delete local checkpoint after hub verify")
|
| 277 |
ap.add_argument("--dry-run", action="store_true", help="build everything, train 0 steps")
|
| 278 |
ap.add_argument("--benchmark", type=int, default=0,
|
|
|
|
| 384 |
|
| 385 |
# 10 checkpoints per run is §2's cadence; --push-every-steps overrides for the preflight.
|
| 386 |
ckpt_every = args.push_every_steps or max(1, steps_planned // 10)
|
| 387 |
+
if args.stop_after_steps:
|
| 388 |
+
if args.stop_after_steps % ckpt_every:
|
| 389 |
+
raise SystemExit(f"--stop-after-steps {args.stop_after_steps} is not a whole multiple of the "
|
| 390 |
+
f"checkpoint interval {ckpt_every}: the session would end between two "
|
| 391 |
+
f"checkpoints, which is exactly what this flag exists to prevent")
|
| 392 |
+
if args.stop_after_steps > steps_planned:
|
| 393 |
+
raise SystemExit(f"--stop-after-steps {args.stop_after_steps} exceeds the horizon "
|
| 394 |
+
f"{steps_planned}; use 0 to run to the end")
|
| 395 |
|
| 396 |
api = None
|
| 397 |
if args.hub_repo:
|
|
|
|
| 444 |
"decay_start": int(steps_planned * args.decay_frac),
|
| 445 |
"total_steps": steps_planned},
|
| 446 |
)
|
| 447 |
+
hub_cb = None
|
| 448 |
if api is not None:
|
| 449 |
+
hub_cb = HubPush(args.hub_repo, api, os.environ.get("HF_TOKEN"), args.seq_len,
|
| 450 |
+
args.data_seed, fingerprint, seqs_per_step,
|
| 451 |
+
prune=args.prune, repo_type=args.hub_repo_type,
|
| 452 |
+
stop_after_steps=args.stop_after_steps)
|
| 453 |
+
tr.add_callback(hub_cb)
|
| 454 |
|
| 455 |
# Precision must be ASSERTED, not configured: bf16 "works" silently on Turing and fp32 master
|
| 456 |
# weights can be lost in a refactor (docs/00-platform-notes.md §8, memory/ERRORS.md E-006). The
|
|
|
|
| 521 |
say(f"validation loss={ev['eval_loss']:.4f} ppl={ppl:.2f} over {n_val} held-out windows")
|
| 522 |
except Exception as e:
|
| 523 |
say(f"validation eval failed: {type(e).__name__}: {str(e)[:200]}")
|
| 524 |
+
segment = bool(hub_cb and hub_cb.stopped_at and step < steps_planned)
|
| 525 |
+
if api is not None and not segment:
|
| 526 |
r = hubckpt.push_and_prune(args.hub_repo, out, "final", api, repo_type=args.hub_repo_type,
|
| 527 |
token=os.environ.get("HF_TOKEN"), prune=args.prune)
|
| 528 |
# .get, not [k]: `pruned` and `free_after_gb` are only present on some paths through
|
|
|
|
| 530 |
say("final push:", json.dumps({k: r.get(k) for k in
|
| 531 |
("verify", "pruned", "free_before_gb", "free_after_gb",
|
| 532 |
"prune_blocked_reason")}, default=str)[:900])
|
| 533 |
+
elif segment:
|
| 534 |
+
# The session stopped on a checkpoint interval, and HubPush already pushed AND verified that
|
| 535 |
+
# checkpoint and rolled latest.json to it. Re-pushing it as "final" would add a 1.7 GB LFS
|
| 536 |
+
# revision per session for a copy the Hub already holds.
|
| 537 |
+
say(f"segment boundary reached at step {step} of {steps_planned}: the checkpoint HubPush just "
|
| 538 |
+
"verified is the resume point, so no separate final push")
|
| 539 |
say("RUN_JSON " + json.dumps({"final_step": step, "val_ppl": ppl, "tokens_consumed": consumed,
|
| 540 |
+
"segment_stop": segment, "steps_planned": steps_planned,
|
| 541 |
"tok_per_s": round(consumed_this_run / max(1, elapsed)),
|
| 542 |
"final_loss": final_loss, "prior_loss": prior,
|
| 543 |
"micro_batch": args.micro_batch, "seq_len": args.seq_len,
|