adyoi commited on
Commit
068c6b9
·
verified ·
1 Parent(s): c7c5a39

Delete train_tf.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. train_tf.py +0 -197
train_tf.py DELETED
@@ -1,197 +0,0 @@
1
- import argparse
2
- import math
3
- import os
4
- import random
5
- import time
6
-
7
- import numpy as np
8
- import tensorflow as tf
9
- from safetensors.numpy import load_file, save_file
10
-
11
- from indigo.common import collect_text_files, load_meta, read_clean, save_meta
12
- from indigo.model_keras import build_gpt
13
- from indigo.tokenizer import CharTokenizer
14
-
15
- CONFIG_KEYS = ("vocab_size", "block_size", "n_layer", "n_head", "n_embd", "dropout")
16
-
17
-
18
- def get_batch(np_data, block_size, batch_size):
19
- ix = np.random.randint(0, len(np_data) - block_size - 1, size=batch_size)
20
- x = np.stack([np_data[i : i + block_size] for i in ix])
21
- y = np.stack([np_data[i + 1 : i + block_size + 1] for i in ix])
22
- return tf.constant(x), tf.constant(y)
23
-
24
-
25
- @tf.function(reduce_retracing=True)
26
- def train_step(model, optimizer, loss_fn, x, y):
27
- with tf.GradientTape() as tape:
28
- logits = model(x, training=True)
29
- loss = loss_fn(y, logits)
30
- grads = tape.gradient(loss, model.trainable_variables)
31
- optimizer.apply_gradients(zip(grads, model.trainable_variables))
32
- return loss
33
-
34
-
35
- @tf.function(reduce_retracing=True)
36
- def eval_step(model, loss_fn, x, y):
37
- logits = model(x, training=False)
38
- return loss_fn(y, logits)
39
-
40
-
41
- @tf.function(reduce_retracing=True)
42
- def forward_last(model, x):
43
- return model(x, training=False)[:, -1, :]
44
-
45
-
46
- def save_weights_tf(model, base_path, config, vocab, step, val_loss):
47
- tensors = {v.path: np.asarray(v) for v in model.weights}
48
- save_file(tensors, base_path)
49
- save_meta(base_path, config, vocab, step, val_loss, backend="tensorflow")
50
-
51
-
52
- def main():
53
- parser = argparse.ArgumentParser(description="Latih model Indigo (backend TensorFlow/Keras)")
54
- parser.add_argument("--data", nargs="+", default=["data/sample.txt"])
55
- parser.add_argument("--out", default="out_tf")
56
- parser.add_argument("--steps", type=int, default=2000)
57
- parser.add_argument("--batch-size", type=int, default=32)
58
- parser.add_argument("--block-size", type=int, default=128)
59
- parser.add_argument("--n-layer", type=int, default=4)
60
- parser.add_argument("--n-head", type=int, default=4)
61
- parser.add_argument("--n-embd", type=int, default=128)
62
- parser.add_argument("--dropout", type=float, default=0.1)
63
- parser.add_argument("--lr", type=float, default=3e-4)
64
- parser.add_argument("--warmup", type=int, default=100)
65
- parser.add_argument("--weight-decay", type=float, default=0.1)
66
- parser.add_argument("--eval-interval", type=int, default=200)
67
- parser.add_argument("--eval-iters", type=int, default=20)
68
- parser.add_argument("--seed", type=int, default=1337)
69
- parser.add_argument("--init-from", default=None, help="checkpoint safetensors dari backend TF")
70
- parser.add_argument("--device", default="auto", choices=["auto", "cpu", "gpu"])
71
- args = parser.parse_args()
72
-
73
- if args.device == "cpu":
74
- tf.config.set_visible_devices([], "GPU")
75
- gpus = tf.config.list_physical_devices("GPU")
76
- device_label = f"gpu({len(gpus)})" if gpus and args.device != "cpu" else "cpu"
77
-
78
- random.seed(args.seed)
79
- np.random.seed(args.seed)
80
- tf.random.set_seed(args.seed)
81
- os.makedirs(args.out, exist_ok=True)
82
-
83
- files = sorted(collect_text_files(args.data))
84
- if not files:
85
- raise SystemExit("tidak ada file teks ditemukan")
86
- rng = random.Random(args.seed)
87
- rng.shuffle(files)
88
- n_val = max(1, round(len(files) * 0.1)) if len(files) > 1 else 0
89
- print(f"file latih={len(files) - n_val} | file validasi={n_val}")
90
-
91
- train_text = "".join(read_clean(p) for p in files[n_val:])
92
- val_text = "".join(read_clean(p) for p in files[:n_val])
93
-
94
- tokenizer = CharTokenizer.from_text(train_text + val_text)
95
- train_np = np.array(tokenizer.encode(train_text), dtype=np.int64)
96
- val_np = np.array(tokenizer.encode(val_text), dtype=np.int64)
97
- if len(train_np) < args.block_size * 2:
98
- raise SystemExit(f"data latih terlalu pendek ({len(train_np)} token)")
99
- print(
100
- f"tokens latih={len(train_np):,} | tokens validasi={len(val_np):,} | vocab={tokenizer.vocab_size}"
101
- )
102
-
103
- start_step = 0
104
- init_state = None
105
- if args.init_from:
106
- meta = load_meta(args.init_from)
107
- if meta.get("backend") != "tensorflow":
108
- raise SystemExit(f"{args.init_from} bukan checkpoint backend TensorFlow")
109
- config_d = meta["config"]
110
- start_step = meta.get("step", 0)
111
- init_state = {k.replace("/", "_"): v for k, v in load_file(args.init_from).items()}
112
- print(f"melanjutkan dari {args.init_from} (step {start_step})")
113
- else:
114
- config_d = {
115
- "vocab_size": tokenizer.vocab_size,
116
- "block_size": args.block_size,
117
- "n_layer": args.n_layer,
118
- "n_head": args.n_head,
119
- "n_embd": args.n_embd,
120
- "dropout": args.dropout,
121
- "bias": False,
122
- }
123
- if config_d["vocab_size"] != tokenizer.vocab_size:
124
- raise SystemExit("vocab tidak cocok")
125
- total_steps = start_step + args.steps
126
-
127
- model = build_gpt(
128
- vocab_size=config_d["vocab_size"],
129
- block_size=config_d["block_size"],
130
- n_layer=config_d["n_layer"],
131
- n_head=config_d["n_head"],
132
- n_embd=config_d["n_embd"],
133
- dropout=config_d["dropout"],
134
- )
135
- if init_state is not None:
136
- by_path = {v.path.replace("/", "_"): v for v in model.weights}
137
- missing = [p for p in by_path if p not in init_state]
138
- if missing:
139
- raise SystemExit(f"bobot tidak cocok dengan checkpoint: {missing[:5]}")
140
- model.set_weights([init_state[v.path.replace("/", "_")] for v in model.weights])
141
-
142
- n_params = int(sum(int(np.prod(v.shape)) for v in model.weights))
143
- print(f"device={device_label} | params={n_params / 1e6:.2f}M | vocab={config_d['vocab_size']} | total_steps={total_steps}")
144
-
145
- optimizer = tf.keras.optimizers.AdamW(
146
- learning_rate=args.lr, beta_1=0.9, beta_2=0.95, weight_decay=args.weight_decay, clipnorm=1.0
147
- )
148
- loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
149
-
150
- def lr_at(step):
151
- if step < args.warmup:
152
- return args.lr * (step + 1) / args.warmup
153
- progress = (step - args.warmup) / max(1, total_steps - args.warmup)
154
- return 0.1 * args.lr + 0.45 * args.lr * (1 + math.cos(math.pi * progress))
155
-
156
- best_val = float("inf")
157
- last_val = None
158
- t0 = time.time()
159
- for step in range(start_step, total_steps):
160
- optimizer.learning_rate.assign(lr_at(step))
161
- x, y = get_batch(train_np, config_d["block_size"], args.batch_size)
162
- loss = train_step(model, optimizer, loss_fn, x, y)
163
- if step % args.eval_interval == 0 or step == total_steps - 1:
164
- if len(val_np) > config_d["block_size"] + 1:
165
- losses = []
166
- for _ in range(args.eval_iters):
167
- vx, vy = get_batch(val_np, config_d["block_size"], args.batch_size)
168
- losses.append(float(eval_step(model, loss_fn, vx, vy)))
169
- val_loss = sum(losses) / len(losses)
170
- marker = ""
171
- if val_loss < best_val:
172
- best_val = val_loss
173
- save_weights_tf(
174
- model,
175
- os.path.join(args.out, "indigo_best.safetensors"),
176
- config_d,
177
- tokenizer.itos,
178
- total_steps,
179
- val_loss,
180
- )
181
- marker = " <- best"
182
- last_val = val_loss
183
- val_str = f"{val_loss:.4f}{marker}"
184
- else:
185
- val_str = "n/a"
186
- print(
187
- f"step {step + 1:5d}/{total_steps} | "
188
- f"loss {float(loss):.4f} | val {val_str} | {time.time() - t0:.1f}s"
189
- )
190
-
191
- final_path = os.path.join(args.out, "indigo.safetensors")
192
- save_weights_tf(model, final_path, config_d, tokenizer.itos, total_steps, last_val)
193
- print(f"model tersimpan di {final_path} (+_meta.json)")
194
-
195
-
196
- if __name__ == "__main__":
197
- main()