Spaces:
Paused
Paused
Download src/memory_native/baselines.py from kharki/mn-zerogpu: direct link, hf CLI and curl.
- Browser
- Download file 3.4 kB
-
https://huggingface.co/spaces/kharki/mn-zerogpu/resolve/main/src/memory_native/baselines.py
- Command line
-
hf download hf://spaces/kharki/mn-zerogpu/src/memory_native/baselines.py
-
curl -L -o baselines.py https://huggingface.co/spaces/kharki/mn-zerogpu/resolve/main/src/memory_native/baselines.py
3.4 kB
| """Baselines to compare the counter synapse against — in plain PyTorch. | |
| Right now: a BitNet-b1.58-style ternary QAT linear (full FP32 master + Adam, ternary in the | |
| forward) which isolates "cost of the 6-bit counter optimizer" vs "cost of ternarization". | |
| The README roadmap lists the memory-efficient-training baselines worth adding next (8-bit | |
| Adam / GaLore / LoMo), so the memory claim is measured against real competitors, not only | |
| FP32+Adam. | |
| """ | |
| from __future__ import annotations | |
| import math | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| __all__ = ["TernaryQATLinear", "make_linear"] | |
| class TernaryQATLinear(nn.Module): | |
| """FP32 master weight, per-row absmean ternary in forward, straight-through gradient to | |
| the master; Adam updates the master. Same ternary inference as the counter layer, but a | |
| full FP32 optimizer -- so (counter vs this) isolates the 6-bit optimizer cost.""" | |
| def __init__(self, fin: int, fout: int, init_gain: float = 1.0) -> None: | |
| super().__init__() | |
| self.weight = nn.Parameter(torch.empty(fout, fin)) | |
| nn.init.normal_(self.weight, mean=0.0, std=init_gain * math.sqrt(1.0 / fin)) | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| w = self.weight | |
| scale = w.abs().mean(dim=1, keepdim=True).clamp_min(1e-5) | |
| wq = (w / scale).round().clamp_(-1, 1) * scale | |
| wq = w + (wq - w).detach() # straight-through estimator | |
| return F.linear(x, wq) | |
| def make_linear(kind: str, fin: int, fout: int, init_gain: float = 1.0, **counter_kw): | |
| """Factory used by the GPT harness. | |
| kind in {dense, qat, counter, counter_rms, counter_packed, counter_triton, slowfast, group}. | |
| 'slowfast' (M3) and 'group' (M2) are counter-linear drop-ins: SlowFastCounterLinear folds a | |
| low-rank fp residual into the base every K steps (cuts the base correlation 8-32x); the extra | |
| rank/merge_every knobs ride in counter_kw. GroupCounterLinear is a 2:4 structured-sparse counter | |
| linear (group/keep/hysteresis in counter_kw). Both replace any nn.Linear in the block.""" | |
| from .counter import CompactCounterLinear, RMSCounterLinear | |
| from .packed import PackedRMSCounterLinear | |
| if kind == "counter": | |
| return CompactCounterLinear(fin, fout, init_gain=init_gain, **counter_kw) | |
| if kind == "counter_rms": | |
| return RMSCounterLinear(fin, fout, init_gain=init_gain, **counter_kw) | |
| if kind == "counter_packed": | |
| return PackedRMSCounterLinear(fin, fout, init_gain=init_gain, **counter_kw) | |
| if kind == "counter_triton": | |
| from .triton_counter import TritonCounterLinear | |
| return TritonCounterLinear(fin, fout, init_gain=init_gain, **counter_kw) | |
| if kind == "slowfast": # M3 | |
| from .slowfast import SlowFastCounterLinear | |
| return SlowFastCounterLinear(fin, fout, init_gain=init_gain, **counter_kw) | |
| if kind == "group": # M2 | |
| from .group_counter import GroupCounterLinear | |
| return GroupCounterLinear(fin, fout, init_gain=init_gain, **counter_kw) | |
| if kind == "qat": | |
| return TernaryQATLinear(fin, fout, init_gain) | |
| if kind == "dense": | |
| lin = nn.Linear(fin, fout, bias=False) | |
| nn.init.normal_(lin.weight, mean=0.0, std=init_gain * math.sqrt(1.0 / fin)) | |
| return lin | |
| raise ValueError(f"unknown linear kind: {kind!r}") | |