Delete src/bigru_t/model/u8cell_t.py
Browse files- src/bigru_t/model/u8cell_t.py +0 -209
src/bigru_t/model/u8cell_t.py
DELETED
|
@@ -1,209 +0,0 @@
|
|
| 1 |
-
"""u8cell_t.py — u8cell_T: módulo especialista com 8 BiGRU4 + TransformerUnit.
|
| 2 |
-
|
| 3 |
-
Componente do Lema 1 (Desacoplamento via atenção hierárquica).
|
| 4 |
-
|
| 5 |
-
Cada u8cell_T é um "módulo especialista" independente. O UnifiedModel
|
| 6 |
-
instanciará até `max_modules` deles e selecionará quais ativar via softmax
|
| 7 |
-
com temperatura controlada (Lema 1).
|
| 8 |
-
|
| 9 |
-
Reaproveita a arquitetura "4 camadas BiGRU cooperativas" do v13.9.2, mas:
|
| 10 |
-
- Cada BiGRU4 contém 4 camadas (vs. 1 cooperative layer no v13.9.2)
|
| 11 |
-
- 8 BiGRU4 paralelas por u8cell_T (vs. 1 GRU stack no v13.9.2)
|
| 12 |
-
- TransformerUnit funde as 8 saídas (vs. Confidence Gate no v13.9.2)
|
| 13 |
-
- Sem Hypothesis Network interna (a hipótese é global, Lema 3)
|
| 14 |
-
- Sem Trust Network interna (o orquestrador global faz o papel, Lema 4)
|
| 15 |
-
|
| 16 |
-
V4 — Aprimoramento da detecção de ativação BiGRU:
|
| 17 |
-
Adiciona `return_aux=True` no forward para retornar métricas de
|
| 18 |
-
paralelismo real e diversificação de dados entre as 8 BiGRU4:
|
| 19 |
-
- `bigru_representations`: lista de (batch, d_transformer) — saídas das 8 BiGRU4
|
| 20 |
-
- `cosine_diversity`: 1 - média(cos_sim entre pares) ∈ [0, 2]
|
| 21 |
-
Alto (próximo de 1) = módulos produzindo representações diversas
|
| 22 |
-
Baixo (próximo de 0) = módulos colapsados (mesma saída)
|
| 23 |
-
- `gate_norm_ratio`: std(||v_i||) / mean(||v_i||) — coef. variação das normas
|
| 24 |
-
Alto = módulos com magnitudes diferentes (especialização de escala)
|
| 25 |
-
Baixo = módulos com mesma magnitude (sem diferenciação)
|
| 26 |
-
- `activation_variance`: variância inter-BiGRU por sample (média sobre batch)
|
| 27 |
-
Alto = diversificação de conteúdo
|
| 28 |
-
Baixo = redundância
|
| 29 |
-
- `parallelism_score`: geom_mean(||v_i||) / mean(||v_i||) — score de paralelismo
|
| 30 |
-
Próximo de 1 = todas as 8 BiGRU contribuem ativamente
|
| 31 |
-
Próximo de 0 = apenas algumas dominam
|
| 32 |
-
|
| 33 |
-
Essas métricas permitem monitorar se os 8 BiGRUs estão realmente trabalhando
|
| 34 |
-
em paralelo com dados diversificados (Lema 1) ou se colapsaram.
|
| 35 |
-
"""
|
| 36 |
-
from __future__ import annotations
|
| 37 |
-
|
| 38 |
-
import torch
|
| 39 |
-
import torch.nn as nn
|
| 40 |
-
import torch.nn.functional as F
|
| 41 |
-
from typing import Optional
|
| 42 |
-
|
| 43 |
-
from .bigru4 import BiGRU4
|
| 44 |
-
from .transformer_unit import TransformerUnit
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
class u8cell_T(nn.Module):
|
| 48 |
-
"""Módulo com 8 BiGRU4 paralelas + TransformerUnit.
|
| 49 |
-
|
| 50 |
-
Args:
|
| 51 |
-
input_dim: dimensão da entrada
|
| 52 |
-
hidden_dim_bigru: dimensão oculta de cada GRU nas BiGRU4
|
| 53 |
-
d_transformer: d_model do TransformerUnit
|
| 54 |
-
nhead: nº de cabeças de atenção do TransformerUnit
|
| 55 |
-
d_ff: dimensão interna do FFN do TransformerUnit
|
| 56 |
-
output_dim: dimensão de saída do u8cell_T
|
| 57 |
-
|
| 58 |
-
Forward (default):
|
| 59 |
-
x: (batch, T, input_dim) → h_out: (batch, output_dim)
|
| 60 |
-
|
| 61 |
-
Forward (return_aux=True):
|
| 62 |
-
→ (h_out, aux_dict) onde aux_dict contém métricas BiGRU (V4)
|
| 63 |
-
"""
|
| 64 |
-
|
| 65 |
-
def __init__(
|
| 66 |
-
self,
|
| 67 |
-
input_dim: int,
|
| 68 |
-
hidden_dim_bigru: int,
|
| 69 |
-
d_transformer: int,
|
| 70 |
-
nhead: int,
|
| 71 |
-
d_ff: int,
|
| 72 |
-
output_dim: int,
|
| 73 |
-
dropout: float = 0.1,
|
| 74 |
-
):
|
| 75 |
-
super().__init__()
|
| 76 |
-
self.input_dim = input_dim
|
| 77 |
-
self.output_dim = output_dim
|
| 78 |
-
self.n_bigru = 8 # Número de BiGRU4 paralelas (constante arquitetural)
|
| 79 |
-
|
| 80 |
-
# 8 BiGRU4 paralelas (cada uma com 4 camadas BiGRU)
|
| 81 |
-
self.bigru_list = nn.ModuleList(
|
| 82 |
-
[BiGRU4(input_dim, hidden_dim_bigru, dropout=dropout) for _ in range(self.n_bigru)]
|
| 83 |
-
)
|
| 84 |
-
bigru_out_dim = 2 * hidden_dim_bigru # bidirecional
|
| 85 |
-
|
| 86 |
-
# Projeção para o d_model do TransformerUnit
|
| 87 |
-
self.proj_in = nn.Linear(bigru_out_dim, d_transformer)
|
| 88 |
-
|
| 89 |
-
# TransformerUnit funde as 8 representações
|
| 90 |
-
self.transformer_unit = TransformerUnit(d_transformer, nhead, d_ff, dropout=dropout)
|
| 91 |
-
|
| 92 |
-
# Projeção final para output_dim
|
| 93 |
-
self.proj_out = nn.Linear(d_transformer, output_dim)
|
| 94 |
-
|
| 95 |
-
def forward(
|
| 96 |
-
self,
|
| 97 |
-
x: torch.Tensor,
|
| 98 |
-
return_aux: bool = False,
|
| 99 |
-
) -> torch.Tensor:
|
| 100 |
-
"""x: (batch, T, input_dim) → h_out: (batch, output_dim)
|
| 101 |
-
|
| 102 |
-
Se return_aux=True, retorna (h_out, aux_dict) com métricas de
|
| 103 |
-
paralelismo e diversificação das 8 BiGRU4 (V4).
|
| 104 |
-
"""
|
| 105 |
-
representations = [] # cada (batch, d_transformer) — saídas projetadas
|
| 106 |
-
bigru_raw = [] # cada (batch, 2*hidden_dim) — saídas brutas das BiGRU4
|
| 107 |
-
|
| 108 |
-
for bigru in self.bigru_list:
|
| 109 |
-
v_i = bigru(x) # (batch, bigru_out_dim)
|
| 110 |
-
v_i_proj = self.proj_in(v_i) # (batch, d_transformer)
|
| 111 |
-
bigru_raw.append(v_i)
|
| 112 |
-
representations.append(v_i_proj)
|
| 113 |
-
|
| 114 |
-
# Empilha as 8 representações: (batch, 8, d_transformer)
|
| 115 |
-
stacked = torch.stack(representations, dim=1)
|
| 116 |
-
|
| 117 |
-
# TransformerUnit → (batch, d_transformer)
|
| 118 |
-
h_unit = self.transformer_unit(stacked)
|
| 119 |
-
|
| 120 |
-
# Projeção final → (batch, output_dim)
|
| 121 |
-
h_out = self.proj_out(h_unit)
|
| 122 |
-
|
| 123 |
-
if not return_aux:
|
| 124 |
-
return h_out
|
| 125 |
-
|
| 126 |
-
# =====================================================================
|
| 127 |
-
# V4: Métricas de paralelismo e diversificação das 8 BiGRU4
|
| 128 |
-
# =====================================================================
|
| 129 |
-
aux = self._compute_bigru_diversity_metrics(representations, bigru_raw)
|
| 130 |
-
return h_out, aux
|
| 131 |
-
|
| 132 |
-
def _compute_bigru_diversity_metrics(
|
| 133 |
-
self,
|
| 134 |
-
representations: list[torch.Tensor],
|
| 135 |
-
bigru_raw: list[torch.Tensor],
|
| 136 |
-
) -> dict:
|
| 137 |
-
"""Computa métricas de paralelismo/diversificação das 8 BiGRU4.
|
| 138 |
-
|
| 139 |
-
Args:
|
| 140 |
-
representations: lista de 8 tensores (batch, d_transformer) — saídas projetadas
|
| 141 |
-
bigru_raw: lista de 8 tensores (batch, 2*hidden_dim) — saídas brutas
|
| 142 |
-
|
| 143 |
-
Returns:
|
| 144 |
-
dict com:
|
| 145 |
-
- cosine_diversity: 1 - mean(cos_sim entre pares) ∈ [0, 2]
|
| 146 |
-
- gate_norm_ratio: std(||v_i||) / mean(||v_i||)
|
| 147 |
-
- activation_variance: variância inter-BiGRU (média sobre batch)
|
| 148 |
-
- parallelism_score: geom_mean(||v_i||) / mean(||v_i||)
|
| 149 |
-
- per_bigru_norms: lista de 8 normas L2 (uma por BiGRU4)
|
| 150 |
-
- bigru_representations: stacked (batch, 8, d_transformer) — para análise externa
|
| 151 |
-
"""
|
| 152 |
-
# Stack para (8, batch, d_transformer) → (8, batch)
|
| 153 |
-
norms = torch.stack(
|
| 154 |
-
[v.norm(p=2, dim=-1) for v in representations], dim=0
|
| 155 |
-
) # (8, batch)
|
| 156 |
-
per_bigru_norms = norms.mean(dim=1) # (8,) — norma média de cada BiGRU4
|
| 157 |
-
|
| 158 |
-
# Stack das representações projetadas: (batch, 8, d_transformer)
|
| 159 |
-
stacked_reps = torch.stack(representations, dim=1)
|
| 160 |
-
|
| 161 |
-
# 1. Cosine diversity: 1 - mean(cos_sim entre pares i<j)
|
| 162 |
-
# representations[i]: (batch, d_transformer)
|
| 163 |
-
# cosine sim(i, j) médio sobre batch
|
| 164 |
-
n = len(representations)
|
| 165 |
-
cos_sims = []
|
| 166 |
-
for i in range(n):
|
| 167 |
-
for j in range(i + 1, n):
|
| 168 |
-
# (batch,) — cosine sim por sample, depois média sobre batch
|
| 169 |
-
cs = F.cosine_similarity(
|
| 170 |
-
representations[i], representations[j], dim=-1
|
| 171 |
-
) # (batch,)
|
| 172 |
-
cos_sims.append(cs.mean())
|
| 173 |
-
if cos_sims:
|
| 174 |
-
mean_cos = torch.stack(cos_sims).mean()
|
| 175 |
-
cosine_diversity = 1.0 - mean_cos
|
| 176 |
-
else:
|
| 177 |
-
cosine_diversity = torch.tensor(0.0, device=representations[0].device)
|
| 178 |
-
|
| 179 |
-
# 2. Gate norm ratio: coef. de variação das normas L2 das 8 BiGRU4
|
| 180 |
-
# Médio sobre batch: usamos per_bigru_norms (já é média sobre batch)
|
| 181 |
-
mean_norm = per_bigru_norms.mean()
|
| 182 |
-
std_norm = per_bigru_norms.std()
|
| 183 |
-
gate_norm_ratio = (std_norm / (mean_norm + 1e-8)).clamp(min=0.0)
|
| 184 |
-
|
| 185 |
-
# 3. Activation variance: variância inter-BiGRU por sample, média sobre batch
|
| 186 |
-
# stacked_raw: (batch, 8, bigru_out_dim)
|
| 187 |
-
stacked_raw = torch.stack(bigru_raw, dim=1) # (batch, 8, bigru_out_dim)
|
| 188 |
-
# variância sobre dim=1 (inter-BiGRU), depois média sobre batch e features
|
| 189 |
-
activation_variance = stacked_raw.var(dim=1).mean()
|
| 190 |
-
|
| 191 |
-
# 4. Parallelism score: geom_mean(||v_i||) / mean(||v_i||) — score ∈ (0, 1]
|
| 192 |
-
# geom_mean próximo de mean → 1.0 (todas contribuem)
|
| 193 |
-
# geom_mean muito menor que mean → algumas BiGRUs dominam
|
| 194 |
-
log_norms = torch.log(per_bigru_norms + 1e-8)
|
| 195 |
-
log_geom_mean = log_norms.mean()
|
| 196 |
-
geom_mean = torch.exp(log_geom_mean)
|
| 197 |
-
parallelism_score = (geom_mean / (mean_norm + 1e-8)).clamp(min=0.0, max=1.0)
|
| 198 |
-
|
| 199 |
-
return {
|
| 200 |
-
"cosine_diversity": float(cosine_diversity.item()),
|
| 201 |
-
"gate_norm_ratio": float(gate_norm_ratio.item()),
|
| 202 |
-
"activation_variance": float(activation_variance.item()),
|
| 203 |
-
"parallelism_score": float(parallelism_score.item()),
|
| 204 |
-
"per_bigru_norms": [float(x.item()) for x in per_bigru_norms],
|
| 205 |
-
# V4: NÃO retornar bigru_representations (consome RAM nos K módulos)
|
| 206 |
-
# A diversidade INTER-módulos é computada no UnifiedModel usando
|
| 207 |
-
# h_k (saída do u8cell_T), não as representações internas.
|
| 208 |
-
# "bigru_representations": stacked_reps.detach(), # comentado para economizar RAM
|
| 209 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|