Instructions to use Motif-Technologies/optimizer with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Kernels
How to use Motif-Technologies/optimizer with Kernels:
# !pip install kernels from kernels import get_kernel # a version (or an explicit revision) is required; see the "Files and versions" tab for the available ones kernel = get_kernel("Motif-Technologies/optimizer", version=1) - Notebooks
- Google Colab
- Kaggle
Merge pull request #34 from MotifTechnologies/fix/qk-clip-rotary-full-gamma
Browse files- torch-ext/optimizer/muon.py +26 -2
- torch-ext/optimizer/qk_clip.py +33 -45
torch-ext/optimizer/muon.py
CHANGED
|
@@ -479,6 +479,18 @@ class Muon(torch.optim.Optimizer):
|
|
| 479 |
p, qk_clip_state, n
|
| 480 |
) if qk_clip_state is not None else None
|
| 481 |
if scales_full is not None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 482 |
ratio = p.shape[0] // scales_full.shape[0]
|
| 483 |
idx0 = local_indices[0]
|
| 484 |
if isinstance(idx0, slice):
|
|
@@ -486,7 +498,7 @@ class Muon(torch.optim.Optimizer):
|
|
| 486 |
idx0 = torch.arange(start,
|
| 487 |
idx0.stop,
|
| 488 |
device=scales_full.device)
|
| 489 |
-
row_scales = scales_full[idx0 // ratio]
|
| 490 |
p._local_tensor.mul_(row_scales.view(-1, 1))
|
| 491 |
|
| 492 |
if not batch_params:
|
|
@@ -558,6 +570,18 @@ class Muon(torch.optim.Optimizer):
|
|
| 558 |
p, qk_clip_state, n
|
| 559 |
) if qk_clip_state is not None else None
|
| 560 |
if scales_full is not None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 561 |
ratio = p.shape[0] // scales_full.shape[0]
|
| 562 |
idx0 = local_indices[0]
|
| 563 |
if isinstance(idx0, slice):
|
|
@@ -565,7 +589,7 @@ class Muon(torch.optim.Optimizer):
|
|
| 565 |
idx0 = torch.arange(start,
|
| 566 |
idx0.stop,
|
| 567 |
device=scales_full.device)
|
| 568 |
-
row_scales = scales_full[idx0 // ratio]
|
| 569 |
p._local_tensor.mul_(row_scales.view(-1, 1))
|
| 570 |
|
| 571 |
def _setup_parallel(self, names, params, group, qk_logits):
|
|
|
|
| 479 |
p, qk_clip_state, n
|
| 480 |
) if qk_clip_state is not None else None
|
| 481 |
if scales_full is not None:
|
| 482 |
+
# scales_full is raw per-head γ; apply the content
|
| 483 |
+
# exponent per head (MHA √γ, wq_b γ^(1-r), wkv_b
|
| 484 |
+
# γ^r). NOTE: this per-head form cannot resolve the
|
| 485 |
+
# MLA rotary/value sub-regions (q_pe → full γ, v
|
| 486 |
+
# untouched) — see qk_clip; the sharded path scales
|
| 487 |
+
# q_pe/v by the content exponent instead.
|
| 488 |
+
if not qk_clip_state.is_mla:
|
| 489 |
+
e = 0.5
|
| 490 |
+
elif qk_clip_state.kind == 'wq_b':
|
| 491 |
+
e = 1.0 - qk_clip_state.k_ratio
|
| 492 |
+
else:
|
| 493 |
+
e = qk_clip_state.k_ratio
|
| 494 |
ratio = p.shape[0] // scales_full.shape[0]
|
| 495 |
idx0 = local_indices[0]
|
| 496 |
if isinstance(idx0, slice):
|
|
|
|
| 498 |
idx0 = torch.arange(start,
|
| 499 |
idx0.stop,
|
| 500 |
device=scales_full.device)
|
| 501 |
+
row_scales = (scales_full**e)[idx0 // ratio]
|
| 502 |
p._local_tensor.mul_(row_scales.view(-1, 1))
|
| 503 |
|
| 504 |
if not batch_params:
|
|
|
|
| 570 |
p, qk_clip_state, n
|
| 571 |
) if qk_clip_state is not None else None
|
| 572 |
if scales_full is not None:
|
| 573 |
+
# scales_full is raw per-head γ; apply the content
|
| 574 |
+
# exponent per head (MHA √γ, wq_b γ^(1-r), wkv_b
|
| 575 |
+
# γ^r). NOTE: this per-head form cannot resolve the
|
| 576 |
+
# MLA rotary/value sub-regions (q_pe → full γ, v
|
| 577 |
+
# untouched) — see qk_clip; the sharded path scales
|
| 578 |
+
# q_pe/v by the content exponent instead.
|
| 579 |
+
if not qk_clip_state.is_mla:
|
| 580 |
+
e = 0.5
|
| 581 |
+
elif qk_clip_state.kind == 'wq_b':
|
| 582 |
+
e = 1.0 - qk_clip_state.k_ratio
|
| 583 |
+
else:
|
| 584 |
+
e = qk_clip_state.k_ratio
|
| 585 |
ratio = p.shape[0] // scales_full.shape[0]
|
| 586 |
idx0 = local_indices[0]
|
| 587 |
if isinstance(idx0, slice):
|
|
|
|
| 589 |
idx0 = torch.arange(start,
|
| 590 |
idx0.stop,
|
| 591 |
device=scales_full.device)
|
| 592 |
+
row_scales = (scales_full**e)[idx0 // ratio]
|
| 593 |
p._local_tensor.mul_(row_scales.view(-1, 1))
|
| 594 |
|
| 595 |
def _setup_parallel(self, names, params, group, qk_logits):
|
torch-ext/optimizer/qk_clip.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
import logging
|
| 2 |
-
import math
|
| 3 |
from dataclasses import dataclass
|
| 4 |
|
| 5 |
import torch
|
|
@@ -127,17 +126,16 @@ def get_qk_clip_info(clip_config, n, qk_logits):
|
|
| 127 |
|
| 128 |
|
| 129 |
def compute_scales(p, qk_clip_state, name: str = ''):
|
| 130 |
-
"""Compute per-head
|
| 131 |
|
| 132 |
-
Returns
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
MLA wq_b : scale = γ^(1 - k_ratio). Q carries (1-k_ratio) of the
|
| 137 |
-
log-reduction; k_ratio=0 → full γ on Q only (K unclipped).
|
| 138 |
-
MLA wkv_b : scale = γ^k_ratio applied to k_nope rows only (v rows
|
| 139 |
-
untouched). Returns None when k_ratio=0 (K unclipped).
|
| 140 |
-
Together wq_b × wkv_b deliver γ^(1-k_ratio) × γ^k_ratio = γ end-to-end.
|
| 141 |
"""
|
| 142 |
kind = qk_clip_state.kind
|
| 143 |
|
|
@@ -150,32 +148,18 @@ def compute_scales(p, qk_clip_state, name: str = ''):
|
|
| 150 |
threshold = qk_clip_state.threshold
|
| 151 |
logit = qk_clip_state.logit
|
| 152 |
|
| 153 |
-
# Exponent for (threshold/v_ele)^exponent:
|
| 154 |
-
# MLA wq_b → 1 - k_ratio (Q carries this fraction of log-reduction)
|
| 155 |
-
# MLA wkv_b → k_ratio (K carries the rest; applied to k_nope rows only)
|
| 156 |
-
# MHA/GQA → 0.5 (equal split; equivalent to k_ratio=0.5)
|
| 157 |
-
#
|
| 158 |
-
# Principled k_ratio for Q:K = G:1 GQA: 1 / (1 + sqrt(G))
|
| 159 |
-
# K's gradient is a sum of G Q-head terms that partially cancel, so its
|
| 160 |
-
# effective recovery signal scales as 1/sqrt(G) (random-walk argument).
|
| 161 |
-
# Setting clip/recovery equal for both sides:
|
| 162 |
-
# (1-r)/1 = r/(1/sqrt(G)) => r = 1/(1+sqrt(G))
|
| 163 |
-
# G=1 → 0.5 (recovers MHA), G=4 → ≈0.33, G=8 → ≈0.26.
|
| 164 |
-
if qk_clip_state.is_mla:
|
| 165 |
-
exponent = (1.0 - qk_clip_state.k_ratio) if kind == 'wq_b' else qk_clip_state.k_ratio
|
| 166 |
-
else:
|
| 167 |
-
exponent = 0.5
|
| 168 |
-
|
| 169 |
head_scales = {}
|
| 170 |
for logit_idx, head_idx in enumerate(indices):
|
| 171 |
v_ele = float(logit[logit_idx])
|
| 172 |
if v_ele > threshold:
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
|
|
|
|
|
|
| 176 |
logger.info(
|
| 177 |
f"[{kind}] {name} Head {head_idx} exceeded threshold "
|
| 178 |
-
f"(value={v_ele:.4f}, threshold={threshold:.4f}) ->
|
| 179 |
)
|
| 180 |
|
| 181 |
if not head_scales:
|
|
@@ -195,36 +179,40 @@ def compute_scales(p, qk_clip_state, name: str = ''):
|
|
| 195 |
|
| 196 |
|
| 197 |
def qk_clip(p, scales, info):
|
| 198 |
-
"""Apply
|
|
|
|
| 199 |
|
| 200 |
Args:
|
| 201 |
p: Parameter (nn.Parameter or raw tensor).
|
| 202 |
-
scales: [n_heads] tensor of per-head
|
| 203 |
-
|
| 204 |
-
info: QKClipInfo with kind, head_dim, and MLA sub-head
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
"""
|
| 210 |
W = p.data if isinstance(p, torch.nn.Parameter) else p
|
|
|
|
| 211 |
|
| 212 |
if not info.is_mla:
|
| 213 |
-
|
| 214 |
-
W.view(-1, info.head_dim, W.shape[1]).mul_(scales.view(-1, 1, 1))
|
| 215 |
return
|
| 216 |
|
| 217 |
-
# MLA: vectorized sub-region scaling within each head
|
| 218 |
if info.kind == 'wq_b':
|
| 219 |
qk_nope = info.qk_nope_head_dim
|
| 220 |
qk_head_dim = qk_nope + info.qk_rope_head_dim
|
| 221 |
W_3d = W.view(-1, qk_head_dim, W.shape[1]) # [H, qk_head_dim, in_dim]
|
| 222 |
-
W_3d[:, :qk_nope, :].mul_(scales.view(-1, 1, 1)) # q_nope → γ^(1-
|
| 223 |
-
W_3d[:, qk_nope:, :].mul_(scales.view(-1, 1, 1)) # q_pe
|
| 224 |
|
| 225 |
elif info.kind == 'wkv_b':
|
| 226 |
qk_nope = info.qk_nope_head_dim
|
| 227 |
kv_stride = qk_nope + info.v_head_dim
|
| 228 |
W_3d = W.view(-1, kv_stride, W.shape[1]) # [H, kv_stride, in_dim]
|
| 229 |
-
W_3d[:, :qk_nope, :].mul_(scales.view(-1, 1, 1)) # k_nope → γ^
|
| 230 |
-
# v rows:
|
|
|
|
| 1 |
import logging
|
|
|
|
| 2 |
from dataclasses import dataclass
|
| 3 |
|
| 4 |
import torch
|
|
|
|
| 126 |
|
| 127 |
|
| 128 |
def compute_scales(p, qk_clip_state, name: str = ''):
|
| 129 |
+
"""Compute the per-head raw clip factor γ = threshold / max_logit.
|
| 130 |
|
| 131 |
+
Returns a per-head tensor of γ (1.0 for heads under the threshold) if any
|
| 132 |
+
head requires clipping, else None. The per-region exponent on γ is NOT
|
| 133 |
+
applied here — it is applied at multiply time (``qk_clip`` for the whole
|
| 134 |
+
tensor, or the sharded path in muon.py) so that one per-head γ can drive
|
| 135 |
+
different sub-regions (q_nope, q_pe, k_nope, v) with different exponents.
|
| 136 |
|
| 137 |
+
wkv_b with k_ratio=0 returns None: the whole reduction is placed on Q and
|
| 138 |
+
the key projection is left unclipped.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
"""
|
| 140 |
kind = qk_clip_state.kind
|
| 141 |
|
|
|
|
| 148 |
threshold = qk_clip_state.threshold
|
| 149 |
logit = qk_clip_state.logit
|
| 150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
head_scales = {}
|
| 152 |
for logit_idx, head_idx in enumerate(indices):
|
| 153 |
v_ele = float(logit[logit_idx])
|
| 154 |
if v_ele > threshold:
|
| 155 |
+
gamma = threshold / v_ele # raw clip factor; exponent applied later
|
| 156 |
+
# Within a shared (GQA) group, keep the smallest γ, i.e. the
|
| 157 |
+
# strongest required clipping.
|
| 158 |
+
if head_idx not in head_scales or gamma < head_scales[head_idx]:
|
| 159 |
+
head_scales[head_idx] = gamma
|
| 160 |
logger.info(
|
| 161 |
f"[{kind}] {name} Head {head_idx} exceeded threshold "
|
| 162 |
+
f"(value={v_ele:.4f}, threshold={threshold:.4f}) -> γ={gamma:.4f}"
|
| 163 |
)
|
| 164 |
|
| 165 |
if not head_scales:
|
|
|
|
| 179 |
|
| 180 |
|
| 181 |
def qk_clip(p, scales, info):
|
| 182 |
+
"""Apply QK-clip to a Q/K projection weight; each sub-region is raised to
|
| 183 |
+
its own exponent so every logit component is reduced by exactly γ.
|
| 184 |
|
| 185 |
Args:
|
| 186 |
p: Parameter (nn.Parameter or raw tensor).
|
| 187 |
+
scales: [n_heads] tensor of per-head raw γ (= threshold/value), 1.0 for
|
| 188 |
+
unclipped heads, as returned by ``compute_scales``.
|
| 189 |
+
info: QKClipInfo with kind, head_dim, k_ratio and MLA sub-head dims.
|
| 190 |
+
|
| 191 |
+
Exponents:
|
| 192 |
+
MHA : √γ on all rows.
|
| 193 |
+
MLA q_nope : γ^(1-k_ratio), k_nope : γ^k_ratio (content product = γ).
|
| 194 |
+
MLA q_pe : γ (full) — the decoupled rotary key is shared and left
|
| 195 |
+
unchanged, so the rotary query carries the whole γ for
|
| 196 |
+
every k_ratio; γ^(1-k_ratio) here would under-clip rotary.
|
| 197 |
+
MLA v rows : untouched.
|
| 198 |
"""
|
| 199 |
W = p.data if isinstance(p, torch.nn.Parameter) else p
|
| 200 |
+
r = info.k_ratio
|
| 201 |
|
| 202 |
if not info.is_mla:
|
| 203 |
+
W.view(-1, info.head_dim, W.shape[1]).mul_((scales**0.5).view(-1, 1, 1))
|
|
|
|
| 204 |
return
|
| 205 |
|
|
|
|
| 206 |
if info.kind == 'wq_b':
|
| 207 |
qk_nope = info.qk_nope_head_dim
|
| 208 |
qk_head_dim = qk_nope + info.qk_rope_head_dim
|
| 209 |
W_3d = W.view(-1, qk_head_dim, W.shape[1]) # [H, qk_head_dim, in_dim]
|
| 210 |
+
W_3d[:, :qk_nope, :].mul_((scales**(1.0 - r)).view(-1, 1, 1)) # q_nope → γ^(1-r)
|
| 211 |
+
W_3d[:, qk_nope:, :].mul_(scales.view(-1, 1, 1)) # q_pe → γ (full)
|
| 212 |
|
| 213 |
elif info.kind == 'wkv_b':
|
| 214 |
qk_nope = info.qk_nope_head_dim
|
| 215 |
kv_stride = qk_nope + info.v_head_dim
|
| 216 |
W_3d = W.view(-1, kv_stride, W.shape[1]) # [H, kv_stride, in_dim]
|
| 217 |
+
W_3d[:, :qk_nope, :].mul_((scales**r).view(-1, 1, 1)) # k_nope → γ^r
|
| 218 |
+
# v rows: untouched (shared rotary key k_rope is unchanged)
|