Uunan commited on
Commit
f0c7475
·
verified ·
1 Parent(s): a1217c4

Upload train.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. train.py +99 -0
train.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Train the tiny DeepSeek-V3-style (MLA + MoE) model on Turkish names.
2
+
3
+ Run: python train.py
4
+ """
5
+
6
+ import os
7
+
8
+ import torch
9
+
10
+ from config import ModelConfig
11
+ from model import TinyDeepSeek
12
+ from moe import MoE
13
+ from tokenizer import CharTokenizer
14
+
15
+ # ---------------------------------------------------------------------------
16
+ # Hyperparameters
17
+ # ---------------------------------------------------------------------------
18
+ DATA_FILE = os.path.join(os.path.dirname(__file__), "..", "data", "koyler.txt")
19
+ BATCH_SIZE = 64
20
+ BLOCK_SIZE = 32
21
+ STEPS = 8000 # sparse routing needs a little longer to settle than the dense models
22
+ LEARNING_RATE = 3e-3
23
+ EVAL_EVERY = 200
24
+ SEED = 1337
25
+
26
+ device = "cuda" if torch.cuda.is_available() else "cpu"
27
+ torch.manual_seed(SEED)
28
+
29
+ # ---------------------------------------------------------------------------
30
+ # Tokenizer + data
31
+ # ---------------------------------------------------------------------------
32
+ tokenizer = CharTokenizer.from_file(DATA_FILE)
33
+ vocab_size = tokenizer.vocab_size
34
+
35
+ text = open(DATA_FILE, encoding="utf-8").read()
36
+ data = torch.tensor(tokenizer.encode(text), dtype=torch.long)
37
+
38
+
39
+ def get_batch():
40
+ ix = torch.randint(len(data) - BLOCK_SIZE - 1, (BATCH_SIZE,))
41
+ x = torch.stack([data[i:i + BLOCK_SIZE] for i in ix])
42
+ y = torch.stack([data[i + 1:i + 1 + BLOCK_SIZE] for i in ix])
43
+ return x.to(device), y.to(device)
44
+
45
+
46
+ # ---------------------------------------------------------------------------
47
+ # Model. The MoE point in one line: total params > params active per token.
48
+ # ---------------------------------------------------------------------------
49
+ cfg = ModelConfig(vocab_size=vocab_size)
50
+ model = TinyDeepSeek(cfg).to(device)
51
+
52
+ n_params = sum(p.numel() for p in model.parameters())
53
+ expert_params = sum(p.numel() for layer in model.layers if isinstance(layer.mlp, MoE)
54
+ for p in layer.mlp.experts[0].parameters())
55
+ n_moe_layers = sum(isinstance(layer.mlp, MoE) for layer in model.layers)
56
+ per_expert = expert_params // max(n_moe_layers, 1)
57
+ n_active = n_params - per_expert * (cfg.n_routed_experts - cfg.top_k) * n_moe_layers
58
+ print(f"device={device} vocab_size={vocab_size} parameters={n_params:,} "
59
+ f"(active per token ~{n_active:,})")
60
+ print(f"layers: {['dense' if not isinstance(l.mlp, MoE) else 'moe' for l in model.layers]}")
61
+
62
+ optimizer = torch.optim.AdamW(model.parameters(), lr=LEARNING_RATE)
63
+
64
+
65
+ def sample_names(n: int = 10, max_new_tokens: int = 20):
66
+ model.eval()
67
+ start = torch.full((n, 1), tokenizer.newline_id, dtype=torch.long, device=device)
68
+ out = model.generate(start, max_new_tokens=max_new_tokens, temperature=1.0,
69
+ top_k=None, eos_id=tokenizer.eos_id)
70
+ model.train()
71
+ return [tokenizer.decode(row[1:]).split("\n")[0] for row in out.tolist()]
72
+
73
+
74
+ # ---------------------------------------------------------------------------
75
+ # Training loop
76
+ # ---------------------------------------------------------------------------
77
+ for step in range(1, STEPS + 1):
78
+ x, y = get_batch()
79
+ _, loss = model(x, y)
80
+ optimizer.zero_grad()
81
+ loss.backward()
82
+ optimizer.step()
83
+ if step % EVAL_EVERY == 0 or step == 1:
84
+ print(f"step {step:5d} loss {loss.item():.4f}")
85
+
86
+ # Show how evenly the load balancer spread tokens (ideal: ~0.25 per expert).
87
+ # `load` is recorded by each MoE during its last training forward pass.
88
+ for i, layer in enumerate(model.layers):
89
+ if isinstance(layer.mlp, MoE):
90
+ print(f"layer {i} expert load: {[round(v, 2) for v in layer.mlp.load.tolist()]}")
91
+
92
+ print("\nbaseline loss (uniform guessing): %.4f" % torch.log(torch.tensor(float(vocab_size))))
93
+ print("\nsample names:")
94
+ for name in sample_names(10):
95
+ print(" ", name)
96
+
97
+ torch.save({"model": model.state_dict(), "chars": tokenizer.chars, "cfg": cfg},
98
+ "tiny_deepseek_village.pt")
99
+ print("\nsaved checkpoint to tiny_deepseek_village.pt")