Delete src/bigru_t/model/gru_hierarchy.py
Browse files
src/bigru_t/model/gru_hierarchy.py
DELETED
|
@@ -1,82 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Xavante - gru_hierarchy.py
|
| 3 |
-
Responsabilidade: GRU hierarquica (Teorema 7.1/7.2). Reutiliza o FlexGRU
|
| 4 |
-
validado do FlexNet.
|
| 5 |
-
"""
|
| 6 |
-
from __future__ import annotations
|
| 7 |
-
|
| 8 |
-
import logging
|
| 9 |
-
from typing import List, Optional
|
| 10 |
-
|
| 11 |
-
import torch
|
| 12 |
-
import torch.nn as nn
|
| 13 |
-
|
| 14 |
-
logger = logging.getLogger(__name__)
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
class FlexGRUCell(nn.Module):
|
| 18 |
-
"""GRU cell com gate extra de confianca (h_t) que escala update."""
|
| 19 |
-
|
| 20 |
-
def __init__(self, d_in: int, d_hidden: int):
|
| 21 |
-
super().__init__()
|
| 22 |
-
self.d_in = d_in
|
| 23 |
-
self.d_hidden = d_hidden
|
| 24 |
-
# Linear concatenado x_t e h_{t-1}
|
| 25 |
-
self.x2h = nn.Linear(d_in, 3 * d_hidden, bias=True)
|
| 26 |
-
self.h2h = nn.Linear(d_hidden, 3 * d_hidden, bias=True)
|
| 27 |
-
# Confidence gate
|
| 28 |
-
self.conf_gate = nn.Linear(d_in + d_hidden, 1)
|
| 29 |
-
|
| 30 |
-
def forward(self, x: torch.Tensor, h: Optional[torch.Tensor] = None) -> torch.Tensor:
|
| 31 |
-
B, D = x.shape
|
| 32 |
-
if h is None:
|
| 33 |
-
h = torch.zeros(B, self.d_hidden, device=x.device, dtype=x.dtype)
|
| 34 |
-
gates_x = self.x2h(x)
|
| 35 |
-
gates_h = self.h2h(h)
|
| 36 |
-
x_r, x_z, x_n = gates_x.chunk(3, dim=-1)
|
| 37 |
-
h_r, h_z, h_n = gates_h.chunk(3, dim=-1)
|
| 38 |
-
r = torch.sigmoid(x_r + h_r)
|
| 39 |
-
z = torch.sigmoid(x_z + h_z)
|
| 40 |
-
n = torch.tanh(x_n + r * h_n)
|
| 41 |
-
# Confidence scaling (Teorema 17.1)
|
| 42 |
-
c = torch.sigmoid(self.conf_gate(torch.cat([x, h], dim=-1)))
|
| 43 |
-
h_new = (1 - z * c) * h + (z * c) * n
|
| 44 |
-
return h_new
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
class GRUHierarchy(nn.Module):
|
| 48 |
-
"""GRU hierarquica em L niveis (Teorema 7.1/7.2)."""
|
| 49 |
-
|
| 50 |
-
def __init__(self, d_model: int, d_hidden: int, n_levels: int = 3):
|
| 51 |
-
super().__init__()
|
| 52 |
-
self.n_levels = n_levels
|
| 53 |
-
self.cells = nn.ModuleList(
|
| 54 |
-
[FlexGRUCell(d_model if i == 0 else d_hidden, d_hidden) for i in range(n_levels)]
|
| 55 |
-
)
|
| 56 |
-
# Projecao de saida de cada nivel
|
| 57 |
-
self.projs = nn.ModuleList([nn.Linear(d_hidden, d_model) for _ in range(n_levels)])
|
| 58 |
-
|
| 59 |
-
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 60 |
-
"""
|
| 61 |
-
x: [B, L, d_model]
|
| 62 |
-
Retorna: [B, L, d_model]
|
| 63 |
-
"""
|
| 64 |
-
B, L, D = x.shape
|
| 65 |
-
h_states: List[Optional[torch.Tensor]] = [None] * self.n_levels
|
| 66 |
-
outputs = []
|
| 67 |
-
for t in range(L):
|
| 68 |
-
xt = x[:, t, :]
|
| 69 |
-
inp = xt
|
| 70 |
-
new_h_states = []
|
| 71 |
-
for lvl, cell in enumerate(self.cells):
|
| 72 |
-
h_new = cell(inp, h_states[lvl])
|
| 73 |
-
new_h_states.append(h_new)
|
| 74 |
-
inp = h_new
|
| 75 |
-
h_states = new_h_states
|
| 76 |
-
# Use each level's own projection (fixes dead projections bug)
|
| 77 |
-
combined = sum(self.projs[lvl](h_states[lvl]) for lvl in range(self.n_levels)) / self.n_levels
|
| 78 |
-
outputs.append(combined)
|
| 79 |
-
return torch.stack(outputs, dim=1)
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
__all__ = ["FlexGRUCell", "GRUHierarchy"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|