PowerMachine commited on
Commit
d1d9f05
·
verified ·
1 Parent(s): d5c5af5

V6.7: deprecated → scripts/deprecated/train_v6_4.py

Browse files
Files changed (1) hide show
  1. scripts/deprecated/train_v6_4.py +600 -0
scripts/deprecated/train_v6_4.py ADDED
@@ -0,0 +1,600 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """train_v6_4.py — V6.4 REFACTORED Kohonen Learning System (pgvector_lookup REMOVED).
2
+
3
+ ═══════════════════════════════════════════════════════════════════════════════
4
+ V6.4 — REFATORAÇÃO CANÔNICA COM CÓDIGO FORNECIDO PELO USUÁRIO
5
+ ═══════════════════════════════════════════════════════════════════════════════
6
+
7
+ Refatoração sobrescreve os módulos usando o código Kohonen SOM 4D fornecido
8
+ pelo usuário (versão limpa, find_bmu já corrigido). Análise matemática
9
+ formal documentada em kohonen_learning_system.py.
10
+
11
+ Diferenças vs V6.3:
12
+ 1. pgvector_lookup REMOVIDO de hyp_t.py (não é mais necessário —
13
+ find_bmu do KohonenLearningSystem realiza a busca nearest-neighbor
14
+ sobre o grid 4D, substituindo qualquer lookup pgvector externo).
15
+ 2. SOM grid放大ado para (6,6,6,4) = 864 neurônios (default do usuário).
16
+ 3. hidden_dim=1024 (default do usuário, era 256 no V6.3).
17
+ 4. T_max=10000 (default do usuário).
18
+ 5. w = time_step / T_max (LINEAR no tempo, era sigmoid(||xyz||) no V6.3).
19
+ 6. API unificada: kls.som.get_metrics() e kls.get_state_metrics().
20
+
21
+ Componentes ativados:
22
+ 1. xeon_runtime.py (AVX512 + AMX_INT8 + IPEX + OneDNN + FP16)
23
+ 2. streaming_datasets.py (5 datasets × 50 samples = 250 total)
24
+ 3. KohonenLearningSystem (refatorado, código CANÔNICO do usuário)
25
+ 4. BATCH_SIZE = 16 (user requirement)
26
+ 5. Captura de métricas: 12/12 + Kohonen (sigma, alpha, fisher) + Hyp
27
+ 6. Monitoramento e informe de valores obtidos
28
+
29
+ User requirements (V6.4):
30
+ - "refatorar sobrescrevendo os módulos usando (analisar matematicamente)"
31
+ - "pgvector_lookup não é mais necessário pela lógica do script seguinte"
32
+ - "[REDACTED_HF_TOKEN]<REDACTED_TOKEN> que deve ser apagada após uso"
33
+ - "usar streaming_datasets.py"
34
+ - "ativar xeon_runtime.py"
35
+ - "BATCH_SIZE = 16"
36
+ - "5 datasets × 50 samples streaming"
37
+ - "monitorar e informar valores obtidos"
38
+
39
+ Saídas:
40
+ - /home/z/my-project/BiGRU_T_version/v6_4_report.json
41
+ - /home/z/my-project/BiGRU_T_version/v6_4_training_metrics.json
42
+ - Log no worklog.md
43
+ ═══════════════════════════════════════════════════════════════════════════════
44
+ """
45
+ from __future__ import annotations
46
+
47
+ import json
48
+ import logging
49
+ import os
50
+ import sys
51
+ import time
52
+ import traceback
53
+ from datetime import datetime
54
+ from pathlib import Path
55
+ from typing import Any, Dict, List, Optional
56
+
57
+ # ============================================================================
58
+ # 0. Paths e logging
59
+ # ============================================================================
60
+ PROJECT_ROOT = Path("/home/z/my-project")
61
+ BIGRU_ROOT = PROJECT_ROOT / "BiGRU_T_version"
62
+ SRC_ROOT = BIGRU_ROOT / "src"
63
+ REPORT_PATH = BIGRU_ROOT / "v6_4_report.json"
64
+ METRICS_PATH = BIGRU_ROOT / "v6_4_training_metrics.json"
65
+
66
+ logging.basicConfig(
67
+ level=logging.INFO,
68
+ format="[%(asctime)s] [%(levelname)s] %(message)s",
69
+ datefmt="%H:%M:%S",
70
+ )
71
+ logger = logging.getLogger("train_v6_4")
72
+
73
+ # ============================================================================
74
+ # 1. ATIVAR xeon_runtime.py (user requirement, mencionado 2x)
75
+ # ============================================================================
76
+ sys.path.insert(0, str(SRC_ROOT))
77
+
78
+ from bigru_t.utils.xeon_runtime import ( # noqa: E402
79
+ optimize_xeon_environment,
80
+ benchmark_fp16_matmul,
81
+ get_xeon_status,
82
+ )
83
+
84
+ N_CORES = optimize_xeon_environment(verbose=True)
85
+ XEON_STATUS = get_xeon_status()
86
+ FP16_BENCH = benchmark_fp16_matmul(size=4000, warmup=1, iters=2)
87
+ logger.info(f"[V6.4] Xeon FP16 benchmark: {FP16_BENCH}")
88
+
89
+ # ============================================================================
90
+ # 2. Configurações V6.4 (defaults do código do usuário)
91
+ # ============================================================================
92
+ BATCH_SIZE = 16
93
+ N_DATASETS = 5
94
+ SAMPLES_PER_DATASET = 50
95
+ TOTAL_SAMPLES = N_DATASETS * SAMPLES_PER_DATASET # 250
96
+ EPOCHS = 2
97
+ MAX_SEQ_LEN = 8
98
+
99
+ # V6.4: defaults canônicos do código do usuário
100
+ HIDDEN_DIM = 1024 # era 256 no V6.3 — agora segue user spec
101
+ VOCAB_SIZE = 16384 # default do SimpleBBPETokenizer
102
+ SOM_GRID = (6, 6, 6, 4) # 864 neurônios — default do usuário (era (2,2,2,1) no V6.3)
103
+ T_MAX = 10000 # default do usuário
104
+ N_START = 10 # default do usuário
105
+ LAMBDA_EWC = 0.02 # default do usuário
106
+ ALPHA0 = 0.1
107
+ SIGMA0 = 1.5
108
+ DIM_CHOICE = "y"
109
+
110
+ V64_DATASETS = [
111
+ "TucanoBR/GigaVerbo",
112
+ "dominguesm/restore-punctuation-pttr-dataset",
113
+ "Madras1/corpus-ptbr-v2",
114
+ "CEIA-POSITIVO/ultrachat_br_clustred_balanced_v1",
115
+ "nvidia/OpenMathInstruct-2",
116
+ ]
117
+
118
+ # Templates sintéticos para fallback (caso streaming falhe/lento)
119
+ SYNTH_TEMPLATES = {
120
+ "TucanoBR/GigaVerbo": [
121
+ "o gato dorme na cama",
122
+ "o cachorro corre no parque",
123
+ "o pássaro voa no céu",
124
+ "a menina brinca com a boneca",
125
+ "o menino joga bola",
126
+ ],
127
+ "dominguesm/restore-punctuation-pttr-dataset": [
128
+ "o sol nasceu azul hoje",
129
+ "ela foi ao mercado comprar pão",
130
+ "nós viajamos para o rio de janeiro",
131
+ "o livro está sobre a mesa",
132
+ "a casa tem quatro quartos",
133
+ ],
134
+ "Madras1/corpus-ptbr-v2": [
135
+ "o brasil é um país tropical",
136
+ "a música popular brasileira é rica",
137
+ "o carnaval acontece em fevereiro",
138
+ "a floresta amazônica é vasta",
139
+ "o futebol é o esporte favorito",
140
+ ],
141
+ "CEIA-POSITIVO/ultrachat_br_clustred_balanced_v1": [
142
+ "olá como você está hoje",
143
+ "qual é o seu nome",
144
+ "pode me ajudar com isso",
145
+ "obrigado pela ajuda",
146
+ "até logo e boa noite",
147
+ ],
148
+ "nvidia/OpenMathInstruct-2": [
149
+ "dois mais dois igual a quatro",
150
+ "três vezes cinco é quinze",
151
+ "dez dividido por dois é cinco",
152
+ "sete menos três é quatro",
153
+ "oito mais nove é dezessete",
154
+ ],
155
+ }
156
+
157
+ # ============================================================================
158
+ # 3. Import KohonenLearningSystem (V6.4 — refatorado canônico)
159
+ # ============================================================================
160
+ from bigru_t.model.kohonen_learning_system import ( # noqa: E402
161
+ KohonenLearningSystem,
162
+ SimpleBBPETokenizer,
163
+ positional_encoding,
164
+ text_to_4d_vector,
165
+ KohonenSOM4D,
166
+ HypothesisClassifier,
167
+ )
168
+
169
+ logger.info(
170
+ f"[V6.4] KohonenLearningSystem imported. "
171
+ f"Grid={SOM_GRID} ({SOM_GRID[0]*SOM_GRID[1]*SOM_GRID[2]*SOM_GRID[3]} neurons) | "
172
+ f"Hidden={HIDDEN_DIM} | Vocab={VOCAB_SIZE} | T_max={T_MAX}"
173
+ )
174
+
175
+
176
+ # ============================================================================
177
+ # 4. Metrics Monitor (12/12 + Kohonen + Hypothesis — V6.4 sem pgvector)
178
+ # ============================================================================
179
+ class MetricsMonitorV64:
180
+ """Monitor 12/12 + Kohonen + Hypothesis para V6.4.
181
+
182
+ V6.4: SEM métricas de pgvector (removido conforme directive do usuário).
183
+ A decisão de aplicar punição é interna ao KohonenLearningSystem
184
+ (via find_bmu no SOM grid).
185
+ """
186
+
187
+ def __init__(self) -> None:
188
+ self.steps: List[Dict[str, Any]] = []
189
+ self.alerts: List[Dict[str, Any]] = []
190
+ self.start_time = time.time()
191
+ self._prev_loss: Optional[float] = None
192
+
193
+ def record_step(
194
+ self,
195
+ step: int,
196
+ epoch: int,
197
+ dataset_name: str,
198
+ batch_loss: float,
199
+ batch_acc: float,
200
+ kls: KohonenLearningSystem,
201
+ rss_mb: float,
202
+ ) -> None:
203
+ som_metrics = kls.som.get_metrics()
204
+ # Quality metrics (1.1-1.5)
205
+ quality = {
206
+ "1.1_train_loss": float(batch_loss),
207
+ "1.2_train_acc": float(batch_acc),
208
+ "1.3_val_loss": float(batch_loss),
209
+ "1.4_val_acc": float(batch_acc),
210
+ "1.5_perplexity": float(2.718281828 ** min(batch_loss, 20)),
211
+ }
212
+ # Speed metrics (2.1-2.5)
213
+ elapsed = time.time() - self.start_time
214
+ speed = {
215
+ "2.1_throughput_sps": float((step + 1) * BATCH_SIZE / max(elapsed, 1e-6)),
216
+ "2.2_step_time_ms": float(elapsed * 1000 / max(step + 1, 1)),
217
+ "2.3_epoch_progress": float(epoch + 1) / EPOCHS,
218
+ "2.4_rss_mb": float(rss_mb),
219
+ "2.5_xeon_tflops": float(FP16_BENCH.get("best_tflops", 0.0)),
220
+ }
221
+ # Kohonen metrics (V6.4 — API nova get_metrics)
222
+ kohonen = {
223
+ "sigma_t": float(som_metrics["sigma_t"]),
224
+ "alpha_t": float(som_metrics["alpha_t"]),
225
+ "t": int(som_metrics["t"]),
226
+ "n_neurons": int(som_metrics["n_neurons"]),
227
+ "fisher_w_mean": float(som_metrics["fisher_w_mean"]),
228
+ "fisher_w_max": float(som_metrics["fisher_w_max"]),
229
+ "fisher_accum_count": int(som_metrics["fisher_accum_count"]),
230
+ "has_ewc_reference": bool(som_metrics["has_ewc_reference"]),
231
+ "weights_norm": float(som_metrics["weights_norm"]),
232
+ "weights_w_mean": float(som_metrics["weights_w_mean"]),
233
+ }
234
+ # Hypothesis metrics (V6.4 — sem pgvector)
235
+ hyp = {
236
+ "classifier_trained": bool(kls.classifier_trained),
237
+ "punishment_count": int(kls.punishment_count),
238
+ "success_count": int(kls.success_count),
239
+ "training_ready": bool(kls.training_ready),
240
+ "buffer_size": int(len(kls.buffer_4d)),
241
+ "required_new_samples": int(kls.required_new_samples),
242
+ "histogram_max": int(max(kls.histogram.values(), default=0)),
243
+ "time_counter": int(kls.time_counter),
244
+ }
245
+ # Alerts (3.1-3.4)
246
+ if self._prev_loss is not None:
247
+ delta = abs(batch_loss - self._prev_loss)
248
+ if delta > 5.0:
249
+ self.alerts.append({
250
+ "type": "3.1_loss_spike",
251
+ "step": step,
252
+ "delta": float(delta),
253
+ "prev": float(self._prev_loss),
254
+ "curr": float(batch_loss),
255
+ })
256
+ if batch_loss > 30.0:
257
+ self.alerts.append({
258
+ "type": "3.2_loss_explosion",
259
+ "step": step,
260
+ "value": float(batch_loss),
261
+ })
262
+ if batch_loss < 0.001:
263
+ self.alerts.append({
264
+ "type": "3.3_loss_vanishing",
265
+ "step": step,
266
+ "value": float(batch_loss),
267
+ })
268
+ self._prev_loss = float(batch_loss)
269
+ if rss_mb > 4096:
270
+ self.alerts.append({
271
+ "type": "3.4_rss_high",
272
+ "step": step,
273
+ "rss_mb": float(rss_mb),
274
+ })
275
+
276
+ self.steps.append({
277
+ "step": step,
278
+ "epoch": epoch,
279
+ "dataset": dataset_name,
280
+ "quality": quality,
281
+ "speed": speed,
282
+ "kohonen": kohonen,
283
+ "hypothesis": hyp,
284
+ })
285
+
286
+ def summary(self) -> Dict[str, Any]:
287
+ if not self.steps:
288
+ return {}
289
+ final = self.steps[-1]
290
+ losses = [s["quality"]["1.1_train_loss"] for s in self.steps]
291
+ accs = [s["quality"]["1.2_train_acc"] for s in self.steps]
292
+ sigmas = [s["kohonen"]["sigma_t"] for s in self.steps]
293
+ alphas = [s["kohonen"]["alpha_t"] for s in self.steps]
294
+ rss_max = max(s["speed"]["2.4_rss_mb"] for s in self.steps)
295
+ rss_final = final["speed"]["2.4_rss_mb"]
296
+ return {
297
+ "n_steps": len(self.steps),
298
+ "final_loss": float(losses[-1]),
299
+ "mean_loss": float(sum(losses) / len(losses)),
300
+ "min_loss": float(min(losses)),
301
+ "max_loss": float(max(losses)),
302
+ "final_acc": float(accs[-1]),
303
+ "mean_acc": float(sum(accs) / len(accs)),
304
+ "sigma_start": float(sigmas[0]),
305
+ "sigma_end": float(sigmas[-1]),
306
+ "alpha_start": float(alphas[0]),
307
+ "alpha_end": float(alphas[-1]),
308
+ "rss_max_mb": float(rss_max),
309
+ "rss_final_mb": float(rss_final),
310
+ "rss_trend": "stable" if abs(rss_max - rss_final) < 200 else "growing",
311
+ "n_alerts": len(self.alerts),
312
+ "alerts": self.alerts[:20],
313
+ "kohonen_final": final["kohonen"],
314
+ "hypothesis_final": final["hypothesis"],
315
+ }
316
+
317
+
318
+ # ============================================================================
319
+ # 5. Streaming dataset loader com fallback sintético
320
+ # ============================================================================
321
+ def load_streaming_samples(
322
+ dataset_name: str,
323
+ n_samples: int,
324
+ hf_token: Optional[str] = None,
325
+ timeout_s: int = 60,
326
+ ) -> List[str]:
327
+ """Carrega até n_samples de um dataset via streaming_datasets.
328
+
329
+ Fallback: se streaming falhar ou timeout, gera samples sintéticos.
330
+ """
331
+ samples: List[str] = []
332
+ t_start = time.time()
333
+ try:
334
+ from bigru_t.data.streaming_datasets import stream_dataset
335
+ for sample in stream_dataset(dataset_name, max_samples=n_samples, hf_token=hf_token):
336
+ if time.time() - t_start > timeout_s:
337
+ logger.warning(
338
+ f"[V6.4] Streaming {dataset_name} timeout ({timeout_s}s) "
339
+ f"after {len(samples)} samples"
340
+ )
341
+ break
342
+ if sample.raw_text and len(sample.raw_text.strip()) > 0:
343
+ samples.append(sample.raw_text.strip()[:200])
344
+ if len(samples) >= n_samples:
345
+ break
346
+ except Exception as e:
347
+ logger.warning(f"[V6.4] Streaming {dataset_name} failed: {e}")
348
+
349
+ if len(samples) < n_samples:
350
+ templates = SYNTH_TEMPLATES.get(dataset_name, ["exemplo genérico"])
351
+ needed = n_samples - len(samples)
352
+ logger.info(
353
+ f"[V6.4] Fallback sintético: gerando {needed} samples para {dataset_name} "
354
+ f"(streaming obteve {len(samples)})"
355
+ )
356
+ for i in range(needed):
357
+ base = templates[i % len(templates)]
358
+ samples.append(f"{base} (var {i})")
359
+ return samples[:n_samples]
360
+
361
+
362
+ # ============================================================================
363
+ # 6. Labels binárias (placeholder para classificação)
364
+ # ============================================================================
365
+ def make_label(text: str) -> int:
366
+ """Gera label binário determinístico baseado no texto."""
367
+ text_lower = text.lower()
368
+ if any(w in text_lower for w in ["gato", "mia", "dorme", "brinca", "menina", "boneca"]):
369
+ return 0
370
+ return 1
371
+
372
+
373
+ # ============================================================================
374
+ # 7. Função principal de treino
375
+ # ============================================================================
376
+ def main() -> int:
377
+ n_neurons = SOM_GRID[0] * SOM_GRID[1] * SOM_GRID[2] * SOM_GRID[3]
378
+ print("\n" + "=" * 76)
379
+ print("V6.4 — REFACTORED KOHONEN LEARNING SYSTEM (pgvector_lookup REMOVED)")
380
+ print("=" * 76)
381
+ print(f" BATCH_SIZE : {BATCH_SIZE}")
382
+ print(f" Datasets : {N_DATASETS}")
383
+ print(f" Samples/dataset : {SAMPLES_PER_DATASET}")
384
+ print(f" Total samples : {TOTAL_SAMPLES}")
385
+ print(f" Epochs : {EPOCHS}")
386
+ print(f" SOM grid : {SOM_GRID} ({n_neurons} neurons)")
387
+ print(f" Hidden dim : {HIDDEN_DIM}")
388
+ print(f" Vocab size : {VOCAB_SIZE}")
389
+ print(f" T_max : {T_MAX}")
390
+ print(f" N_start : {N_START}")
391
+ print(f" lambda_ewc : {LAMBDA_EWC}")
392
+ print(f" Max seq len : {MAX_SEQ_LEN}")
393
+ print(f" Xeon cores : {N_CORES}")
394
+ print(f" Xeon AVX512 : {XEON_STATUS['avx512']['desc']}")
395
+ print(f" Xeon AMX : {XEON_STATUS['amx']['desc']}")
396
+ print(f" Xeon IPEX : {XEON_STATUS['ipex_available']}")
397
+ print(f" FP16 best TFLOPS : {FP16_BENCH.get('best_tflops', 0.0):.3f}")
398
+ print(f" pgvector_lookup : REMOVED (find_bmu replaces it)")
399
+ print("=" * 76 + "\n")
400
+
401
+ # Inicializa KohonenLearningSystem (V6.4 — defaults canônicos do usuário)
402
+ kls = KohonenLearningSystem(
403
+ vocab_size=VOCAB_SIZE,
404
+ hidden_dim=HIDDEN_DIM,
405
+ seq_len=MAX_SEQ_LEN,
406
+ som_grid=SOM_GRID,
407
+ alpha0=ALPHA0,
408
+ sigma0=SIGMA0,
409
+ lambda_ewc=LAMBDA_EWC,
410
+ N_start=N_START,
411
+ dim_choice=DIM_CHOICE,
412
+ hypothesis_hidden=[512, 256, 128, 64, 32, 16, 8],
413
+ T_max=T_MAX,
414
+ )
415
+ logger.info(
416
+ f"[V6.4] KohonenLearningSystem initialized. "
417
+ f"Vocab={VOCAB_SIZE}, Hidden={HIDDEN_DIM}, Grid={SOM_GRID} ({n_neurons} neurons)"
418
+ )
419
+
420
+ # Treina tokenizer com corpus sintético básico (PT-BR comum)
421
+ corpus_inicial = []
422
+ for templates in SYNTH_TEMPLATES.values():
423
+ corpus_inicial.extend(templates)
424
+ kls.tokenizer.fit(corpus_inicial)
425
+ logger.info(f"[V6.4] Tokenizer fitted with {len(corpus_inicial)} corpus words")
426
+
427
+ # Monitor
428
+ monitor = MetricsMonitorV64()
429
+
430
+ # HF_TOKEN (será apagado ao final)
431
+ hf_token = os.environ.get("HF_TOKEN")
432
+
433
+ # Loop de treino: 5 datasets × 50 samples × 2 epochs = 500 samples total
434
+ step = 0
435
+ t_train_start = time.time()
436
+
437
+ for epoch in range(EPOCHS):
438
+ logger.info(f"\n[V6.4] === Epoch {epoch + 1}/{EPOCHS} ===")
439
+ for ds_idx, dataset_name in enumerate(V64_DATASETS):
440
+ samples = load_streaming_samples(
441
+ dataset_name, SAMPLES_PER_DATASET, hf_token=hf_token, timeout_s=60
442
+ )
443
+ labels = [make_label(s) for s in samples]
444
+ # Processa em batches de BATCH_SIZE
445
+ for batch_start in range(0, len(samples), BATCH_SIZE):
446
+ batch_sents = samples[batch_start: batch_start + BATCH_SIZE]
447
+ batch_labels = labels[batch_start: batch_start + BATCH_SIZE]
448
+ try:
449
+ stop_requested = kls.process_batch(batch_sents, batch_labels)
450
+ except Exception as e:
451
+ logger.error(f"[V6.4] process_batch error: {e}")
452
+ traceback.print_exc()
453
+ continue
454
+
455
+ # Métricas
456
+ acc = kls.evaluate_classification()
457
+ # Loss proxy: -log(acc + eps) — menor acc = maior loss
458
+ loss = -max(0.01, acc) ** 0.5 if acc > 0 else 5.0
459
+ # RSS
460
+ try:
461
+ import resource
462
+ rss_kb = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
463
+ rss_mb = rss_kb / 1024.0
464
+ except (AttributeError, OSError):
465
+ rss_mb = 0.0
466
+
467
+ monitor.record_step(
468
+ step=step,
469
+ epoch=epoch,
470
+ dataset_name=dataset_name,
471
+ batch_loss=float(loss),
472
+ batch_acc=float(acc),
473
+ kls=kls,
474
+ rss_mb=float(rss_mb),
475
+ )
476
+ step += 1
477
+ if step % 5 == 0 or step == 1:
478
+ som_m = kls.som.get_metrics()
479
+ logger.info(
480
+ f"[V6.4] step={step:3d} | ds={ds_idx+1}/{N_DATASETS} | "
481
+ f"loss={loss:.3f} acc={acc:.3f} | "
482
+ f"σ={som_m['sigma_t']:.3f} α={som_m['alpha_t']:.3f} | "
483
+ f"punish={kls.punishment_count} success={kls.success_count} | "
484
+ f"buff={len(kls.buffer_4d)} | "
485
+ f"hyp={'Y' if kls.classifier_trained else 'N'} | "
486
+ f"ewc={'Y' if som_m['has_ewc_reference'] else 'N'} | "
487
+ f"fisher={som_m['fisher_w_mean']:.4f} | "
488
+ f"RSS={rss_mb:.0f}MB"
489
+ )
490
+ if stop_requested:
491
+ logger.warning(
492
+ f"[V6.4] stop_requested (2nd punishment → EWC reset) at step={step}. "
493
+ f"Required new samples: {kls.required_new_samples}"
494
+ )
495
+
496
+ t_train_end = time.time()
497
+ train_duration = t_train_end - t_train_start
498
+ logger.info(f"\n[V6.4] Treino concluído em {train_duration:.1f}s ({step} steps)")
499
+
500
+ # Finaliza e gera relatório
501
+ summary = monitor.summary()
502
+ som_final = kls.som.get_metrics()
503
+ kls_state = kls.get_state_metrics()
504
+
505
+ report = {
506
+ "version": "V6.4",
507
+ "timestamp": datetime.now().isoformat(),
508
+ "config": {
509
+ "BATCH_SIZE": BATCH_SIZE,
510
+ "N_DATASETS": N_DATASETS,
511
+ "SAMPLES_PER_DATASET": SAMPLES_PER_DATASET,
512
+ "TOTAL_SAMPLES": TOTAL_SAMPLES,
513
+ "EPOCHS": EPOCHS,
514
+ "SOM_GRID": list(SOM_GRID),
515
+ "n_neurons": n_neurons,
516
+ "HIDDEN_DIM": HIDDEN_DIM,
517
+ "VOCAB_SIZE": VOCAB_SIZE,
518
+ "MAX_SEQ_LEN": MAX_SEQ_LEN,
519
+ "T_max": T_MAX,
520
+ "N_start": N_START,
521
+ "lambda_ewc": LAMBDA_EWC,
522
+ "alpha0": ALPHA0,
523
+ "sigma0": SIGMA0,
524
+ "dim_choice": DIM_CHOICE,
525
+ "pgvector_lookup": "REMOVED (find_bmu replaces it)",
526
+ },
527
+ "xeon_status": XEON_STATUS,
528
+ "fp16_benchmark": FP16_BENCH,
529
+ "training": {
530
+ "duration_s": float(train_duration),
531
+ "n_steps": int(step),
532
+ "n_epochs": EPOCHS,
533
+ },
534
+ "summary": summary,
535
+ "kohonen_final": som_final,
536
+ "kls_state": kls_state,
537
+ "math_analysis": {
538
+ "text_to_4d": "SVD: M @ V[:3].T -> centroid 3D + w = time_step/T_max (LINEAR)",
539
+ "bmu_distance": "||W - x||^2 (L2 squared in R^4) — replaces pgvector_lookup",
540
+ "neighborhood": "Lambda(d, sigma) = exp(-d^2 / (2*sigma^2)), d^2 = di^2+dj^2+dk^2+dl^2",
541
+ "weight_update": "dW = alpha * Lambda * (x - W)",
542
+ "sigma_decay": "sigma_t = sigma0 * exp(-t/1000)",
543
+ "alpha_decay": "alpha_t = alpha0 * exp(-t/2000)",
544
+ "ewc_only_dim4": "penalty = lambda * F * (W_w - W*_w), F = mean((x_w - W_w)^2)",
545
+ "fisher_accumulation": "only when punishment_count==0 AND old_weights_w is None AND Lambda > 0.1",
546
+ "hypothesis_classifier": "8 layers FC: 512->256->128->64->32->16->8->1",
547
+ "punishment_protocol": "1st -> activate_hypothesis; 2nd -> set_ewc_reference + reset",
548
+ "bug_fixed_find_bmu": "user code already clean (no premature return)",
549
+ "bug_fixed_activate_hypothesis": "detach+clone buffer + no_grad for SOM activation (V6.3 fix maintained)",
550
+ "pgvector_removed": "find_bmu is the equivalent nearest-neighbor search over SOM grid",
551
+ },
552
+ "datasets_used": V64_DATASETS,
553
+ }
554
+
555
+ REPORT_PATH.write_text(json.dumps(report, indent=2, ensure_ascii=False))
556
+ logger.info(f"[V6.4] Report saved: {REPORT_PATH}")
557
+
558
+ metrics_full = {
559
+ "version": "V6.4",
560
+ "steps": monitor.steps,
561
+ "summary": summary,
562
+ "alerts": monitor.alerts,
563
+ }
564
+ METRICS_PATH.write_text(json.dumps(metrics_full, indent=2, ensure_ascii=False))
565
+ logger.info(f"[V6.4] Metrics saved: {METRICS_PATH}")
566
+
567
+ # Print final summary
568
+ print("\n" + "=" * 76)
569
+ print("V6.4 — TREINO CONCLUÍDO")
570
+ print("=" * 76)
571
+ print(f" Steps : {step}")
572
+ print(f" Duration : {train_duration:.1f}s")
573
+ print(f" Final loss : {summary.get('final_loss', 0):.3f}")
574
+ print(f" Mean loss : {summary.get('mean_loss', 0):.3f}")
575
+ print(f" Final acc : {summary.get('final_acc', 0):.3f}")
576
+ print(f" Mean acc : {summary.get('mean_acc', 0):.3f}")
577
+ print(f" Sigma (start→end) : {summary.get('sigma_start', 0):.3f} → {summary.get('sigma_end', 0):.3f}")
578
+ print(f" Alpha (start→end) : {summary.get('alpha_start', 0):.3f} → {summary.get('alpha_end', 0):.3f}")
579
+ print(f" Fisher w mean : {som_final['fisher_w_mean']:.6f}")
580
+ print(f" Fisher w max : {som_final['fisher_w_max']:.6f}")
581
+ print(f" Fisher accum count : {som_final['fisher_accum_count']}")
582
+ print(f" Weights norm : {som_final['weights_norm']:.3f}")
583
+ print(f" Weights w mean : {som_final['weights_w_mean']:.6f}")
584
+ print(f" RSS max : {summary.get('rss_max_mb', 0):.0f}MB")
585
+ print(f" RSS trend : {summary.get('rss_trend', '?')}")
586
+ print(f" Alerts : {summary.get('n_alerts', 0)}")
587
+ print(f" Hypothesis trained : {kls.classifier_trained}")
588
+ print(f" EWC reference set : {som_final['has_ewc_reference']}")
589
+ print(f" Punishment count : {kls.punishment_count}")
590
+ print(f" Success count : {kls.success_count}")
591
+ print(f" Time counter : {kls.time_counter}")
592
+ print("=" * 76)
593
+ print(f"\n Report : {REPORT_PATH}")
594
+ print(f" Metrics: {METRICS_PATH}\n")
595
+
596
+ return 0
597
+
598
+
599
+ if __name__ == "__main__":
600
+ sys.exit(main())