V6.5-7ds cleanup: remove legacy scripts/train_v2.py
Browse files- scripts/train_v2.py +0 -440
scripts/train_v2.py
DELETED
|
@@ -1,440 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python3
|
| 2 |
-
"""train_v2.py — Treino BiGRU_T_version V2 (15M params, HW optimizer, multimodal bug-hunt).
|
| 3 |
-
|
| 4 |
-
Melhorias vs train_fast.py:
|
| 5 |
-
- max_modules=10 (aumento de 4→10, memória permite), d_model=128
|
| 6 |
-
- ~14.45M params (objetivo 15M)
|
| 7 |
-
- HamiltonianWasserstein optimizer ATIVADO (AdamW + W₂ + repulsão + LR cíclico)
|
| 8 |
-
- TimeBudget + aggressive_cleanup (estilo Xavante)
|
| 9 |
-
- Teste de multimodalidade (text/image/audio/video encoders) com poucos samples
|
| 10 |
-
- Timeout aumentado (1800s total, 900s/epoch)
|
| 11 |
-
- Verificação de OOM-Killer antes do treino
|
| 12 |
-
- Smoke checks antes do treino principal
|
| 13 |
-
|
| 14 |
-
Uso:
|
| 15 |
-
export HF_TOKEN=hf_xxx # opcional, para datasets privados
|
| 16 |
-
python3 scripts/train_v2.py
|
| 17 |
-
"""
|
| 18 |
-
from __future__ import annotations
|
| 19 |
-
|
| 20 |
-
import os
|
| 21 |
-
import sys
|
| 22 |
-
import time
|
| 23 |
-
import json
|
| 24 |
-
import logging
|
| 25 |
-
import gc
|
| 26 |
-
import shutil
|
| 27 |
-
from pathlib import Path
|
| 28 |
-
|
| 29 |
-
# Adiciona src/ ao path
|
| 30 |
-
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
|
| 31 |
-
|
| 32 |
-
# Otimização Xeon
|
| 33 |
-
os.environ.setdefault("OMP_NUM_THREADS", "2")
|
| 34 |
-
os.environ.setdefault("MKL_NUM_THREADS", "2")
|
| 35 |
-
os.environ.setdefault("TOKENIZERS_PARALLELISM", "false")
|
| 36 |
-
|
| 37 |
-
import torch
|
| 38 |
-
torch.set_num_threads(2)
|
| 39 |
-
|
| 40 |
-
try:
|
| 41 |
-
from bigru_t.utils.xeon_runtime import optimize_xeon_environment
|
| 42 |
-
optimize_xeon_environment()
|
| 43 |
-
except Exception as e:
|
| 44 |
-
logging.warning(f"Could not apply Xeon optimization: {e}")
|
| 45 |
-
|
| 46 |
-
from bigru_t import (
|
| 47 |
-
UnifiedModel, UnifiedModelConfig, create_unified_model,
|
| 48 |
-
BiGRU_T_Trainer, TrainerConfig,
|
| 49 |
-
HamiltonianWassersteinOptimizer,
|
| 50 |
-
CircularReasoningWasserstein,
|
| 51 |
-
BiGRUTGenerator,
|
| 52 |
-
aggressive_cleanup, get_rss_mb, TimeBudget,
|
| 53 |
-
)
|
| 54 |
-
from bigru_t.data.streaming_datasets import stream_dataset
|
| 55 |
-
|
| 56 |
-
logging.basicConfig(
|
| 57 |
-
level=logging.INFO,
|
| 58 |
-
format="%(asctime)s [%(levelname)s] %(message)s",
|
| 59 |
-
datefmt="%H:%M:%S",
|
| 60 |
-
handlers=[logging.StreamHandler()],
|
| 61 |
-
)
|
| 62 |
-
logger = logging.getLogger(__name__)
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
def check_oom_killer_risk() -> bool:
|
| 66 |
-
"""Verifica se há risco de OOM-Killer antes de iniciar treino.
|
| 67 |
-
|
| 68 |
-
Checa:
|
| 69 |
-
1. dmesg por ocorrências recentes de OOM-Killer
|
| 70 |
-
2. Memória livre do sistema
|
| 71 |
-
3. Swap disponível
|
| 72 |
-
|
| 73 |
-
Returns:
|
| 74 |
-
True se seguro para prosseguir, False se risco alto.
|
| 75 |
-
"""
|
| 76 |
-
import subprocess
|
| 77 |
-
# 1. dmesg OOM check
|
| 78 |
-
try:
|
| 79 |
-
result = subprocess.run(
|
| 80 |
-
["dmesg"], capture_output=True, text=True, timeout=5
|
| 81 |
-
)
|
| 82 |
-
if "Out of memory" in result.stdout or "Killed process" in result.stdout:
|
| 83 |
-
logger.warning("⚠️ dmesg mostra OOM-Killer activity recente — risco alto")
|
| 84 |
-
# Não aborta, apenas avisa (pode ser histórico antigo)
|
| 85 |
-
except (FileNotFoundError, subprocess.TimeoutExpired):
|
| 86 |
-
pass # dmesg pode não estar acessível
|
| 87 |
-
|
| 88 |
-
# 2. Memória livre do sistema
|
| 89 |
-
try:
|
| 90 |
-
with open("/proc/meminfo", "r") as f:
|
| 91 |
-
meminfo = dict(line.split(":")[1].strip().split()[0:2] for line in f if ":" in line)
|
| 92 |
-
free_mb = int(meminfo.get("MemAvailable", "0")) / 1024
|
| 93 |
-
total_mb = int(meminfo.get("MemTotal", "0")) / 1024
|
| 94 |
-
logger.info(f" Sistema: {total_mb:.0f}MB total, {free_mb:.0f}MB disponível")
|
| 95 |
-
if free_mb < 512:
|
| 96 |
-
logger.error(f"❌ Memória disponível muito baixa ({free_mb:.0f}MB < 512MB)")
|
| 97 |
-
return False
|
| 98 |
-
except Exception:
|
| 99 |
-
pass
|
| 100 |
-
|
| 101 |
-
# 3. Disk free
|
| 102 |
-
try:
|
| 103 |
-
usage = shutil.disk_usage("/home/z/my-project")
|
| 104 |
-
free_gb = usage.free / (1024**3)
|
| 105 |
-
logger.info(f" Disk free: {free_gb:.2f}GB")
|
| 106 |
-
if free_gb < 1.0:
|
| 107 |
-
logger.error(f"❌ Disk livre muito baixo ({free_gb:.2f}GB < 1GB)")
|
| 108 |
-
return False
|
| 109 |
-
except Exception:
|
| 110 |
-
pass
|
| 111 |
-
|
| 112 |
-
return True
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
def smoke_test_model(model, tokenizer) -> bool:
|
| 116 |
-
"""Smoke test rápido: forward + backward + inference."""
|
| 117 |
-
logger.info("Running smoke test (forward + backward + generate)...")
|
| 118 |
-
try:
|
| 119 |
-
import torch
|
| 120 |
-
# Forward — COM grad (para permitir backward)
|
| 121 |
-
dummy_ids = torch.randint(0, 100, (1, 16), dtype=torch.long)
|
| 122 |
-
y_hat, delta = model(dummy_ids, temperature=1.0, use_hypothesis=False)
|
| 123 |
-
assert y_hat.shape[0] == 1, f"batch mismatch: {y_hat.shape}"
|
| 124 |
-
assert not torch.isnan(y_hat).any(), "NaN in y_hat"
|
| 125 |
-
logger.info(f" Forward OK: y_hat {tuple(y_hat.shape)}, delta {tuple(delta.shape)}")
|
| 126 |
-
|
| 127 |
-
# Backward
|
| 128 |
-
target = torch.tensor([5], dtype=torch.long)
|
| 129 |
-
loss = torch.nn.functional.cross_entropy(y_hat, target)
|
| 130 |
-
loss.backward()
|
| 131 |
-
grad_norm = sum(p.grad.norm().item() ** 2 for p in model.parameters() if p.grad is not None) ** 0.5
|
| 132 |
-
logger.info(f" Backward OK: loss={loss.item():.4f}, grad_norm={grad_norm:.4f}")
|
| 133 |
-
model.zero_grad()
|
| 134 |
-
|
| 135 |
-
# Generate (no grad)
|
| 136 |
-
gen = BiGRUTGenerator(model, max_seq_len=64)
|
| 137 |
-
with torch.no_grad():
|
| 138 |
-
out = gen.generate(dummy_ids, max_new_tokens=5, do_sample=False)
|
| 139 |
-
logger.info(f" Generate OK: {dummy_ids.shape} -> {out.shape}")
|
| 140 |
-
return True
|
| 141 |
-
except Exception as e:
|
| 142 |
-
import traceback
|
| 143 |
-
logger.error(f" Smoke test FAILED: {e}")
|
| 144 |
-
traceback.print_exc()
|
| 145 |
-
return False
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
def test_multimodal_encoders() -> dict:
|
| 149 |
-
"""Testa os encoders multimodais com dados sintéticos (bug detection).
|
| 150 |
-
|
| 151 |
-
Não usa datasets reais (apenas poucos samples sintéticos para validar
|
| 152 |
-
que os encoders não quebram). Retorna dict com status de cada encoder.
|
| 153 |
-
|
| 154 |
-
BUGS ENCONTRADOS E CORRIGIDOS:
|
| 155 |
-
1. TextEncoder dependia de 3 módulos ausentes (attention_multimodal,
|
| 156 |
-
embedding_reconfig, gru_hierarchy) — COPIADOS da fonte HF.
|
| 157 |
-
2. AudioEncoder: parâmetro `in_channels` é ignorado pelo Conv1d interno
|
| 158 |
-
(sempre usa n_mels=80 como canal) — WORKAROUND: passar [B, 80, T].
|
| 159 |
-
3. VideoEncoder.forward(frames, audio) espera frames=[B,T,C,H,W] (5D),
|
| 160 |
-
NÃO [B,C,T,H,W] — corrigido no teste.
|
| 161 |
-
4. ModalRouter.forward(inputs: Dict[str, Tensor]) — espera dict nomeado.
|
| 162 |
-
5. FusionLayer.forward(modality_embs: list) — espera lista de embeddings.
|
| 163 |
-
"""
|
| 164 |
-
logger.info("Testing multimodal encoders (synthetic data, bug detection)...")
|
| 165 |
-
results = {}
|
| 166 |
-
|
| 167 |
-
try:
|
| 168 |
-
from bigru_t.multimodal.text_encoder import TextEncoder
|
| 169 |
-
enc = TextEncoder(vocab_size=16384, d_model=128, n_heads=4, n_gru_levels=2, max_seq_len=64)
|
| 170 |
-
import torch
|
| 171 |
-
x = torch.randint(0, 100, (2, 16), dtype=torch.long)
|
| 172 |
-
out = enc(x)
|
| 173 |
-
results["text_encoder"] = {"ok": True, "shape": str(tuple(out.shape))}
|
| 174 |
-
logger.info(f" TextEncoder OK: {tuple(out.shape)}")
|
| 175 |
-
except Exception as e:
|
| 176 |
-
results["text_encoder"] = {"ok": False, "error": str(e)}
|
| 177 |
-
logger.warning(f" TextEncoder FAIL: {e}")
|
| 178 |
-
|
| 179 |
-
try:
|
| 180 |
-
from bigru_t.multimodal.image_encoder import ImageEncoder
|
| 181 |
-
enc = ImageEncoder(d_model=128, in_channels=3)
|
| 182 |
-
import torch
|
| 183 |
-
x = torch.randn(2, 3, 16, 16)
|
| 184 |
-
out = enc(x)
|
| 185 |
-
results["image_encoder"] = {"ok": True, "shape": str(tuple(out.shape))}
|
| 186 |
-
logger.info(f" ImageEncoder OK: {tuple(out.shape)}")
|
| 187 |
-
except Exception as e:
|
| 188 |
-
results["image_encoder"] = {"ok": False, "error": str(e)}
|
| 189 |
-
logger.warning(f" ImageEncoder FAIL: {e}")
|
| 190 |
-
|
| 191 |
-
try:
|
| 192 |
-
from bigru_t.multimodal.audio_encoder import AudioEncoder
|
| 193 |
-
# BUG: in_channels é ignorado; Conv1d usa n_mels como canal
|
| 194 |
-
enc = AudioEncoder(d_model=128, in_channels=80, n_mels=80)
|
| 195 |
-
import torch
|
| 196 |
-
# Shape correta: [B, n_mels=80, T_audio]
|
| 197 |
-
x = torch.randn(2, 80, 100)
|
| 198 |
-
out = enc(x)
|
| 199 |
-
results["audio_encoder"] = {"ok": True, "shape": str(tuple(out.shape)),
|
| 200 |
-
"note": "in_channels param unused; uses n_mels=80 as channel"}
|
| 201 |
-
logger.info(f" AudioEncoder OK: {tuple(out.shape)}")
|
| 202 |
-
except Exception as e:
|
| 203 |
-
results["audio_encoder"] = {"ok": False, "error": str(e)}
|
| 204 |
-
logger.warning(f" AudioEncoder FAIL: {e}")
|
| 205 |
-
|
| 206 |
-
try:
|
| 207 |
-
from bigru_t.multimodal.video_encoder import VideoEncoder
|
| 208 |
-
enc = VideoEncoder(d_model=128, n_frames=4)
|
| 209 |
-
import torch
|
| 210 |
-
# BUG: frames deve ser [B, T, C, H, W] (5D, T antes de C)
|
| 211 |
-
frames = torch.randn(2, 4, 3, 16, 16) # (B=2, T=4, C=3, H=16, W=16)
|
| 212 |
-
audio = torch.randn(2, 80, 100) # (B, n_mels, T_audio)
|
| 213 |
-
out = enc(frames, audio)
|
| 214 |
-
results["video_encoder"] = {"ok": True, "shape": str(tuple(out.shape)),
|
| 215 |
-
"note": "frames=[B,T,C,H,W], audio=[B,80,T]"}
|
| 216 |
-
logger.info(f" VideoEncoder OK: {tuple(out.shape)}")
|
| 217 |
-
except Exception as e:
|
| 218 |
-
results["video_encoder"] = {"ok": False, "error": str(e)}
|
| 219 |
-
logger.warning(f" VideoEncoder FAIL: {e}")
|
| 220 |
-
|
| 221 |
-
try:
|
| 222 |
-
from bigru_t.multimodal.modal_router import ModalRouter
|
| 223 |
-
from bigru_t.multimodal.fusion_layer import FusionLayer
|
| 224 |
-
router = ModalRouter(d_model=128)
|
| 225 |
-
fusion = FusionLayer(d_model=128, n_modalities=4)
|
| 226 |
-
import torch
|
| 227 |
-
# ModalRouter.forward(inputs: Dict[str, Tensor]) — espera dict nomeado
|
| 228 |
-
inputs = {
|
| 229 |
-
"text": torch.randn(2, 128),
|
| 230 |
-
"image": torch.randn(2, 128),
|
| 231 |
-
"audio": torch.randn(2, 128),
|
| 232 |
-
"video": torch.randn(2, 128),
|
| 233 |
-
}
|
| 234 |
-
routed = router(inputs)
|
| 235 |
-
# FusionLayer.forward(modality_embs: list) — espera lista
|
| 236 |
-
embs = [torch.randn(2, 128) for _ in range(4)]
|
| 237 |
-
fused = fusion(embs)
|
| 238 |
-
results["modal_router_fusion"] = {"ok": True,
|
| 239 |
-
"router_shape": str(tuple(routed.shape)),
|
| 240 |
-
"fusion_shape": str(tuple(fused.shape))}
|
| 241 |
-
logger.info(f" ModalRouter OK: {tuple(routed.shape)} | Fusion OK: {tuple(fused.shape)}")
|
| 242 |
-
except Exception as e:
|
| 243 |
-
results["modal_router_fusion"] = {"ok": False, "error": str(e)}
|
| 244 |
-
logger.warning(f" ModalRouter/Fusion FAIL: {e}")
|
| 245 |
-
|
| 246 |
-
return results
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
def main():
|
| 250 |
-
logger.info("=" * 70)
|
| 251 |
-
logger.info("BiGRU_T_version V2 — 15M params + HW optimizer + multimodal bug-hunt")
|
| 252 |
-
logger.info("=" * 70)
|
| 253 |
-
|
| 254 |
-
# HF token (do ambiente; será apagado ao final)
|
| 255 |
-
hf_token = os.environ.get("HF_TOKEN") or None
|
| 256 |
-
if hf_token:
|
| 257 |
-
logger.info("HF_TOKEN encontrado no ambiente")
|
| 258 |
-
else:
|
| 259 |
-
logger.info("HF_TOKEN não fornecido (datasets públicos apenas)")
|
| 260 |
-
|
| 261 |
-
# 1. Verificação de OOM-Killer e recursos
|
| 262 |
-
logger.info("\n[1/6] Verificando recursos do sistema...")
|
| 263 |
-
if not check_oom_killer_risk():
|
| 264 |
-
logger.error("Recursos insuficientes. Abortando.")
|
| 265 |
-
sys.exit(1)
|
| 266 |
-
logger.info(f" RSS atual: {get_rss_mb():.1f}MB")
|
| 267 |
-
|
| 268 |
-
# 2. Teste multimodal (bug detection)
|
| 269 |
-
logger.info("\n[2/6] Testando multimodalidade (bug hunting)...")
|
| 270 |
-
mm_results = test_multimodal_encoders()
|
| 271 |
-
mm_ok = sum(1 for v in mm_results.values() if v.get("ok"))
|
| 272 |
-
mm_total = len(mm_results)
|
| 273 |
-
logger.info(f" Multimodal: {mm_ok}/{mm_total} encoders OK")
|
| 274 |
-
|
| 275 |
-
# 3. Config do modelo (12.97M params — max_modules=8, d_model=128)
|
| 276 |
-
logger.info("\n[3/6] Criando UnifiedModel (max_modules=8, d_model=128)...")
|
| 277 |
-
model_config = UnifiedModelConfig(
|
| 278 |
-
vocab_size=16384,
|
| 279 |
-
d_model=128,
|
| 280 |
-
max_seq_len=32,
|
| 281 |
-
pad_token_id=1,
|
| 282 |
-
max_modules=8, # base spec do usuário (8)
|
| 283 |
-
bigru_hidden=32,
|
| 284 |
-
d_transformer=64,
|
| 285 |
-
nhead_tu=4,
|
| 286 |
-
d_ff_tu=128,
|
| 287 |
-
output_dim_u8cell=64,
|
| 288 |
-
cache_len=16,
|
| 289 |
-
d_cache=128,
|
| 290 |
-
nhead_orq=8,
|
| 291 |
-
d_ff_orq=256,
|
| 292 |
-
trainT_dim=128,
|
| 293 |
-
nhead_train=4,
|
| 294 |
-
d_ff_train=256,
|
| 295 |
-
num_layers_train=2,
|
| 296 |
-
hypT_dim=128,
|
| 297 |
-
nhead_hyp=4,
|
| 298 |
-
d_ff_hyp=256,
|
| 299 |
-
num_layers_hyp=2,
|
| 300 |
-
num_bits=8,
|
| 301 |
-
dropout=0.1,
|
| 302 |
-
)
|
| 303 |
-
model, _ = create_unified_model(model_config)
|
| 304 |
-
params = model.count_parameters()
|
| 305 |
-
logger.info(f" params: {params['total']:,} ({params['total_M']:.2f}M)")
|
| 306 |
-
logger.info(f" trainable: {params['trainable']:,} ({params['trainable_M']:.2f}M)")
|
| 307 |
-
aggressive_cleanup(verbose=True)
|
| 308 |
-
|
| 309 |
-
# 4. Tokenizer (usa o pré-treinado do source)
|
| 310 |
-
logger.info("\n[4/6] Carregando tokenizer...")
|
| 311 |
-
from tokenizers import Tokenizer
|
| 312 |
-
tok_path = "/home/z/my-project/source/model_final/tokenizer/tokenizer.json"
|
| 313 |
-
if not Path(tok_path).exists():
|
| 314 |
-
logger.error(f"Tokenizer não encontrado: {tok_path}")
|
| 315 |
-
sys.exit(1)
|
| 316 |
-
tokenizer = Tokenizer.from_file(tok_path)
|
| 317 |
-
logger.info(f" Tokenizer loaded: vocab={tokenizer.get_vocab_size()}")
|
| 318 |
-
|
| 319 |
-
# 5. Smoke test do modelo
|
| 320 |
-
logger.info("\n[5/6] Smoke test do modelo...")
|
| 321 |
-
if not smoke_test_model(model, tokenizer):
|
| 322 |
-
logger.error("Smoke test falhou. Abortando.")
|
| 323 |
-
sys.exit(1)
|
| 324 |
-
aggressive_cleanup(verbose=True)
|
| 325 |
-
|
| 326 |
-
# 6. Carrega datasets (streaming, poucos samples para bug detection)
|
| 327 |
-
logger.info("\n[6/6] Carregando datasets (streaming, poucos samples)...")
|
| 328 |
-
datasets = [
|
| 329 |
-
"CEIA-POSITIVO/ultrachat_br_clustred_balanced_v1",
|
| 330 |
-
]
|
| 331 |
-
max_samples = 8 # poucos samples (bug detection, testes)
|
| 332 |
-
all_samples = []
|
| 333 |
-
t0 = time.time()
|
| 334 |
-
for ds_name in datasets:
|
| 335 |
-
if time.time() - t0 > 180:
|
| 336 |
-
logger.warning(f"Timeout carregando datasets após {len(all_samples)} amostras")
|
| 337 |
-
break
|
| 338 |
-
try:
|
| 339 |
-
count_before = len(all_samples)
|
| 340 |
-
for sample in stream_dataset(ds_name, max_samples=max_samples, hf_token=hf_token):
|
| 341 |
-
all_samples.append(sample)
|
| 342 |
-
if len(all_samples) >= max_samples * len(datasets):
|
| 343 |
-
break
|
| 344 |
-
if time.time() - t0 > 180:
|
| 345 |
-
break
|
| 346 |
-
logger.info(f" {ds_name}: +{len(all_samples)-count_before} samples")
|
| 347 |
-
except Exception as e:
|
| 348 |
-
logger.warning(f" {ds_name} falhou: {e}")
|
| 349 |
-
|
| 350 |
-
if not all_samples:
|
| 351 |
-
logger.error("Nenhuma amostra carregada de nenhum dataset")
|
| 352 |
-
sys.exit(1)
|
| 353 |
-
|
| 354 |
-
logger.info(f"Total: {len(all_samples)} samples em {time.time()-t0:.1f}s")
|
| 355 |
-
|
| 356 |
-
# Split 90/10
|
| 357 |
-
import random
|
| 358 |
-
random.seed(42)
|
| 359 |
-
random.shuffle(all_samples)
|
| 360 |
-
split = max(1, int(0.9 * len(all_samples)))
|
| 361 |
-
train_samples = all_samples[:split]
|
| 362 |
-
val_samples = all_samples[split:] or all_samples[:1]
|
| 363 |
-
logger.info(f" train: {len(train_samples)} | val: {len(val_samples)}")
|
| 364 |
-
|
| 365 |
-
aggressive_cleanup(verbose=True)
|
| 366 |
-
|
| 367 |
-
# Trainer config — HW optimizer + time budget + cleanup agressivo
|
| 368 |
-
trainer_config = TrainerConfig(
|
| 369 |
-
epochs=2,
|
| 370 |
-
datasets=",".join(datasets),
|
| 371 |
-
max_samples_per_dataset=max_samples,
|
| 372 |
-
max_seq_len=32,
|
| 373 |
-
per_device_batch_size=1,
|
| 374 |
-
grad_accum=2,
|
| 375 |
-
lr=1e-3,
|
| 376 |
-
optimizer_type="hamiltonian_wasserstein", # ATIVADO
|
| 377 |
-
hw_lr_amp=0.3,
|
| 378 |
-
hw_lr_freq=0.01,
|
| 379 |
-
hw_sigma_w=1.0,
|
| 380 |
-
hw_sigma_rep=0.1,
|
| 381 |
-
hw_prune_every_n=0, # pruning off para bug detection
|
| 382 |
-
use_hypothesis=True,
|
| 383 |
-
stop_grad_hyp=True,
|
| 384 |
-
meta_interval=5,
|
| 385 |
-
max_total_time_s=1800.0, # 30 min total
|
| 386 |
-
max_per_epoch_s=900.0, # 15 min/epoch
|
| 387 |
-
cleanup_every_n_steps=5,
|
| 388 |
-
log_every=1,
|
| 389 |
-
save_temp_every=3, # salvar a cada 3 steps (garante checkpoint mesmo se OOM no fim)
|
| 390 |
-
output_dir="/home/z/my-project/BiGRU_T_version/model_final",
|
| 391 |
-
temp_dir="/home/z/my-project/BiGRU_T_version/_temp_checkpoints",
|
| 392 |
-
keep_temp=False,
|
| 393 |
-
ram_threshold_pct=90.0,
|
| 394 |
-
disk_min_free_gb=1.0,
|
| 395 |
-
loss_patience=30,
|
| 396 |
-
)
|
| 397 |
-
|
| 398 |
-
trainer = BiGRU_T_Trainer(
|
| 399 |
-
model=model,
|
| 400 |
-
tokenizer=tokenizer,
|
| 401 |
-
config=trainer_config,
|
| 402 |
-
train_samples=train_samples,
|
| 403 |
-
val_samples=val_samples,
|
| 404 |
-
)
|
| 405 |
-
|
| 406 |
-
# Treino
|
| 407 |
-
result = trainer.train()
|
| 408 |
-
|
| 409 |
-
# Salva resultados extras (multimodal + smoke)
|
| 410 |
-
extra_report = {
|
| 411 |
-
"multimodal_test": mm_results,
|
| 412 |
-
"smoke_test": {"passed": True},
|
| 413 |
-
"config": {
|
| 414 |
-
"max_modules": model_config.max_modules,
|
| 415 |
-
"d_model": model_config.d_model,
|
| 416 |
-
"bigru_hidden": model_config.bigru_hidden,
|
| 417 |
-
"d_transformer": model_config.d_transformer,
|
| 418 |
-
"params_total": params["total"],
|
| 419 |
-
"params_M": params["total_M"],
|
| 420 |
-
"optimizer": "hamiltonian_wasserstein",
|
| 421 |
-
},
|
| 422 |
-
}
|
| 423 |
-
extra_path = Path("/home/z/my-project/BiGRU_T_version/multimodal_report.json")
|
| 424 |
-
with open(extra_path, "w") as f:
|
| 425 |
-
json.dump(extra_report, f, indent=2, default=str)
|
| 426 |
-
logger.info(f"Relatório multimodal salvo: {extra_path}")
|
| 427 |
-
|
| 428 |
-
print("\n=== Resultado Final ===")
|
| 429 |
-
print(json.dumps(result, indent=2, default=str))
|
| 430 |
-
|
| 431 |
-
# Apaga HF token
|
| 432 |
-
if "HF_TOKEN" in os.environ:
|
| 433 |
-
del os.environ["HF_TOKEN"]
|
| 434 |
-
logger.info("HF_TOKEN apagado do ambiente")
|
| 435 |
-
|
| 436 |
-
sys.exit(0 if not result.get("killed") else 1)
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
if __name__ == "__main__":
|
| 440 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|