Qapdex commited on
Commit
e5a73d8
·
verified ·
1 Parent(s): 4f96d89

Create b158.py

Browse files
Files changed (1) hide show
  1. b158.py +44 -0
b158.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torchao
4
+
5
+ def bitnet_b158_quantize(tensor):
6
+ """
7
+ Konvertiert ein Gewicht-Tensor in das ternäre 1.58-Bit Format {-1, 0, +1}
8
+ inklusive der notwendigen Per-Channel Skalierung.
9
+ """
10
+ # 1. Berechne den durchschnittlichen Absolutwert pro Kanal (Zeile)
11
+ scale = tensor.abs().mean(dim=-1, keepdim=True).clamp(min=1e-5)
12
+
13
+ # 2. Skaliere den Tensor und runde auf die nächste ganze Zahl
14
+ quantized = torch.round(tensor / scale)
15
+
16
+ # 3. Zwinge die Werte strikt in den Bereich von -1 bis +1
17
+ quantized = torch.clamp(quantized, min=-1.0, max=1.0)
18
+
19
+ return quantized, scale
20
+
21
+ class BitLinear158(nn.Module):
22
+ """
23
+ Ein Ersatz für nn.Linear, der die 1.58-Bit Ternary-Inferenz ausführt.
24
+ """
25
+ def __init__(self, in_features, out_features, bias=False):
26
+ super().__init__()
27
+ self.in_features = in_features
28
+ self.out_features = out_features
29
+ self.register_buffer("weight_158", torch.zeros((out_features, in_features), dtype=torch.int8))
30
+ self.register_buffer("scale", torch.zeros((out_features, 1), dtype=torch.bfloat16))
31
+
32
+ @torch.no_grad()
33
+ def from_float(self, float_layer):
34
+ # Transformiere die originalen Gewichte
35
+ q_w, scale = bitnet_b158_quantize(float_layer.weight.data)
36
+ self.weight_158.copy_(q_w.to(torch.int8))
37
+ self.scale.copy_(scale.to(torch.bfloat16))
38
+ return self
39
+
40
+ def forward(self, x):
41
+ # Die Magie: x wird mit den Integer-Gewichten (-1, 0, 1) verarbeitet
42
+ # Auf der Hardwarebene entspricht dies reinen Additionen/Subtraktionen
43
+ out = nn.functional.linear(x, self.weight_158.to(x.dtype))
44
+ return out * self.scale