MiMo-V2.5-QEdge / b158.py
Qapdex's picture
Create b158.py
e5a73d8 verified
Raw
History Blame Contribute Delete
1.72 kB
import torch
import torch.nn as nn
import torchao
def bitnet_b158_quantize(tensor):
"""
Konvertiert ein Gewicht-Tensor in das ternäre 1.58-Bit Format {-1, 0, +1}
inklusive der notwendigen Per-Channel Skalierung.
"""
# 1. Berechne den durchschnittlichen Absolutwert pro Kanal (Zeile)
scale = tensor.abs().mean(dim=-1, keepdim=True).clamp(min=1e-5)
# 2. Skaliere den Tensor und runde auf die nächste ganze Zahl
quantized = torch.round(tensor / scale)
# 3. Zwinge die Werte strikt in den Bereich von -1 bis +1
quantized = torch.clamp(quantized, min=-1.0, max=1.0)
return quantized, scale
class BitLinear158(nn.Module):
"""
Ein Ersatz für nn.Linear, der die 1.58-Bit Ternary-Inferenz ausführt.
"""
def __init__(self, in_features, out_features, bias=False):
super().__init__()
self.in_features = in_features
self.out_features = out_features
self.register_buffer("weight_158", torch.zeros((out_features, in_features), dtype=torch.int8))
self.register_buffer("scale", torch.zeros((out_features, 1), dtype=torch.bfloat16))
@torch.no_grad()
def from_float(self, float_layer):
# Transformiere die originalen Gewichte
q_w, scale = bitnet_b158_quantize(float_layer.weight.data)
self.weight_158.copy_(q_w.to(torch.int8))
self.scale.copy_(scale.to(torch.bfloat16))
return self
def forward(self, x):
# Die Magie: x wird mit den Integer-Gewichten (-1, 0, 1) verarbeitet
# Auf der Hardwarebene entspricht dies reinen Additionen/Subtraktionen
out = nn.functional.linear(x, self.weight_158.to(x.dtype))
return out * self.scale