| 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. |
| """ |
| |
| scale = tensor.abs().mean(dim=-1, keepdim=True).clamp(min=1e-5) |
| |
| |
| quantized = torch.round(tensor / scale) |
| |
| |
| 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): |
| |
| 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): |
| |
| |
| out = nn.functional.linear(x, self.weight_158.to(x.dtype)) |
| return out * self.scale |
|
|