PowerMachine commited on
Commit
a5981f0
·
verified ·
1 Parent(s): 294fdee

Delete training/auto_learner.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. training/auto_learner.py +0 -301
training/auto_learner.py DELETED
@@ -1,301 +0,0 @@
1
- """auto_learner.py — Auto-aprendizado: ajuste dinâmico de LR e controle de gradiente.
2
-
3
- Implementa as seções 9-10 de dados.txt:
4
-
5
- 9. AJUSTE DINÂMICO DAS TAXAS DE APRENDIZADO:
6
- fator_G = exp(-κ * ||grad_G||) * (1 + v_media) / 2
7
- novo_eta_G = eta_G * fator_G
8
-
9
- fator_V = exp(-κ * ||grad_V||) * (1 + L_V_media)^{-1}
10
- novo_eta_V = eta_V * fator_V
11
-
12
- 10. CONTROLE DE EXPLOSÃO DE GRADIENTE E ESPECTRAL NORM:
13
- - clip_grad_norm_(params, GRAD_CLIP)
14
- - Spectral normalization (power iteration) para Conv1D e Linear
15
- """
16
- from __future__ import annotations
17
-
18
- import logging
19
- import math
20
- from dataclasses import dataclass
21
- from typing import Dict, List, Optional, Tuple
22
-
23
- import torch
24
- import torch.nn as nn
25
-
26
- logger = logging.getLogger(__name__)
27
-
28
-
29
- @dataclass
30
- class AutoLearnConfig:
31
- """Configuração do auto-aprendizado."""
32
- kappa_curv: float = 0.01 # κ — fator de ajuste de η com norma do gradiente
33
- grad_clip: float = 1.0 # τ — clipping de gradiente (norma L2)
34
- spectral_radius: float = 1.0 # limite para norma espectral
35
- lr_min: float = 1e-6 # LR mínimo
36
- lr_max: float = 1e-2 # LR máximo
37
- initial_lr_G: float = 1e-3 # LR inicial do gerador
38
- initial_lr_V: float = 1e-3 # LR inicial do verificador
39
- use_spectral_norm: bool = True
40
- apply_after_step: bool = True
41
- # NOVO: peso L2 usado pelo otimizador AdamW (corresponde a L2_REG do dados.txt)
42
- l2_reg: float = 1e-5
43
- # NOVO: potências de iteração para spectral norm (1 era muito pouco)
44
- spectral_n_iters: int = 1
45
- # NOVO: device padrão para buffers internos
46
- device: str = "cpu"
47
-
48
-
49
- class AutoLearner:
50
- """Controla ajuste dinâmico de LR, clipping e spectral norm.
51
-
52
- Não é um nn.Module — é um controlador que atua sobre modelos externos.
53
- """
54
-
55
- def __init__(self, config: AutoLearnConfig):
56
- self.cfg = config
57
- self.current_lr_G = config.initial_lr_G
58
- self.current_lr_V = config.initial_lr_V
59
- self.history: List[Dict] = []
60
-
61
- def compute_total_grad_norm(self, model: nn.Module) -> float:
62
- """Calcula a norma L2 total dos gradientes do modelo."""
63
- total = 0.0
64
- for p in model.parameters():
65
- if p.grad is not None:
66
- total += p.grad.data.norm(2).item() ** 2
67
- return math.sqrt(total)
68
-
69
- def update_learning_rates(
70
- self,
71
- grad_G_norm: float,
72
- grad_V_norm: float,
73
- v_mean: float,
74
- L_V_mean: float,
75
- ) -> Tuple[float, float]:
76
- """Atualiza dinamicamente as taxas de aprendizado.
77
-
78
- Args:
79
- grad_G_norm: norma L2 do gradiente do gerador
80
- grad_V_norm: norma L2 do gradiente do verificador
81
- v_mean: média das probabilidades do verificador
82
- L_V_mean: perda média do verificador
83
-
84
- Returns:
85
- (novo_eta_G, novo_eta_V)
86
- """
87
- # Fator do gerador: exp(-κ * ||grad||) * (1 + v_media) / 2
88
- fator_G = math.exp(-self.cfg.kappa_curv * grad_G_norm) * ((1.0 + v_mean) / 2.0)
89
- novo_eta_G = self.current_lr_G * fator_G
90
-
91
- # Fator do verificador: exp(-κ * ||grad||) * (1 + L_V)^{-1}
92
- # Evita divisão por zero
93
- fator_V = math.exp(-self.cfg.kappa_curv * grad_V_norm) / max(1.0 + L_V_mean, 1e-6)
94
- novo_eta_V = self.current_lr_V * fator_V
95
-
96
- # Clamp para evitar valores absurdos
97
- novo_eta_G = max(self.cfg.lr_min, min(self.cfg.lr_max, novo_eta_G))
98
- novo_eta_V = max(self.cfg.lr_min, min(self.cfg.lr_max, novo_eta_V))
99
-
100
- self.current_lr_G = novo_eta_G
101
- self.current_lr_V = novo_eta_V
102
-
103
- self.history.append({
104
- "lr_G": novo_eta_G,
105
- "lr_V": novo_eta_V,
106
- "grad_G_norm": grad_G_norm,
107
- "grad_V_norm": grad_V_norm,
108
- "v_mean": v_mean,
109
- "L_V_mean": L_V_mean,
110
- })
111
-
112
- return novo_eta_G, novo_eta_V
113
-
114
- def apply_clipping(self, *models: nn.Module) -> None:
115
- """Aplica gradient clipping global nos modelos."""
116
- for model in models:
117
- if model is not None:
118
- torch.nn.utils.clip_grad_norm_(model.parameters(), self.cfg.grad_clip)
119
-
120
- def apply_spectral_norm(self, model: nn.Module) -> int:
121
- """Aplica normalização espectral via power iteration em Conv1d/Linear.
122
-
123
- Após cada step, força ||W||_2 <= spectral_radius.
124
-
125
- CORREÇÃO: O bug original armazenava `module._spec_u` como atributo
126
- comum (não buffer), que NÃO migra com `.to(device)`. Agora usamos
127
- `register_buffer` na primeira chamada para garantir movimentação
128
- corta com o device do modelo.
129
- """
130
- if not self.cfg.use_spectral_norm:
131
- return 0
132
- n_normalized = 0
133
- for module in model.modules():
134
- if isinstance(module, (nn.Linear, nn.Conv1d, nn.Conv2d)):
135
- if module.weight is not None and module.weight.dim() >= 2:
136
- try:
137
- with torch.no_grad():
138
- # Power iteration (n_iters iterações)
139
- W = module.weight
140
- # Reshape para 2D se necessário
141
- W_flat = W.reshape(W.size(0), -1)
142
- # u, v aleatórios (ou reutiliza se já existe)
143
- buffer_name = "_spec_u"
144
- if not hasattr(module, buffer_name):
145
- u = torch.randn(W_flat.size(0), 1, device=W.device, dtype=W.dtype)
146
- u = u / u.norm().clamp(min=1e-8)
147
- # Registrar como buffer (move com .to(device))
148
- module.register_buffer(buffer_name, u, persistent=False)
149
- else:
150
- u = getattr(module, buffer_name)
151
- # Garantir que está no device correto
152
- if u.device != W.device:
153
- u = u.to(W.device)
154
- setattr(module, buffer_name, u)
155
- # n_iters iterações de power iteration
156
- for _ in range(self.cfg.spectral_n_iters):
157
- v = torch.matmul(W_flat.T, u)
158
- v = v / v.norm().clamp(min=1e-8)
159
- u = torch.matmul(W_flat, v)
160
- u = u / u.norm().clamp(min=1e-8)
161
- # Atualizar buffer (in-place para manter no mesmo device)
162
- u_new = u.detach()
163
- getattr(module, buffer_name).copy_(u_new)
164
- sigma = (u.T @ W_flat @ v).item()
165
- if sigma > self.cfg.spectral_radius and sigma > 0:
166
- scale = self.cfg.spectral_radius / sigma
167
- module.weight.data.mul_(scale)
168
- n_normalized += 1
169
- except Exception as e:
170
- logger.debug("Spectral norm falhou em %s: %s", type(module).__name__, e)
171
- return n_normalized
172
-
173
- def set_optimizer_lr(self, optimizer: torch.optim.Optimizer, lr: float) -> None:
174
- """Atualiza a taxa de aprendizado de um otimizador."""
175
- for pg in optimizer.param_groups:
176
- pg["lr"] = lr
177
-
178
-
179
- def orthogonal_init_model(model: nn.Module) -> int:
180
- """Aplica inicialização ortogonal em todas as camadas Linear/Conv/GRUCell."""
181
- n = 0
182
- for module in model.modules():
183
- if isinstance(module, (nn.Linear, nn.Conv1d, nn.Conv2d)):
184
- try:
185
- nn.init.orthogonal_(module.weight)
186
- if module.bias is not None:
187
- nn.init.zeros_(module.bias)
188
- n += 1
189
- except Exception:
190
- pass
191
- elif isinstance(module, (nn.GRUCell, nn.GRU, nn.LSTM)):
192
- for name, p in module.named_parameters():
193
- if "weight" in name and p.dim() >= 2:
194
- try:
195
- nn.init.orthogonal_(p)
196
- n += 1
197
- except Exception:
198
- pass
199
- elif "bias" in name:
200
- nn.init.zeros_(p)
201
- return n
202
-
203
-
204
- def estimate_curvature(
205
- model: nn.Module,
206
- loss_fn,
207
- *args,
208
- eps: float = 1e-3,
209
- n_samples: int = 5,
210
- ) -> torch.Tensor:
211
- """Estima curvatura da perda via diferenças finitas.
212
-
213
- Para uma amostra de parâmetros, calcula:
214
- curv ≈ (L(θ + ε) - 2L(θ) + L(θ - ε)) / ε²
215
-
216
- Retorna a média das estimativas.
217
-
218
- CORREÇÃO: O bug original mutava `flat[i]` in-place sem try/finally,
219
- corrompendo o modelo se uma exceção ocorresse entre `+eps` e o restore.
220
- Agora usamos try/finally para garantir restauração sempre.
221
- """
222
- curvatures = []
223
- params = [p for p in model.parameters() if p.requires_grad and p.dim() >= 2]
224
- if not params:
225
- # Device-safe zero
226
- try:
227
- device = next(model.parameters()).device
228
- except StopIteration:
229
- device = torch.device("cpu")
230
- return torch.zeros((), device=device)
231
-
232
- # Subamostra
233
- n_samples = min(n_samples, len(params))
234
- indices = torch.randperm(len(params))[:n_samples]
235
-
236
- for idx in indices:
237
- p = params[idx]
238
- # Pega um elemento aleatório
239
- flat = p.data.view(-1)
240
- if flat.numel() == 0:
241
- continue
242
- i = torch.randint(0, flat.numel(), (1,)).item()
243
- orig = flat[i].item()
244
-
245
- # TRY/FINALLY para garantir restauração sempre
246
- try:
247
- with torch.no_grad():
248
- # L(θ)
249
- try:
250
- loss_0 = loss_fn(*args)
251
- if isinstance(loss_0, dict):
252
- loss_0 = loss_0["total"]
253
- loss_0 = float(loss_0)
254
- except Exception as e:
255
- logger.debug("curvature L(θ) falhou: %s", e)
256
- continue
257
-
258
- # L(θ + ε)
259
- flat[i] = orig + eps
260
- try:
261
- loss_p = loss_fn(*args)
262
- if isinstance(loss_p, dict):
263
- loss_p = loss_p["total"]
264
- loss_p = float(loss_p)
265
- except Exception as e:
266
- logger.debug("curvature L(θ+ε) falhou: %s", e)
267
- continue
268
-
269
- # L(θ - ε)
270
- flat[i] = orig - eps
271
- try:
272
- loss_m = loss_fn(*args)
273
- if isinstance(loss_m, dict):
274
- loss_m = loss_m["total"]
275
- loss_m = float(loss_m)
276
- except Exception as e:
277
- logger.debug("curvature L(θ-ε) falhou: %s", e)
278
- continue
279
-
280
- curv = (loss_p - 2 * loss_0 + loss_m) / (eps ** 2)
281
- curvatures.append(curv)
282
- finally:
283
- # SEMPRE restaurar o valor original
284
- flat[i] = orig
285
-
286
- if not curvatures:
287
- try:
288
- device = next(model.parameters()).device
289
- except StopIteration:
290
- device = torch.device("cpu")
291
- return torch.zeros((), device=device)
292
-
293
- return torch.tensor(sum(curvatures) / len(curvatures))
294
-
295
-
296
- __all__ = [
297
- "AutoLearnConfig",
298
- "AutoLearner",
299
- "orthogonal_init_model",
300
- "estimate_curvature",
301
- ]