Module neuralops.core.svd_utils
Centralized SVD & Factorization Utilities for Attention and Compression Modules. Provides numerical stability (FP32 execution for half-precision inputs), truncated SVD factor initialization, and energy-based rank selection.
Functions
def init_factorized_linear(src_weight: torch.Tensor,
lin1: nn.Linear,
lin2: nn.Linear,
rank: int,
src_bias: torch.Tensor | None = None) ‑> None-
Expand source code
def init_factorized_linear( src_weight: torch.Tensor, lin1: nn.Linear, lin2: nn.Linear, rank: int, src_bias: torch.Tensor | None = None, ) -> None: """ Initializes a two-stage linear projection (x @ lin1.T @ lin2.T) from a dense source weight using truncated SVD: lin1.weight = Vh[:r, :] lin2.weight = U[:, :r] @ diag(S[:r]) Ensures zeroed parameters for excess capacity and copies bias to lin2 if present. """ with torch.no_grad(): U, S, Vh = stable_svd(src_weight, full_matrices=False) r = min(rank, lin1.weight.shape[0], lin2.weight.shape[1], U.size(1), Vh.size(0)) lin1.weight.data.zero_() lin2.weight.data.zero_() # lin1 takes input and projects to rank: shape (rank, in_features) min_in = min(lin1.weight.shape[1], Vh.shape[1]) lin1.weight.data[:r, :min_in].copy_(Vh[:r, :min_in].to(lin1.weight.dtype)) # lin2 takes rank and projects to out_features: shape (out_features, rank) min_out = min(lin2.weight.shape[0], U.shape[0]) U_scaled = (U[:min_out, :r] * S[:r].unsqueeze(0)).to(lin2.weight.dtype) lin2.weight.data[:min_out, :r].copy_(U_scaled) if src_bias is not None and getattr(lin2, "bias", None) is not None: min_b = min(lin2.bias.shape[0], src_bias.shape[0]) lin2.bias.data[:min_b].copy_(src_bias[:min_b].to(lin2.bias.dtype))Initializes a two-stage linear projection (x @ lin1.T @ lin2.T) from a dense source weight using truncated SVD: lin1.weight = Vh[:r, :] lin2.weight = U[:, :r] @ diag(S[:r]) Ensures zeroed parameters for excess capacity and copies bias to lin2 if present.
def select_rank_by_energy(singular_values: torch.Tensor,
energy_threshold: float = 0.9,
min_rank: int = 4,
max_rank: int | None = None) ‑> int-
Expand source code
def select_rank_by_energy( singular_values: torch.Tensor, energy_threshold: float = 0.90, min_rank: int = 4, max_rank: int | None = None, ) -> int: """ Selects truncation rank r such that sum(S[:r]^2) / sum(S^2) >= energy_threshold. """ if singular_values.numel() == 0: return min_rank energy = torch.cumsum(singular_values**2, dim=0) total_energy = energy[-1] if total_energy <= 0: return min_rank fraction = energy / total_energy mask = fraction >= energy_threshold if not torch.any(mask): r = int(singular_values.numel()) else: r = int(torch.nonzero(mask)[0].item()) + 1 r = max(min_rank, r) if max_rank is not None: r = min(max_rank, r) return rSelects truncation rank r such that sum(S[:r]^2) / sum(S^2) >= energy_threshold.
def stable_svd(weight: torch.Tensor, full_matrices: bool = False) ‑> tuple[torch.Tensor, torch.Tensor, torch.Tensor]-
Expand source code
def stable_svd( weight: torch.Tensor, full_matrices: bool = False, ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]: """ Computes SVD with guaranteed FP32 precision to prevent CUDA half-precision solver crashes (e.g. geqrf_cuda). Returns (U, S, Vh) matching the original device and floating dtype. """ orig_dtype = weight.dtype orig_device = weight.device W_fp32 = weight.detach().to(device=orig_device, dtype=torch.float32) U, S, Vh = torch.linalg.svd(W_fp32, full_matrices=full_matrices) return U.to(orig_dtype), S.to(orig_dtype), Vh.to(orig_dtype)Computes SVD with guaranteed FP32 precision to prevent CUDA half-precision solver crashes (e.g. geqrf_cuda). Returns (U, S, Vh) matching the original device and floating dtype.