Spaces:
Sleeping
Sleeping
| """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) | |
| 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] | |