LAMM / scripts /train.py
bastasie's picture
Rename train.py to scripts/train.py
27721b1 verified
Raw History Blame Contribute Delete
3.71 kB
import argparse, yaml, random, os, json, math
from pathlib import Path
def main():
ap=argparse.ArgumentParser()
ap.add_argument("--config",default="configs/lamm_tiny.yaml")
args=ap.parse_args()
cfg=yaml.safe_load(open(args.config))
try:
import torch
from lamm.model import LAMMModel
from lamm.data import stream_hf, batched, format_sft
from lamm.tokenizer import ByteTokenizer
except Exception as e:
raise SystemExit("Install training dependencies: pip install -e '.[train]'") from e
seed=cfg["seed"]
random.seed(seed); torch.manual_seed(seed)
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
tok=ByteTokenizer()
model=LAMMModel(
vocab_size=tok.vocab_size,
d_model=cfg["model"]["d_model"],
n_heads=cfg["model"]["n_heads"],
d_ff=cfg["model"]["d_ff"],
n_layers=cfg["model"]["n_layers"],
lam=cfg["model"]["state_lambda"],
).to(device)
opt=torch.optim.AdamW(
model.parameters(),
lr=cfg["training"]["learning_rate"],
weight_decay=cfg["training"]["weight_decay"]
)
out=Path(cfg["training"]["output_dir"])
out.mkdir(parents=True,exist_ok=True)
(out/"config.json").write_text(json.dumps(cfg,indent=2))
stream=stream_hf(
cfg["data"]["dataset"],
cfg["data"]["split"],
cfg["data"].get("source")
)
max_len=cfg["model"]["max_length"]
batch_size=cfg["training"]["batch_size"]
grad_acc=cfg["training"]["gradient_accumulation"]
max_steps=cfg["training"]["max_steps"]
ckpt_every=cfg["training"]["checkpoint_every"]
def make_batch(records):
seqs=[tok.encode(format_sft(r),max_len) for r in records]
L=max(len(x) for x in seqs)
L=min(L,max_len)
ids=torch.full((len(seqs),L),tok.PAD,dtype=torch.long)
labels=torch.full_like(ids,-100)
for i,s in enumerate(seqs):
s=s[:L]
ids[i,:len(s)]=torch.tensor(s)
# Prompt masking is approximated at the serialized boundary:
# train on the complete solution serialization while excluding PAD.
labels[i,:len(s)]=torch.tensor(s)
return ids.to(device), labels.to(device)
model.train()
running=0.0
step=0
seen=0
for batch in batched(stream,batch_size):
ids,labels=make_batch(batch)
outp=model(ids,labels)
loss=outp["loss"]/grad_acc
loss.backward()
running += float(loss.item())
seen += len(batch)
if (step+1)%grad_acc==0:
torch.nn.utils.clip_grad_norm_(model.parameters(),1.0)
opt.step(); opt.zero_grad(set_to_none=True)
step += 1
if step%25==0:
print(json.dumps({
"step":step,
"loss":running/max(1,min(25,step)),
"seen":seen,
"device":str(device)
}))
running=0.0
if step%ckpt_every==0:
ckpt=out/f"step-{step}.pt"
torch.save({
"model":model.state_dict(),
"optimizer":opt.state_dict(),
"step":step,
"seen":seen
},ckpt)
print("checkpoint",ckpt)
if step>=max_steps:
break
ckpt=out/"final.pt"
torch.save({
"model":model.state_dict(),
"optimizer":opt.state_dict(),
"step":step,
"seen":seen
},ckpt)
print(json.dumps({
"status":"TRAINING_COMPLETE",
"steps":step,
"samples_seen":seen,
"checkpoint":str(ckpt),
"device":str(device)
}))
if __name__=="__main__":
main()