Download inference_code/inference/pruning/original_structured.py from Agnes-AI/Agnes-Video-2.0-MoE: direct link, hf CLI and curl.
- Browser
- Download file 4.02 kB
-
https://huggingface.co/Agnes-AI/Agnes-Video-2.0-MoE/resolve/main/inference_code/inference/pruning/original_structured.py
- Command line
-
hf download hf://Agnes-AI/Agnes-Video-2.0-MoE/inference_code/inference/pruning/original_structured.py
-
curl -L -o original_structured.py https://huggingface.co/Agnes-AI/Agnes-Video-2.0-MoE/resolve/main/inference_code/inference/pruning/original_structured.py
4.02 kB
| """Original Wanda/SparseGPT importance adapted to SwiGLU mid-neuron groups. | |
| The algorithms remain unstructured at the score level, but the selected | |
| coordinates are removed as complete SwiGLU neurons so checkpoint shapes shrink. | |
| """ | |
| from __future__ import annotations | |
| import torch | |
| def wanda_mid_scores(energy: torch.Tensor, down_weight: torch.Tensor) -> torch.Tensor: | |
| """Return classic Wanda scores for V/A/T and each SwiGLU mid coordinate.""" | |
| if energy.ndim != 2 or energy.shape[0] != 3: | |
| raise ValueError(f"energy must be [3, d_int], got {tuple(energy.shape)}") | |
| if down_weight.ndim != 2 or down_weight.shape[1] != energy.shape[1]: | |
| raise ValueError( | |
| f"down_weight must be [hidden, {energy.shape[1]}], got {tuple(down_weight.shape)}" | |
| ) | |
| col_norm = down_weight.detach().float().norm(dim=0) | |
| return col_norm.unsqueeze(0) * energy.detach().float().clamp_min(0).sqrt() | |
| def _damped_hinv(gram: torch.Tensor, percdamp: float) -> torch.Tensor: | |
| """Upper-triangular Cholesky factor of damped H^{-1} (miniSeedance SparseGPT).""" | |
| if gram.ndim != 2 or gram.shape[0] != gram.shape[1]: | |
| raise ValueError(f"gram must be square, got {tuple(gram.shape)}") | |
| h = gram.detach().float().clone() | |
| h = (h + h.T) * 0.5 | |
| diag = torch.diag(h) | |
| dead = diag == 0 | |
| if bool(dead.any()): | |
| ids = torch.arange(h.shape[0], device=h.device) | |
| h[ids[dead], ids[dead]] = 1.0 | |
| diag = torch.diag(h) | |
| damping = float(percdamp) * diag.clamp_min(1e-8).mean() | |
| ids = torch.arange(h.shape[0], device=h.device) | |
| inv = None | |
| for _ in range(8): | |
| trial = h.clone() | |
| trial[ids, ids] += damping | |
| chol, info = torch.linalg.cholesky_ex(trial) | |
| if int(info.max()) == 0: | |
| inv = torch.cholesky_inverse(chol) | |
| break | |
| damping *= 10.0 | |
| if inv is None: | |
| raise torch.linalg.LinAlgError("unable to stabilize Gram matrix for SparseGPT") | |
| return torch.linalg.cholesky(inv, upper=True) | |
| def sparsegpt_mid_scores( | |
| gram: torch.Tensor, | |
| energy: torch.Tensor, | |
| down_weight: torch.Tensor, | |
| percdamp: float = 0.01, | |
| ) -> torch.Tensor: | |
| """Return OBS/SparseGPT salience for grouped SwiGLU mid coordinates.""" | |
| if energy.ndim != 2 or energy.shape[0] != 3: | |
| raise ValueError(f"energy must be [3, d_int], got {tuple(energy.shape)}") | |
| if down_weight.ndim != 2 or down_weight.shape[1] != energy.shape[1]: | |
| raise ValueError( | |
| f"down_weight must be [hidden, {energy.shape[1]}], got {tuple(down_weight.shape)}" | |
| ) | |
| hinv = _damped_hinv(gram, percdamp) | |
| d = torch.diag(hinv).clamp_min(1e-8) | |
| base = down_weight.detach().float().pow(2).sum(dim=0) / d.pow(2) | |
| return energy.detach().float().clamp_min(0) * base.unsqueeze(0) | |
| def sparsegpt_compensate_down( | |
| down_weight: torch.Tensor, | |
| gram: torch.Tensor, | |
| keep_idx: torch.Tensor, | |
| percdamp: float = 0.01, | |
| eps: float = 1e-8, | |
| ) -> torch.Tensor: | |
| """OBS-style compensation on down_proj before physical slice (miniSeedance SparseGPT).""" | |
| keep_idx = keep_idx.long() | |
| w = down_weight.detach().clone().float() | |
| d_int = w.shape[1] | |
| keep_set = set(keep_idx.tolist()) | |
| drop = [i for i in range(d_int) if i not in keep_set] | |
| if not drop: | |
| return w.to(down_weight.dtype) | |
| work = gram.device | |
| if work.type == "cpu" and torch.cuda.is_available(): | |
| work = torch.device("cuda") | |
| w = w.to(work) | |
| gram = gram.to(work) | |
| hinv = _damped_hinv(gram, percdamp) | |
| d_diag = torch.diag(hinv).clamp_min(eps) | |
| importance = w.pow(2).sum(dim=0) / d_diag.pow(2) | |
| drop_t = torch.tensor(drop, device=w.device, dtype=torch.long) | |
| drop_sorted = drop_t[torch.argsort(importance[drop_t])] | |
| for i in drop_sorted.tolist(): | |
| col = w[:, i] | |
| d = hinv[i, i] | |
| err = col / d | |
| w[:, i:] -= err.unsqueeze(1).matmul(hinv[i, i:].unsqueeze(0)) | |
| w[:, i] = 0 | |
| return w.to(device=down_weight.device, dtype=down_weight.dtype) | |