Merge branch 'master' into fix/typo
This commit is contained in:
@@ -18,6 +18,7 @@ Presently, the main focus of development is on tuning the pretraining stage, whi
|
|||||||
| 2 | 2.91 | 0.74504 | 0.2578 | d26 slightly undertrained **+fp8** | Feb 2 2026 | a67eba3 | @karpathy |
|
| 2 | 2.91 | 0.74504 | 0.2578 | d26 slightly undertrained **+fp8** | Feb 2 2026 | a67eba3 | @karpathy |
|
||||||
| 3 | 2.76 | 0.74645 | 0.2602 | bump total batch size to 1M tokens | Feb 5 2026 | 2c062aa | @karpathy |
|
| 3 | 2.76 | 0.74645 | 0.2602 | bump total batch size to 1M tokens | Feb 5 2026 | 2c062aa | @karpathy |
|
||||||
| 4 | 2.02 | 0.71854 | 0.2571 | change dataset to NVIDIA ClimbMix | Mar 4 2026 | 324e69c | @ddudek @karpathy |
|
| 4 | 2.02 | 0.71854 | 0.2571 | change dataset to NVIDIA ClimbMix | Mar 4 2026 | 324e69c | @ddudek @karpathy |
|
||||||
|
| 5 | 1.80 | 0.71808 | 0.2690 | autoresearch [round 1](https://x.com/karpathy/status/2031135152349524125) | Mar 9 2026 | 6ed7d1d | @karpathy |
|
||||||
|
|
||||||
The primary metric we care about is "time to GPT-2" - the wall clock time needed to outperform the GPT-2 (1.6B) CORE metric on an 8XH100 GPU node. The GPT-2 CORE score is 0.256525. In 2019, the training of GPT-2 cost approximately $43,000 so it is incredible that due to many advances over 7 years across the stack, we can now do so much faster and for well below $100 (e.g. at the current ~$3/GPU/hr, an 8XH100 node is ~$24/hr, so 2 hours is ~$48).
|
The primary metric we care about is "time to GPT-2" - the wall clock time needed to outperform the GPT-2 (1.6B) CORE metric on an 8XH100 GPU node. The GPT-2 CORE score is 0.256525. In 2019, the training of GPT-2 cost approximately $43,000 so it is incredible that due to many advances over 7 years across the stack, we can now do so much faster and for well below $100 (e.g. at the current ~$3/GPU/hr, an 8XH100 node is ~$24/hr, so 2 hours is ~$48).
|
||||||
|
|
||||||
|
|||||||
@@ -191,3 +191,8 @@ Mean is 0.25714 (higher than the GPT-2 threshold needed), max-min is 0.01646. So
|
|||||||
|
|
||||||
NOTE: The `val_bpb` is as of this run *NOT* comparable due to the data distribution change to the previous 3 runs. This run happens to be at `0.71854` validation bpb. If the dataset is not changed, the `val_bpb` number is a great, smooth metric to track relative performance w.r.t. and has less noise than CORE.
|
NOTE: The `val_bpb` is as of this run *NOT* comparable due to the data distribution change to the previous 3 runs. This run happens to be at `0.71854` validation bpb. If the dataset is not changed, the `val_bpb` number is a great, smooth metric to track relative performance w.r.t. and has less noise than CORE.
|
||||||
|
|
||||||
|
## Run 5
|
||||||
|
|
||||||
|
Achieved Mar 9, 2026 on commit `6ed7d1d`. Exactly the same launch command as Run 4 except `--target-param-data-ratio=8.7`. I ran 5 identical runs, the average CORE was 0.2690, which is quite a bit above the needed threshold of 0.2565. But the reason I didn't decrease the ratio further (i.e. train shorter) is that while the CORE "safety gap" is large, the val_loss safety gap is smaller - 0.71808, which we want to be below the Run 4 val loss of 0.71854. It's likely that we could have reduced the ratio even lower, possibly to 8.6, but it's not worth splitting hairs at this point.
|
||||||
|
|
||||||
|
This commit is special because all of the improvements that went into [this commit](https://github.com/karpathy/nanochat/commit/6ed7d1d82cee16c2e26f45d559ad3338447a6c1b) came from fully autonomous "research" done by a private version of [autoresearch](https://github.com/karpathy/autoresearch) run on a d12 model. I wrote more about this in [this tweet](https://x.com/karpathy/status/2031135152349524125). The changes easily translated from d12 to d24, hence new leaderboard record, taking us from 2.02 hours "time to GPT-2" to 1.80 hours.
|
||||||
|
|||||||
+17
-15
@@ -76,7 +76,7 @@ class CausalSelfAttention(nn.Module):
|
|||||||
self.c_k = Linear(self.n_embd, self.n_kv_head * self.head_dim, bias=False)
|
self.c_k = Linear(self.n_embd, self.n_kv_head * self.head_dim, bias=False)
|
||||||
self.c_v = Linear(self.n_embd, self.n_kv_head * self.head_dim, bias=False)
|
self.c_v = Linear(self.n_embd, self.n_kv_head * self.head_dim, bias=False)
|
||||||
self.c_proj = Linear(self.n_embd, self.n_embd, bias=False)
|
self.c_proj = Linear(self.n_embd, self.n_embd, bias=False)
|
||||||
self.ve_gate_channels = 32
|
self.ve_gate_channels = 12
|
||||||
self.ve_gate = Linear(self.ve_gate_channels, self.n_kv_head, bias=False) if has_ve(layer_idx, config.n_layer) else None
|
self.ve_gate = Linear(self.ve_gate_channels, self.n_kv_head, bias=False) if has_ve(layer_idx, config.n_layer) else None
|
||||||
|
|
||||||
def forward(self, x, ve, cos_sin, window_size, kv_cache):
|
def forward(self, x, ve, cos_sin, window_size, kv_cache):
|
||||||
@@ -91,13 +91,15 @@ class CausalSelfAttention(nn.Module):
|
|||||||
# Value residual (ResFormer): mix in value embedding with input-dependent gate per head
|
# Value residual (ResFormer): mix in value embedding with input-dependent gate per head
|
||||||
if ve is not None:
|
if ve is not None:
|
||||||
ve = ve.view(B, T, self.n_kv_head, self.head_dim)
|
ve = ve.view(B, T, self.n_kv_head, self.head_dim)
|
||||||
gate = 2 * torch.sigmoid(self.ve_gate(x[..., :self.ve_gate_channels])) # (B, T, n_kv_head), range (0, 2)
|
gate = 3 * torch.sigmoid(self.ve_gate(x[..., :self.ve_gate_channels])) # (B, T, n_kv_head), range (0, 3)
|
||||||
v = v + gate.unsqueeze(-1) * ve
|
v = v + gate.unsqueeze(-1) * ve
|
||||||
|
|
||||||
# Apply Rotary Embeddings to queries and keys to get relative positional encoding
|
# Apply Rotary Embeddings to queries and keys to get relative positional encoding
|
||||||
cos, sin = cos_sin
|
cos, sin = cos_sin
|
||||||
q, k = apply_rotary_emb(q, cos, sin), apply_rotary_emb(k, cos, sin)
|
q, k = apply_rotary_emb(q, cos, sin), apply_rotary_emb(k, cos, sin)
|
||||||
q, k = norm(q), norm(k) # QK norm
|
q, k = norm(q), norm(k) # QK norm
|
||||||
|
q = q * 1.15 # sharper attention (split scale between Q and K), TODO think through better
|
||||||
|
k = k * 1.15
|
||||||
|
|
||||||
# Flash Attention (FA3 on Hopper+, PyTorch SDPA fallback elsewhere)
|
# Flash Attention (FA3 on Hopper+, PyTorch SDPA fallback elsewhere)
|
||||||
# window_size is (left, right) tuple: (N, 0) for causal, (-1, 0) for full context
|
# window_size is (left, right) tuple: (N, 0) for causal, (-1, 0) for full context
|
||||||
@@ -208,7 +210,7 @@ class GPT(nn.Module):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Embedding and unembedding
|
# Embedding and unembedding
|
||||||
torch.nn.init.normal_(self.transformer.wte.weight, mean=0.0, std=1.0)
|
torch.nn.init.normal_(self.transformer.wte.weight, mean=0.0, std=0.8)
|
||||||
torch.nn.init.normal_(self.lm_head.weight, mean=0.0, std=0.001)
|
torch.nn.init.normal_(self.lm_head.weight, mean=0.0, std=0.001)
|
||||||
|
|
||||||
# Transformer blocks: uniform init with bound = sqrt(3) * std (same standard deviation as normal)
|
# Transformer blocks: uniform init with bound = sqrt(3) * std (same standard deviation as normal)
|
||||||
@@ -219,7 +221,7 @@ class GPT(nn.Module):
|
|||||||
torch.nn.init.uniform_(block.attn.c_k.weight, -s, s)
|
torch.nn.init.uniform_(block.attn.c_k.weight, -s, s)
|
||||||
torch.nn.init.uniform_(block.attn.c_v.weight, -s, s)
|
torch.nn.init.uniform_(block.attn.c_v.weight, -s, s)
|
||||||
torch.nn.init.zeros_(block.attn.c_proj.weight) # projections are zero
|
torch.nn.init.zeros_(block.attn.c_proj.weight) # projections are zero
|
||||||
torch.nn.init.uniform_(block.mlp.c_fc.weight, -s, s)
|
torch.nn.init.uniform_(block.mlp.c_fc.weight, -s * 0.5, s * 0.5) # 0.5x init scale for c_fc
|
||||||
torch.nn.init.zeros_(block.mlp.c_proj.weight)
|
torch.nn.init.zeros_(block.mlp.c_proj.weight)
|
||||||
|
|
||||||
# Per-layer scalars
|
# Per-layer scalars
|
||||||
@@ -230,10 +232,10 @@ class GPT(nn.Module):
|
|||||||
for ve in self.value_embeds.values():
|
for ve in self.value_embeds.values():
|
||||||
torch.nn.init.uniform_(ve.weight, -s, s)
|
torch.nn.init.uniform_(ve.weight, -s, s)
|
||||||
|
|
||||||
# Gate weights init to zero so gates start at sigmoid(0) = 0.5, scaled by 2 -> 1.0 (neutral)
|
# Gate weights init with small positive values so gates start slightly above neutral
|
||||||
for block in self.transformer.h:
|
for block in self.transformer.h:
|
||||||
if block.attn.ve_gate is not None:
|
if block.attn.ve_gate is not None:
|
||||||
torch.nn.init.zeros_(block.attn.ve_gate.weight)
|
torch.nn.init.uniform_(block.attn.ve_gate.weight, 0.0, 0.02)
|
||||||
|
|
||||||
# Rotary embeddings
|
# Rotary embeddings
|
||||||
head_dim = self.config.n_embd // self.config.n_head
|
head_dim = self.config.n_embd // self.config.n_head
|
||||||
@@ -248,7 +250,7 @@ class GPT(nn.Module):
|
|||||||
for ve in self.value_embeds.values():
|
for ve in self.value_embeds.values():
|
||||||
ve.to(dtype=COMPUTE_DTYPE)
|
ve.to(dtype=COMPUTE_DTYPE)
|
||||||
|
|
||||||
def _precompute_rotary_embeddings(self, seq_len, head_dim, base=10000, device=None):
|
def _precompute_rotary_embeddings(self, seq_len, head_dim, base=100000, device=None):
|
||||||
# TODO: bump base theta more? e.g. 100K is more common more recently
|
# TODO: bump base theta more? e.g. 100K is more common more recently
|
||||||
# autodetect the device from model embeddings
|
# autodetect the device from model embeddings
|
||||||
if device is None:
|
if device is None:
|
||||||
@@ -280,7 +282,7 @@ class GPT(nn.Module):
|
|||||||
assert all(c in "SL" for c in pattern), f"Invalid window_pattern: {pattern}. Use only S and L."
|
assert all(c in "SL" for c in pattern), f"Invalid window_pattern: {pattern}. Use only S and L."
|
||||||
# Map characters to window sizes
|
# Map characters to window sizes
|
||||||
long_window = config.sequence_len
|
long_window = config.sequence_len
|
||||||
short_window = long_window // 2
|
short_window = -(-long_window // 3 // 128) * 128 # ceil to FA3 tile size (2048 -> 768)
|
||||||
char_to_window = {
|
char_to_window = {
|
||||||
"L": (long_window, 0),
|
"L": (long_window, 0),
|
||||||
"S": (short_window, 0),
|
"S": (short_window, 0),
|
||||||
@@ -353,7 +355,7 @@ class GPT(nn.Module):
|
|||||||
'total': total,
|
'total': total,
|
||||||
}
|
}
|
||||||
|
|
||||||
def setup_optimizer(self, unembedding_lr=0.004, embedding_lr=0.2, matrix_lr=0.02, weight_decay=0.0, adam_betas=(0.8, 0.95), scalar_lr=0.5):
|
def setup_optimizer(self, unembedding_lr=0.004, embedding_lr=0.2, matrix_lr=0.02, weight_decay=0.0, scalar_lr=0.5):
|
||||||
model_dim = self.config.n_embd
|
model_dim = self.config.n_embd
|
||||||
ddp, rank, local_rank, world_size = get_dist_info()
|
ddp, rank, local_rank, world_size = get_dist_info()
|
||||||
|
|
||||||
@@ -373,10 +375,10 @@ class GPT(nn.Module):
|
|||||||
# Build param_groups with all required fields explicit
|
# Build param_groups with all required fields explicit
|
||||||
param_groups = [
|
param_groups = [
|
||||||
# AdamW groups (embeddings, lm_head, scalars)
|
# AdamW groups (embeddings, lm_head, scalars)
|
||||||
dict(kind='adamw', params=lm_head_params, lr=unembedding_lr * dmodel_lr_scale, betas=adam_betas, eps=1e-10, weight_decay=0.0),
|
dict(kind='adamw', params=lm_head_params, lr=unembedding_lr * dmodel_lr_scale, betas=(0.8, 0.96), eps=1e-10, weight_decay=0.01),
|
||||||
dict(kind='adamw', params=embedding_params, lr=embedding_lr * dmodel_lr_scale, betas=adam_betas, eps=1e-10, weight_decay=0.0),
|
dict(kind='adamw', params=embedding_params, lr=embedding_lr * dmodel_lr_scale, betas=(0.8, 0.995), eps=1e-10, weight_decay=0.001),
|
||||||
dict(kind='adamw', params=value_embeds_params, lr=embedding_lr * dmodel_lr_scale, betas=adam_betas, eps=1e-10, weight_decay=0.0),
|
dict(kind='adamw', params=value_embeds_params, lr=embedding_lr * dmodel_lr_scale * 0.5, betas=(0.8, 0.995), eps=1e-10, weight_decay=0.01),
|
||||||
dict(kind='adamw', params=resid_params, lr=scalar_lr * 0.01, betas=adam_betas, eps=1e-10, weight_decay=0.0),
|
dict(kind='adamw', params=resid_params, lr=scalar_lr * 0.01, betas=(0.8, 0.95), eps=1e-10, weight_decay=0.05),
|
||||||
dict(kind='adamw', params=x0_params, lr=scalar_lr, betas=(0.96, 0.95), eps=1e-10, weight_decay=0.0), # higher beta1 for x0
|
dict(kind='adamw', params=x0_params, lr=scalar_lr, betas=(0.96, 0.95), eps=1e-10, weight_decay=0.0), # higher beta1 for x0
|
||||||
]
|
]
|
||||||
# Muon groups (matrix params, grouped by shape for stacking)
|
# Muon groups (matrix params, grouped by shape for stacking)
|
||||||
@@ -384,7 +386,7 @@ class GPT(nn.Module):
|
|||||||
group_params = [p for p in matrix_params if p.shape == shape]
|
group_params = [p for p in matrix_params if p.shape == shape]
|
||||||
param_groups.append(dict(
|
param_groups.append(dict(
|
||||||
kind='muon', params=group_params, lr=matrix_lr,
|
kind='muon', params=group_params, lr=matrix_lr,
|
||||||
momentum=0.95, ns_steps=5, beta2=0.95, weight_decay=weight_decay,
|
momentum=0.95, ns_steps=5, beta2=0.9, weight_decay=weight_decay,
|
||||||
))
|
))
|
||||||
|
|
||||||
Factory = DistMuonAdamW if ddp else MuonAdamW
|
Factory = DistMuonAdamW if ddp else MuonAdamW
|
||||||
@@ -416,7 +418,7 @@ class GPT(nn.Module):
|
|||||||
x = norm(x)
|
x = norm(x)
|
||||||
|
|
||||||
# Forward the lm_head (compute logits)
|
# Forward the lm_head (compute logits)
|
||||||
softcap = 20 # smoothly cap the logits to the range [-softcap, softcap]
|
softcap = 15 # smoothly cap the logits to the range [-softcap, softcap]
|
||||||
logits = self.lm_head(x) # (B, T, padded_vocab_size) <- very big tensor, large amount of memory
|
logits = self.lm_head(x) # (B, T, padded_vocab_size) <- very big tensor, large amount of memory
|
||||||
logits = logits[..., :self.config.vocab_size] # slice to remove padding
|
logits = logits[..., :self.config.vocab_size] # slice to remove padding
|
||||||
logits = logits.float() # switch to fp32 for logit softcap and loss computation
|
logits = logits.float() # switch to fp32 for logit softcap and loss computation
|
||||||
|
|||||||
+1
-1
@@ -113,7 +113,7 @@ def muon_step_fused(
|
|||||||
|
|
||||||
# Polar express
|
# Polar express
|
||||||
X = g.bfloat16()
|
X = g.bfloat16()
|
||||||
X = X / (X.norm(dim=(-2, -1), keepdim=True) * 1.02 + 1e-6)
|
X = X / (X.norm(dim=(-2, -1), keepdim=True) * 1.01 + 1e-6)
|
||||||
if g.size(-2) > g.size(-1): # Tall matrix
|
if g.size(-2) > g.size(-1): # Tall matrix
|
||||||
for a, b, c in polar_express_coeffs[:ns_steps]:
|
for a, b, c in polar_express_coeffs[:ns_steps]:
|
||||||
A = X.mT @ X
|
A = X.mT @ X
|
||||||
|
|||||||
+12
-15
@@ -60,15 +60,13 @@ parser.add_argument("--target-param-data-ratio", type=float, default=10.5, help=
|
|||||||
parser.add_argument("--device-batch-size", type=int, default=32, help="per-device batch size. good number to reduce to 16,8,4,... if you OOM on VRAM.")
|
parser.add_argument("--device-batch-size", type=int, default=32, help="per-device batch size. good number to reduce to 16,8,4,... if you OOM on VRAM.")
|
||||||
parser.add_argument("--total-batch-size", type=int, default=-1, help="total batch size in tokens. decent numbers are e.g. 524288. (-1 = auto-compute optimal)")
|
parser.add_argument("--total-batch-size", type=int, default=-1, help="total batch size in tokens. decent numbers are e.g. 524288. (-1 = auto-compute optimal)")
|
||||||
parser.add_argument("--embedding-lr", type=float, default=0.3, help="learning rate for embedding parameters (Adam)")
|
parser.add_argument("--embedding-lr", type=float, default=0.3, help="learning rate for embedding parameters (Adam)")
|
||||||
parser.add_argument("--unembedding-lr", type=float, default=0.004, help="learning rate for unembedding parameters (Adam)")
|
parser.add_argument("--unembedding-lr", type=float, default=0.008, help="learning rate for unembedding parameters (Adam)")
|
||||||
parser.add_argument("--weight-decay", type=float, default=0.2, help="cautious weight decay for the Muon optimizer (for weights)")
|
parser.add_argument("--weight-decay", type=float, default=0.28, help="cautious weight decay for the Muon optimizer (for weights)")
|
||||||
parser.add_argument("--matrix-lr", type=float, default=0.02, help="learning rate for matrix parameters (Muon)")
|
parser.add_argument("--matrix-lr", type=float, default=0.02, help="learning rate for matrix parameters (Muon)")
|
||||||
parser.add_argument("--scalar-lr", type=float, default=0.5, help="learning rate for scalars (resid_lambdas, x0_lambdas)")
|
parser.add_argument("--scalar-lr", type=float, default=0.5, help="learning rate for scalars (resid_lambdas, x0_lambdas)")
|
||||||
parser.add_argument("--adam-beta1", type=float, default=0.8, help="Adam beta1 for embedding/unembedding")
|
parser.add_argument("--warmup-steps", type=int, default=40, help="number of steps for LR warmup")
|
||||||
parser.add_argument("--adam-beta2", type=float, default=0.95, help="Adam beta2 for embedding/unembedding")
|
parser.add_argument("--warmdown-ratio", type=float, default=0.65, help="ratio of iterations for LR warmdown")
|
||||||
parser.add_argument("--warmup-ratio", type=float, default=0.0, help="ratio of iterations for LR warmup")
|
parser.add_argument("--final-lr-frac", type=float, default=0.05, help="final LR as fraction of initial LR")
|
||||||
parser.add_argument("--warmdown-ratio", type=float, default=0.5, help="ratio of iterations for LR warmdown")
|
|
||||||
parser.add_argument("--final-lr-frac", type=float, default=0.0, help="final LR as fraction of initial LR")
|
|
||||||
parser.add_argument("--resume-from-step", type=int, default=-1, help="resume training from this step (-1 = disable)")
|
parser.add_argument("--resume-from-step", type=int, default=-1, help="resume training from this step (-1 = disable)")
|
||||||
# Evaluation
|
# Evaluation
|
||||||
parser.add_argument("--eval-every", type=int, default=250, help="evaluate val bpb every N steps (-1 = disable)")
|
parser.add_argument("--eval-every", type=int, default=250, help="evaluate val bpb every N steps (-1 = disable)")
|
||||||
@@ -311,7 +309,6 @@ optimizer = model.setup_optimizer(
|
|||||||
unembedding_lr=args.unembedding_lr * batch_lr_scale,
|
unembedding_lr=args.unembedding_lr * batch_lr_scale,
|
||||||
embedding_lr=args.embedding_lr * batch_lr_scale,
|
embedding_lr=args.embedding_lr * batch_lr_scale,
|
||||||
scalar_lr=args.scalar_lr * batch_lr_scale,
|
scalar_lr=args.scalar_lr * batch_lr_scale,
|
||||||
adam_betas=(args.adam_beta1, args.adam_beta2),
|
|
||||||
# Muon hyperparameters
|
# Muon hyperparameters
|
||||||
matrix_lr=args.matrix_lr * batch_lr_scale,
|
matrix_lr=args.matrix_lr * batch_lr_scale,
|
||||||
weight_decay=weight_decay_scaled,
|
weight_decay=weight_decay_scaled,
|
||||||
@@ -360,7 +357,7 @@ print0(f"Total training FLOPs estimate: {num_flops_per_token * total_tokens:e}")
|
|||||||
|
|
||||||
# Learning rate schedule (linear warmup, constant, linear warmdown)
|
# Learning rate schedule (linear warmup, constant, linear warmdown)
|
||||||
def get_lr_multiplier(it):
|
def get_lr_multiplier(it):
|
||||||
warmup_iters = round(args.warmup_ratio * num_iterations)
|
warmup_iters = args.warmup_steps
|
||||||
warmdown_iters = round(args.warmdown_ratio * num_iterations)
|
warmdown_iters = round(args.warmdown_ratio * num_iterations)
|
||||||
if it < warmup_iters:
|
if it < warmup_iters:
|
||||||
return (it + 1) / warmup_iters
|
return (it + 1) / warmup_iters
|
||||||
@@ -370,15 +367,15 @@ def get_lr_multiplier(it):
|
|||||||
progress = (num_iterations - it) / warmdown_iters
|
progress = (num_iterations - it) / warmdown_iters
|
||||||
return progress * 1.0 + (1 - progress) * args.final_lr_frac
|
return progress * 1.0 + (1 - progress) * args.final_lr_frac
|
||||||
|
|
||||||
# Momentum scheduler for Muon optimizer (warms up to 0.95 over the first 300 steps)
|
# Momentum scheduler for Muon optimizer (warms up to 0.97 over the first 400 steps)
|
||||||
def get_muon_momentum(it):
|
def get_muon_momentum(it):
|
||||||
frac = min(it / 300, 1)
|
frac = min(it / 400, 1)
|
||||||
momentum = (1 - frac) * 0.85 + frac * 0.95
|
momentum = (1 - frac) * 0.85 + frac * 0.97
|
||||||
return momentum
|
return momentum
|
||||||
|
|
||||||
# Weight decay scheduler for Muon optimizer (linearly decays to zero over the course of training)
|
# Weight decay scheduler for Muon optimizer (cosine decay to zero over the course of training)
|
||||||
def get_weight_decay(it):
|
def get_weight_decay(it):
|
||||||
return weight_decay_scaled * (1 - it / num_iterations)
|
return weight_decay_scaled * 0.5 * (1 + math.cos(math.pi * it / num_iterations))
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Training loop
|
# Training loop
|
||||||
@@ -605,7 +602,7 @@ get_report().log(section="Base model training", data=[
|
|||||||
"Number of training tokens": total_tokens,
|
"Number of training tokens": total_tokens,
|
||||||
"Tokens : Scaling params ratio": total_batch_size * num_iterations / num_scaling_params,
|
"Tokens : Scaling params ratio": total_batch_size * num_iterations / num_scaling_params,
|
||||||
"DDP world size": ddp_world_size,
|
"DDP world size": ddp_world_size,
|
||||||
"warmup_ratio": args.warmup_ratio,
|
"warmup_steps": args.warmup_steps,
|
||||||
"warmdown_ratio": args.warmdown_ratio,
|
"warmdown_ratio": args.warmdown_ratio,
|
||||||
"final_lr_frac": args.final_lr_frac,
|
"final_lr_frac": args.final_lr_frac,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user