angular-separation-vit-demo / src /nucleo_lectura.py
ManPla's picture
v6.0: la demo viva sustituye a la galeria estatica, en la misma URL
4d362a0 verified
Raw
History Blame Contribute Delete
2.26 kB
"""núcleo de lectura: svd exacta y decisión de poda, sin dependencias.
`firma_exacta` y `decisiones` las comparten el aparato del paper y la
demo. vivían en `scripts/run_fase_G.py` y `scripts/decision_rota.py`,
que arrastran timm y pandas por su cadena de imports; aquí solo hace
falta torch, de modo que el Space puede ejecutar **el mismo código**
sin cargar el entorno de investigación entero. los cuerpos son los que
produjeron las tablas 2 y 3, movidos sin tocar una línea.
"""
import torch
K_PODA = 3 # top-k de poda del ancla vit-b (25 % de 12 cabezas)
@torch.no_grad()
def firma_exacta(matriz: torch.Tensor, lado: str) -> torch.Tensor:
"""vector singular dominante por svd exacta (no iteración).
el diagnóstico de invariancia exige svd exacta: medirla con
iteración de potencia introduce ruido de init que la enmascara.
Args:
matriz: tensor [h, m, n] con h matrices.
lado: 'izq' devuelve u[:,0] (en R^m); 'der' devuelve vh[0]
(en R^n).
Returns:
tensor [h, k] con la dirección unitaria por cabeza.
"""
out = []
for h in range(matriz.shape[0]):
u, _, vh = torch.linalg.svd(matriz[h], full_matrices=False)
out.append(u[:, 0] if lado == "izq" else vh[0])
return torch.stack(out)
def decisiones(firmas: torch.Tensor,
k: int) -> tuple[tuple[int, int], list[int]]:
"""par más redundante y top-k de poda desde unas firmas.
Args:
firmas: tensor [h, d] de direcciones unitarias por cabeza.
k: tamaño del conjunto de poda. **sin valor por
defecto a propósito**: un default de módulo hizo
que la columna de lenguaje calculara conjuntos de
3 y dividiera por 4 durante dos versiones del
paper. cada llamante declara el suyo.
Returns:
tupla (par_top ordenado, top-k de cabezas por redundancia
media descendente).
"""
c = (firmas @ firmas.t()).abs().clamp(max=1.0)
c.fill_diagonal_(0.0)
h = c.shape[0]
idx = int(torch.argmax(c).item())
par = tuple(sorted((idx // h, idx % h)))
red_media = c.sum(dim=1) / (h - 1)
topk = torch.argsort(red_media, descending=True)[:k]
return par, [int(i) for i in topk]