File size: 8,589 Bytes
56eff0f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | """Geometry-preserving weight analogs for Q2_K bilinear factorization.
At 2 bits per weight (4 levels ``q in {0, 1, 2, 3}`` and 4-bit sub-block
scales ``Ls, Lm in {0..15}``), raw weight blocks suffer from two structural
bottlenecks:
1. **Intra-sub-block outlier collapse**: a single heavy-tailed weight stretches
the sub-block span ``xmax - xmin``, forcing 13-15 of the 16 weights into
one or two quantization bins.
2. **Inter-sub-block scale crushing**: a single high-variance sub-block inflates
the shared superblock scale ``d``, collapsing ``Ls_j`` of the remaining
15 sub-blocks toward small integers with severe rounding loss.
Rather than factoring raw weights alone, V2 constructs a bank of
**geometry-preserving weight analogs** ``x_tilde`` of the eligible weights:
* :func:`subblock_isomoment_analog` maps each 16-weight sub-block through an
importance-weighted saturating transport blended with the optimal 4-level
quantile spacing, then orthogonally projects back onto the exact weighted
mean ``mu_j`` and weighted variance ``sigma_j^2`` of the original sub-block.
* :func:`vesica_gram_analog` operates in the D6 / Vesica fold basis
``(x_p + x_{p+128}, x_p - x_{p+128})``, regularizing outliers in the whitened
eigen-basis and coloring back so the exact 2x2 weighted Gram matrix and means
of the two half-blocks are preserved.
* :func:`subscale_lattice_analog` tempers cross-sub-block dispersion toward the
4-bit ``{0..15}`` scale lattice while preserving every sub-block's unit
direction, mean, and total block weighted energy.
The discrete Q2_K lattice coordinates ``(Ls, Lm, q)`` discovered on each analog
are then projected back onto the **true weights** ``x`` via coupled bilinear
least-squares, guaranteeing that the final emitted block is strictly optimal
under the true objective.
"""
from __future__ import annotations
import numpy as np
from .q2k import NS, QK_K
_Q2_IDEAL_QUANTILES = np.linspace(-1.35, 1.35, 16, dtype=np.float64)
def subblock_isomoment_analog(
x: np.ndarray,
w: np.ndarray | None = None,
tau: float = 1.65,
beta: float = 0.25,
quantile_blend: float = 0.30,
enforce_nonpositive_min: bool = False,
) -> np.ndarray:
"""Create a sub-block iso-moment analog preserving weighted mean & variance.
Invariants per 16-weight sub-block ``j`` (when ``enforce_nonpositive_min``
is ``False``):
* ``sum_k w_{j,k} x_tilde_{j,k} == sum_k w_{j,k} x_{j,k}``
* ``sum_k w_{j,k} (x_tilde_{j,k} - mu_j)^2 == sum_k w_{j,k} (x_{j,k} - mu_j)^2``
* strict rank-order preservation with respect to ``x_{j,k}`` (when ``beta == 0``)
"""
xb = np.asarray(x, dtype=np.float64).reshape(NS, 16)
wb = (
np.ones((NS, 16), dtype=np.float64)
if w is None
else np.asarray(w, dtype=np.float64).reshape(NS, 16)
)
wsum = np.maximum(np.sum(wb, axis=1, keepdims=True), 1.0e-30)
mu = np.sum(wb * xb, axis=1, keepdims=True) / wsum
centered = xb - mu
var = np.sum(wb * centered * centered, axis=1, keepdims=True) / wsum
sigma = np.sqrt(np.maximum(var, 1.0e-30))
active = (sigma[:, 0] >= 1.0e-15)
z = centered / sigma
w_mean = wsum / 16.0
w_rel = np.power(np.maximum(wb / w_mean, 1.0e-12), beta) if beta != 0.0 else 1.0
z_comp = tau * np.tanh((z * w_rel) / max(tau, 1.0e-6))
if quantile_blend > 0.0:
order = np.argsort(z, axis=1, kind="stable")
z_quant = np.empty_like(z)
rows = np.arange(NS)[:, None]
z_quant[rows, order] = _Q2_IDEAL_QUANTILES[None, :]
z_analog = (1.0 - quantile_blend) * z_comp + quantile_blend * z_quant
else:
z_analog = z_comp
mu_a = np.sum(wb * z_analog, axis=1, keepdims=True) / wsum
z_analog = z_analog - mu_a
var_a = np.sum(wb * z_analog * z_analog, axis=1, keepdims=True) / wsum
scale = np.where(var_a > 1.0e-30, np.sqrt(var / np.maximum(var_a, 1.0e-30)), 0.0)
out = np.where(active[:, None], mu + z_analog * scale, xb)
if enforce_nonpositive_min:
orig_min = np.min(xb, axis=1)
new_min = np.min(out, axis=1)
shift = np.where((orig_min <= 0.0) & (new_min > 0.0), new_min, 0.0)
out = out - shift[:, None]
return out.reshape(QK_K).astype(np.float32)
def vesica_gram_analog(
x: np.ndarray,
w: np.ndarray | None = None,
tau: float = 1.9,
) -> np.ndarray:
"""Create a D6 / Vesica fold analog preserving the 2x2 half-block Gram matrix.
Decomposes ``x`` into symmetric ``v = 0.5*(x[:128] + x[128:])`` and
antisymmetric ``u = 0.5*(x[:128] - x[128:])`` modes under pair weights
``wp = 0.5*(w[:128] + w[128:])``. Whitens ``(v, u)``, applies smooth
hyperbolic saturation in the principal axes, and colors back with the exact
2x2 covariance square-root so ``Gram(v_tilde, u_tilde) == Gram(v, u)``.
"""
x_f64 = np.asarray(x, dtype=np.float64).reshape(QK_K)
w_f64 = (
np.ones(QK_K, dtype=np.float64)
if w is None
else np.asarray(w, dtype=np.float64).reshape(QK_K)
)
half = QK_K // 2
x0, x1 = x_f64[:half], x_f64[half:]
wp = np.maximum(0.5 * (w_f64[:half] + w_f64[half:]), 1.0e-30)
wsum = float(np.sum(wp))
v = 0.5 * (x0 + x1)
u = 0.5 * (x0 - x1)
mv = float(np.sum(wp * v) / wsum)
mu = float(np.sum(wp * u) / wsum)
Y = np.vstack([v - mv, u - mu]) # (2, 128)
G = (Y * wp[None, :]) @ Y.T / wsum # 2x2 weighted covariance
evals, evecs = np.linalg.eigh(G)
if float(np.max(evals)) < 1.0e-28:
return x_f64.astype(np.float32)
pos = evals > 1.0e-28
inv_sqrt = np.where(pos, 1.0 / np.sqrt(np.maximum(evals, 1.0e-30)), 0.0)
W_white = (evecs * inv_sqrt[None, :]) @ evecs.T
Z = W_white @ Y # whitened (2, 128)
Z_comp = tau * np.tanh(Z / max(tau, 1.0e-6))
Z_mean = np.sum(Z_comp * wp[None, :], axis=1, keepdims=True) / wsum
Z_comp = Z_comp - Z_mean
G_z = (Z_comp * wp[None, :]) @ Z_comp.T / wsum
ez, Vz = np.linalg.eigh(G_z)
pos_z = ez > 1.0e-28
if not np.all(pos_z):
return x_f64.astype(np.float32)
inv_sqrt_z = np.where(pos_z, 1.0 / np.sqrt(np.maximum(ez, 1.0e-30)), 0.0)
Z_orth = (Vz * inv_sqrt_z[None, :]) @ Vz.T @ Z_comp
sqrt_G = (evecs * np.sqrt(np.maximum(evals, 0.0))[None, :]) @ evecs.T
Y_tilde = sqrt_G @ Z_orth
v_new = mv + Y_tilde[0]
u_new = mu + Y_tilde[1]
return np.concatenate([v_new + u_new, v_new - u_new]).astype(np.float32)
def subscale_lattice_analog(
x: np.ndarray,
w: np.ndarray | None = None,
gamma: float = 0.65,
) -> np.ndarray:
"""Create a cross-sub-block analog whose sub-block dispersions fit 4-bit scales.
Preserves each sub-block's mean ``mu_j`` and unit direction
``(x_j - mu_j) / sigma_j``, while tempering extreme sub-block standard
deviations ``sigma_j`` toward the superblock root-mean-square dispersion
and rescaling to preserve total centered weighted energy.
"""
xb = np.asarray(x, dtype=np.float64).reshape(NS, 16)
wb = (
np.ones((NS, 16), dtype=np.float64)
if w is None
else np.asarray(w, dtype=np.float64).reshape(NS, 16)
)
wsum = np.maximum(np.sum(wb, axis=1, keepdims=True), 1.0e-30)
mu = np.sum(wb * xb, axis=1, keepdims=True) / wsum
centered = xb - mu
energy_j = np.sum(wb * centered * centered, axis=1, keepdims=True)
total_energy = float(np.sum(energy_j))
if total_energy <= 1.0e-30:
return xb.reshape(QK_K).astype(np.float32)
sigma = np.sqrt(np.maximum(energy_j / wsum, 1.0e-30))
sigma_ref = float(np.sqrt(total_energy / max(float(np.sum(wsum)), 1.0e-30)))
target_sigma = np.power(np.maximum(sigma, 1.0e-30), gamma) * (
sigma_ref ** (1.0 - gamma)
)
scaled = np.where(sigma > 1.0e-15, centered * (target_sigma / sigma), 0.0)
new_energy = float(np.sum(wb * scaled * scaled))
if new_energy > 1.0e-30:
scaled = scaled * np.sqrt(total_energy / new_energy)
out = mu + scaled
return out.reshape(QK_K).astype(np.float32)
def build_block_analogs(
x: np.ndarray,
w: np.ndarray | None = None,
) -> list[np.ndarray]:
"""Return the portfolio of geometry-preserving weight analogs for a block."""
a1 = subblock_isomoment_analog(
x, w, tau=1.60, beta=0.25, quantile_blend=0.30, enforce_nonpositive_min=True
)
a2 = subblock_isomoment_analog(
x, w, tau=2.15, beta=0.15, quantile_blend=0.15, enforce_nonpositive_min=True
)
a3 = vesica_gram_analog(x, w, tau=1.85)
a4 = subscale_lattice_analog(a1, w, gamma=0.70)
return [a1, a2, a3, a4]
|