Njap-png
Add Agron neural-network zoo, optimisers, algorithms, schedulers and unified trainer
a311e94 Download train_agron.py from teddyoas/Agron: direct link, hf CLI and curl.
- Browser
- Download file 6.04 kB
-
https://huggingface.co/teddyoas/Agron/resolve/main/train_agron.py
- Command line
-
hf download hf://teddyoas/Agron/train_agron.py
-
curl -L -o train_agron.py https://huggingface.co/teddyoas/Agron/resolve/main/train_agron.py
6.04 kB
| """Fine-tune the published Agron model (or any architecture) with the full zoo. | |
| Examples: | |
| python train_agron.py --steps 500 # continue the published LLaMA | |
| python train_agron.py --arch hybrid --recipe stable --steps 1000 | |
| python train_agron.py --arch mamba --optimizer muon --scheduler wsd \\ | |
| --algorithm gradient_clip --algorithm ema --steps 2000 | |
| python train_agron.py --engine hf --steps 500 # legacy HF Trainer | |
| """ | |
| import argparse | |
| import json | |
| import os | |
| import torch | |
| from transformers import ( | |
| DataCollatorForLanguageModeling, | |
| LlamaConfig, | |
| LlamaForCausalLM, | |
| PreTrainedTokenizerFast, | |
| Trainer, | |
| TrainingArguments, | |
| ) | |
| from agron_nets.training import add_training_args, build_model_from_args, trainer_from_args | |
| from agron_nets.utils import count_parameters, format_parameters | |
| from train_from_scratch import PRESETS, load_texts, make_loader, tokenize_dataset | |
| MODEL_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| TOKENIZER_FILE = os.path.join(MODEL_DIR, "tokenizer.json") | |
| OUTPUT_DIR = os.getenv("AGRON_OUTPUT_DIR", os.path.join(MODEL_DIR, "agron-model")) | |
| def build_tokenizer(): | |
| tok = PreTrainedTokenizerFast(tokenizer_file=TOKENIZER_FILE) | |
| tok.pad_token = "<pad>" | |
| tok.bos_token = "<s>" | |
| tok.eos_token = "</s>" | |
| tok.unk_token = "<unk>" | |
| tok.mask_token = "<mask>" | |
| return tok | |
| def build_published_model(): | |
| """The exact config/weights that were published to the Hub.""" | |
| cfg = LlamaConfig( | |
| vocab_size=16384, | |
| hidden_size=512, | |
| intermediate_size=2048, | |
| num_hidden_layers=8, | |
| num_attention_heads=4, | |
| num_key_value_heads=4, | |
| max_position_embeddings=512, | |
| bos_token_id=0, | |
| eos_token_id=2, | |
| pad_token_id=1, | |
| tie_word_embeddings=False, | |
| ) | |
| model = LlamaForCausalLM(cfg) | |
| weights = os.path.join(MODEL_DIR, "model.safetensors") | |
| if os.path.exists(weights): | |
| from safetensors.torch import load_file | |
| model.load_state_dict(load_file(weights)) | |
| print("Loaded published weights from", weights) | |
| return model | |
| def main(): | |
| ap = argparse.ArgumentParser(description="Continue training an Agron model.") | |
| ap.add_argument("--steps", type=int, default=500) | |
| ap.add_argument("--epochs", type=int, default=1) | |
| ap.add_argument("--dataset", choices=["wikitext", "file"], default="wikitext") | |
| ap.add_argument("--file", type=str, default=None) | |
| ap.add_argument("--output", type=str, default=OUTPUT_DIR) | |
| ap.add_argument("--block-size", type=int, default=512) | |
| ap.add_argument("--engine", choices=["agron", "hf"], default="agron") | |
| ap.add_argument("--init", choices=["published", "scratch"], default="published", | |
| help="start from the published LLaMA weights or fresh weights") | |
| ap.add_argument("--num-workers", type=int, default=2) | |
| add_training_args(ap) | |
| args = ap.parse_args() | |
| tok = build_tokenizer() | |
| arch = args.arch or "llama" | |
| if args.init == "published" and arch == "llama": | |
| model = build_published_model() | |
| config = model.config | |
| else: | |
| if args.init == "published": | |
| print(f"--init published is only meaningful for --arch llama; initialising {arch} from scratch") | |
| model, config = build_model_from_args(args, preset=PRESETS["current"]) | |
| print(f"Model: {config.model_type} | {format_parameters(count_parameters(model))} params") | |
| train_texts, eval_texts = load_texts(args) | |
| train_ds = tokenize_dataset(tok, train_texts, block_size=args.block_size) | |
| eval_ds = tokenize_dataset(tok, eval_texts, block_size=args.block_size) if eval_texts else None | |
| print(f"Training chunks: {len(train_ds):,}") | |
| out_dir = args.output | |
| os.makedirs(out_dir, exist_ok=True) | |
| if args.engine == "hf": | |
| if config.model_type != "llama": | |
| raise SystemExit("--engine hf only supports the llama architecture; use --engine agron") | |
| ta = TrainingArguments( | |
| output_dir=out_dir, | |
| per_device_train_batch_size=args.batch_size, | |
| num_train_epochs=args.epochs, | |
| max_steps=args.steps, | |
| learning_rate=args.lr if args.lr is not None else 5e-05, | |
| lr_scheduler_type="linear", | |
| warmup_steps=args.warmup, | |
| optim="adamw_torch_fused", | |
| weight_decay=args.weight_decay if args.weight_decay is not None else 0.0, | |
| fp16=True if torch.cuda.is_available() else False, | |
| gradient_accumulation_steps=args.grad_accum, | |
| max_grad_norm=args.grad_clip or 0.0, | |
| logging_steps=max(1, args.log_every), | |
| logging_strategy="steps", | |
| save_strategy="steps", | |
| save_steps=max(100, args.steps // 2), | |
| save_total_limit=2, | |
| dataloader_num_workers=args.num_workers, | |
| remove_unused_columns=True, | |
| report_to=[], | |
| seed=args.seed, | |
| do_train=True, | |
| ) | |
| collator = DataCollatorForLanguageModeling(tokenizer=tok, mlm=False) | |
| trainer = Trainer(model=model, args=ta, train_dataset=train_ds, data_collator=collator, | |
| processing_class=tok) | |
| trainer.train() | |
| else: | |
| trainer = trainer_from_args(args, model, output_dir=out_dir) | |
| report = trainer.fit( | |
| make_loader(train_ds, tok, batch_size=args.batch_size, num_workers=args.num_workers), | |
| eval_dataloader=( | |
| make_loader(eval_ds, tok, batch_size=args.batch_size, shuffle=False, | |
| num_workers=args.num_workers) | |
| if eval_ds is not None else None | |
| ), | |
| ) | |
| print(json.dumps({k: v for k, v in report.items() if k != "history"}, indent=2, default=str)) | |
| final_dir = os.path.join(out_dir, "final") | |
| os.makedirs(final_dir, exist_ok=True) | |
| model.save_pretrained(final_dir) | |
| tok.save_pretrained(final_dir) | |
| print("Training complete. Final model saved to", final_dir) | |
| if __name__ == "__main__": | |
| main() | |