File size: 6,400 Bytes
7f1c419 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | """
ViuAI-1M Training Script.
End-to-end training pipeline:
1. Load or prepare data
2. Train BPE tokenizer on the corpus
3. Create datasets and dataloaders
4. Initialize model
5. Train with the ViuAI trainer
6. Save the final model and tokenizer
Usage:
python scripts/train.py
python scripts/train.py --epochs 20 --batch_size 16 --lr 1e-4
"""
import argparse
import os
import sys
import json
# Add project root to path
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, project_root)
import torch
from torch.utils.data import DataLoader
from viuai.model.config import ViuAIConfig
from viuai.model.viuai_model import ViuAIForCausalLM
from viuai.tokenizer.bpe_tokenizer import ViuAITokenizer
from viuai.training.dataset import ViuAIDataset, ChatDataCollator
from viuai.training.trainer import ViuAITrainer
def parse_args():
parser = argparse.ArgumentParser(description="Train ViuAI-1M")
parser.add_argument("--config", type=str, default="configs/viuai_1m.json",
help="Path to model config JSON")
parser.add_argument("--train_data", type=str, default="data/train.jsonl",
help="Path to training data JSONL")
parser.add_argument("--eval_data", type=str, default="data/eval.jsonl",
help="Path to evaluation data JSONL")
parser.add_argument("--tokenizer_corpus", type=str, default="data/tokenizer_corpus.txt",
help="Path to tokenizer training corpus")
parser.add_argument("--output_dir", type=str, default="output",
help="Output directory for checkpoints and tokenizer")
parser.add_argument("--epochs", type=int, default=10,
help="Number of training epochs")
parser.add_argument("--batch_size", type=int, default=32,
help="Training batch size")
parser.add_argument("--lr", type=float, default=3e-4,
help="Learning rate")
parser.add_argument("--warmup_steps", type=int, default=100,
help="Number of warmup steps")
parser.add_argument("--device", type=str, default=None,
help="Device (cuda/cpu/mps)")
return parser.parse_args()
def main():
args = parse_args()
print(f"\n{'='*60}")
print(f" ViuAI-1M Training Pipeline")
print(f"{'='*60}\n")
# ββ Step 1: Load Config ββββββββββββββββββββββββββββββββββββββ
print("[1/6] Loading configuration...")
config_path = os.path.join(project_root, args.config)
with open(config_path, "r") as f:
config_data = json.load(f)
config = ViuAIConfig(**config_data["architecture"])
print(f" Config: {config_path}")
print(f" Estimated parameters: {config.num_parameters:,}")
# ββ Step 2: Train Tokenizer ββββββββββββββββββββββββββββββββββ
print(f"\n[2/6] Training BPE tokenizer...")
tokenizer = ViuAITokenizer(vocab_size=config.vocab_size)
corpus_path = os.path.join(project_root, args.tokenizer_corpus)
if os.path.exists(corpus_path):
with open(corpus_path, "r", encoding="utf-8") as f:
corpus_texts = [line.strip() for line in f if line.strip()]
tokenizer.train(corpus_texts, verbose=True)
else:
print(f" WARNING: Corpus not found at {corpus_path}")
print(f" Run 'python scripts/prepare_data.py' first!")
return
# Update config vocab size to match actual tokenizer
config.vocab_size = tokenizer.vocab_size
# Save tokenizer
tokenizer_dir = os.path.join(project_root, args.output_dir, "tokenizer")
tokenizer.save(tokenizer_dir)
# ββ Step 3: Create Datasets ββββββββββββββββββββββββββββββββββ
print(f"\n[3/6] Creating datasets...")
train_path = os.path.join(project_root, args.train_data)
eval_path = os.path.join(project_root, args.eval_data)
train_dataset = ViuAIDataset(train_path, tokenizer, max_seq_len=config.max_seq_len)
eval_dataset = ViuAIDataset(eval_path, tokenizer, max_seq_len=config.max_seq_len)
collator = ChatDataCollator(pad_token_id=config.pad_token_id)
train_loader = DataLoader(
train_dataset,
batch_size=args.batch_size,
shuffle=True,
collate_fn=collator,
num_workers=0,
)
eval_loader = DataLoader(
eval_dataset,
batch_size=args.batch_size,
shuffle=False,
collate_fn=collator,
num_workers=0,
)
print(f" Train batches: {len(train_loader)}")
print(f" Eval batches: {len(eval_loader)}")
# ββ Step 4: Initialize Model βββββββββββββββββββββββββββββββββ
print(f"\n[4/6] Initializing ViuAI-1M model...")
model = ViuAIForCausalLM(config)
print(model.get_parameter_summary())
# ββ Step 5: Train ββββββββββββββββββββββββββββββββββββββββββββ
print(f"\n[5/6] Starting training...")
checkpoint_dir = os.path.join(project_root, args.output_dir, "checkpoints")
trainer = ViuAITrainer(
model=model,
train_dataloader=train_loader,
eval_dataloader=eval_loader,
learning_rate=args.lr,
weight_decay=0.01,
warmup_steps=args.warmup_steps,
num_epochs=args.epochs,
save_dir=checkpoint_dir,
log_interval=10,
eval_interval=50,
device=args.device,
)
metrics = trainer.train()
# ββ Step 6: Save Final Model βββββββββββββββββββββββββββββββββ
print(f"\n[6/6] Saving final model...")
final_dir = os.path.join(project_root, args.output_dir, "final")
os.makedirs(final_dir, exist_ok=True)
torch.save(model.state_dict(), os.path.join(final_dir, "model.pt"))
config.save(os.path.join(final_dir, "config.json"))
print(f" Model saved to: {final_dir}")
print(f"\n To chat with your model:")
print(f" python scripts/chat.py --checkpoint {final_dir} --tokenizer {tokenizer_dir}")
if __name__ == "__main__":
main()
|