Download inference_code/inference/pruning/verify.py from Agnes-AI/Agnes-Video-2.0-MoE: direct link, hf CLI and curl.
- Browser
- Download file 8.87 kB
-
https://huggingface.co/Agnes-AI/Agnes-Video-2.0-MoE/resolve/main/inference_code/inference/pruning/verify.py
- Command line
-
hf download hf://Agnes-AI/Agnes-Video-2.0-MoE/inference_code/inference/pruning/verify.py
-
curl -L -o verify.py https://huggingface.co/Agnes-AI/Agnes-Video-2.0-MoE/resolve/main/inference_code/inference/pruning/verify.py
8.87 kB
| """Offline diagnostics for signed TENP vs actual removal damage.""" | |
| from __future__ import annotations | |
| import torch | |
| from .collector import perturbation_sensitivity, stacked_token_cache | |
| from .score import PROJ_EPS | |
| def spearman_corr(x: torch.Tensor, y: torch.Tensor, eps: float = 1e-8) -> float: | |
| """Average-rank Spearman. Fine for distinct scores; ties share mid-ranks.""" | |
| a = x.detach().float().reshape(-1) | |
| b = y.detach().float().reshape(-1) | |
| if a.numel() != b.numel() or a.numel() < 3: | |
| return float("nan") | |
| ra = _average_rank(a) | |
| rb = _average_rank(b) | |
| ra = ra - ra.mean() | |
| rb = rb - rb.mean() | |
| denom = (ra.norm() * rb.norm()).clamp_min(eps) | |
| return float((ra * rb).sum() / denom) | |
| def _average_rank(x: torch.Tensor) -> torch.Tensor: | |
| n = int(x.numel()) | |
| order = torch.argsort(x) | |
| ranks = torch.empty(n, device=x.device, dtype=torch.float32) | |
| sorted_x = x[order] | |
| i = 0 | |
| while i < n: | |
| j = i | |
| while j + 1 < n and float(sorted_x[j + 1]) == float(sorted_x[i]): | |
| j += 1 | |
| mid = 0.5 * (i + j) + 1.0 | |
| ranks[order[i : j + 1]] = mid | |
| i = j + 1 | |
| return ranks | |
| def single_neuron_removal_damage( | |
| rel_abs_z: torch.Tensor, | |
| n_tokens: int, | |
| down_weight: torch.Tensor, | |
| ) -> torch.Tensor: | |
| """Mean relative L2 of masking neuron i at expert output (top-1 MoE-equivalent). | |
| During collect we store sum_t |z_{t,i}| / ||y_t||. Then: | |
| Δ_i = (rel_abs_z_i / N) * ||W_down[:, i]||_2 | |
| which equals E_t ||z_i W_i|| / ||y||. | |
| """ | |
| if n_tokens <= 0: | |
| return torch.zeros_like(rel_abs_z, dtype=torch.float32) | |
| col_norm = down_weight.detach().float().norm(dim=0) | |
| return rel_abs_z.detach().float() / float(n_tokens) * col_norm | |
| def group_mean_damage(damage: torch.Tensor, idx: torch.Tensor) -> float: | |
| if idx.numel() == 0: | |
| return float("nan") | |
| return float(damage[idx.long()].mean()) | |
| def group_removal_relative_l2( | |
| z: torch.Tensor, | |
| y: torch.Tensor, | |
| down_weight: torch.Tensor, | |
| idx: torch.Tensor, | |
| eps: float = PROJ_EPS, | |
| ) -> float: | |
| """Exact mean ||sum_{i in G} z_i W_i|| / ||y|| on cached tokens.""" | |
| if idx is None or int(idx.numel()) == 0 or z.numel() == 0: | |
| return float("nan") | |
| keep = idx.detach().long().to(device=z.device) | |
| w = down_weight.detach().to(device=z.device, dtype=torch.float32) | |
| z_f = z.float() | |
| y_n = y.float().norm(dim=-1).clamp_min(eps) | |
| delta = z_f.index_select(1, keep) @ w.index_select(1, keep).T | |
| return float((delta.norm(dim=-1) / y_n).mean()) | |
| def sensitivity_by_bin( | |
| cache_z: list, | |
| cache_y: list, | |
| down_weight: torch.Tensor, | |
| ratios: tuple[float, ...] = (0.05, 0.10), | |
| repeats: int = 3, | |
| seed: int = 0, | |
| ) -> dict[str, list[float]]: | |
| """Offline D^ρ per timestep bin from the token reservoir.""" | |
| gen = torch.Generator(device="cpu") | |
| gen.manual_seed(int(seed)) | |
| out: dict[str, list[float]] = {f"{rho:.2f}": [] for rho in ratios} | |
| n_bins = max(len(cache_z or []), len(cache_y or [])) | |
| for bin_id in range(n_bins): | |
| z = None if cache_z is None or bin_id >= len(cache_z) else cache_z[bin_id] | |
| y = None if cache_y is None or bin_id >= len(cache_y) else cache_y[bin_id] | |
| for rho in ratios: | |
| key = f"{rho:.2f}" | |
| if z is None or y is None or int(z.numel()) == 0: | |
| out[key].append(float("nan")) | |
| continue | |
| out[key].append( | |
| perturbation_sensitivity(z, y, down_weight, rho, repeats, gen) | |
| ) | |
| return out | |
| def redundancy_pair_causal( | |
| z: torch.Tensor, | |
| y: torch.Tensor, | |
| down_weight: torch.Tensor, | |
| score: torch.Tensor, | |
| r_plus: torch.Tensor | None = None, | |
| gram: torch.Tensor | None = None, | |
| n_cand: int = 256, | |
| n_pairs: int = 16, | |
| seed: int = 0, | |
| ) -> dict: | |
| """Compare high-R vs low-R pairs: additivity = Δij / (Δi+Δj). | |
| Same-direction (redundant) pairs add constructively, so additivity is | |
| closer to 1 than for near-orthogonal controls with similar TENP scores. | |
| """ | |
| from .redundancy import contribution_redundancy | |
| s = score.detach().float().reshape(-1) | |
| pos = (s > 0).nonzero(as_tuple=False).reshape(-1) | |
| if int(pos.numel()) < 4 or z.numel() == 0: | |
| return {"skipped": "need cached tokens and >=4 positive-score neurons"} | |
| k = min(int(n_cand), int(pos.numel())) | |
| _, local = torch.topk(s[pos], k) | |
| idx = pos[local] | |
| if r_plus is not None: | |
| sub = r_plus.detach().float()[idx][:, idx].clone() | |
| else: | |
| g_sub = None if gram is None else gram.detach().float()[idx][:, idx] | |
| sub = contribution_redundancy(g_sub, down_weight.detach().float()[:, idx]) | |
| sub.fill_diagonal_(0) | |
| tri_i, tri_j = torch.triu_indices(k, k, offset=1) | |
| r_flat = sub[tri_i, tri_j] | |
| if int(r_flat.numel()) < 2: | |
| return {"skipped": "not enough pairs"} | |
| n_take = min(int(n_pairs), int(r_flat.numel())) | |
| high_sel = torch.topk(r_flat, n_take).indices | |
| low_sel = torch.topk(-r_flat, n_take).indices | |
| def _pack(sel: torch.Tensor) -> dict: | |
| additivities = [] | |
| overlaps = [] | |
| r_vals = [] | |
| for t in sel.tolist(): | |
| li = int(tri_i[t]) | |
| lj = int(tri_j[t]) | |
| a = int(idx[li].item()) | |
| b = int(idx[lj].item()) | |
| di = group_removal_relative_l2(z, y, down_weight, torch.tensor([a])) | |
| dj = group_removal_relative_l2(z, y, down_weight, torch.tensor([b])) | |
| both = group_removal_relative_l2(z, y, down_weight, torch.tensor([a, b])) | |
| denom = di + dj | |
| additivity = float("nan") if denom <= 0 else float(both / denom) | |
| overlap = float("nan") if denom <= 0 else float((denom - both) / denom) | |
| additivities.append(additivity) | |
| overlaps.append(overlap) | |
| r_vals.append(float(sub[li, lj])) | |
| finite_a = [x for x in additivities if x == x] | |
| finite_o = [x for x in overlaps if x == x] | |
| return { | |
| "n_pairs": len(additivities), | |
| "r_mean": round(float(sum(r_vals) / max(len(r_vals), 1)), 4), | |
| "additivity_mean": ( | |
| round(float(sum(finite_a) / len(finite_a)), 4) if finite_a else float("nan") | |
| ), | |
| "overlap_mean": ( | |
| round(float(sum(finite_o) / len(finite_o)), 4) if finite_o else float("nan") | |
| ), | |
| } | |
| del seed | |
| high = _pack(high_sel) | |
| low = _pack(low_sel) | |
| return { | |
| "high_r": high, | |
| "low_r": low, | |
| "additivity_gap": _finite_gap(high, low, "additivity_mean"), | |
| "overlap_gap": _finite_gap(high, low, "overlap_mean"), | |
| "note": "aligned/redundant pairs have additivity Δij/(Δi+Δj) closer to 1", | |
| } | |
| def _finite_gap(high: dict, low: dict, key: str) -> float: | |
| a = high.get(key) | |
| b = low.get(key) | |
| if not isinstance(a, float) or not isinstance(b, float): | |
| return float("nan") | |
| if a != a or b != b: | |
| return float("nan") | |
| return round(float(a - b), 4) | |
| def cache_group_report( | |
| stats, | |
| down_weight: torch.Tensor, | |
| signed: torch.Tensor, | |
| damage: torch.Tensor, | |
| frac: float = 0.10, | |
| ) -> dict: | |
| """Exact group-removal Δ on the reservoir vs mean of single-neuron Δ.""" | |
| n_bot = max(1, int(round(float(frac) * int(signed.numel())))) | |
| bot = torch.topk(signed, n_bot, largest=False).indices | |
| top = torch.topk(signed, n_bot, largest=True).indices | |
| packed = stacked_token_cache(stats) | |
| rec = { | |
| "approx_mean_delta": { | |
| "lowest_signed_10pct": round(group_mean_damage(damage, bot), 6), | |
| "highest_signed_10pct": round(group_mean_damage(damage, top), 6), | |
| } | |
| } | |
| if packed is None: | |
| rec["exact_group_delta"] = {"skipped": "missing token cache; re-collect"} | |
| rec["sensitivity_rho"] = {"skipped": "missing token cache; re-collect"} | |
| rec["redundancy_pairs"] = {"skipped": "missing token cache; re-collect"} | |
| return rec | |
| z, y, _gate = packed | |
| rec["n_cached_tokens"] = int(z.shape[0]) | |
| rec["exact_group_delta"] = { | |
| "lowest_signed_10pct": round( | |
| group_removal_relative_l2(z, y, down_weight, bot), 6 | |
| ), | |
| "highest_signed_10pct": round( | |
| group_removal_relative_l2(z, y, down_weight, top), 6 | |
| ), | |
| } | |
| rec["sensitivity_rho"] = sensitivity_by_bin( | |
| stats.cache_z or [], | |
| stats.cache_y or [], | |
| down_weight, | |
| ratios=(0.05, 0.10), | |
| ) | |
| d5 = torch.tensor(rec["sensitivity_rho"]["0.05"], dtype=torch.float32) | |
| d10 = torch.tensor(rec["sensitivity_rho"]["0.10"], dtype=torch.float32) | |
| live = torch.isfinite(d5) & torch.isfinite(d10) | |
| rec["spearman_d05_vs_d10"] = ( | |
| round(spearman_corr(d5[live], d10[live]), 4) if int(live.sum()) >= 3 else float("nan") | |
| ) | |
| return rec | |