BitNet / Ternary / Binary — Les LLMs 1-bit#
TL;DR — BitNet est une architecture Transformer révolutionnaire où les poids sont binaires {-1, +1} (BitNet b1) ou ternaires {-1, 0, +1} (BitNet b1.58). Au lieu de multiplier, on additionne ou soustrait les activations — éliminant totalement les multiplications matricielles. BitNet b1.58 matche les Transformers FP16/BF16 en qualité tout en divisant la mémoire par ~10×. C'est potentiellement l'avenir de l'inférence LLM.
Le concept radical : pourquoi 1.58 bits ?#
Le constat#
Un LLM classique stocke chaque poids en FP16 ou BF16 : 16 bits par paramètre. Pour un modèle de 70B, cela représente 140 GB de mémoire. La quantification PTQ (GPTQ, AWQ) descend à 4-bit (17.5 GB), mais en deçà, la qualité s'effondre.
L'idée de BitNet : et si on entraînait un modèle from scratch avec des poids qui ne peuvent valoir que -1, 0, ou +1 ?
| Format | Bits/poids | Mémoire (70B model) |
|---|---|---|
| FP32 (legacy) | 32 | 280 GB |
| FP16 / BF16 (std) | 16 | 140 GB |
| INT8 (quantif.) | 8 | 70 GB |
| INT4 (GPTQ/AWQ) | 4 | 35 GB |
| INT2 (QuIP#/AQLM) | 2 | 17.5 GB |
| Binary {-1,+1} | 1 | 8.75 GB |
| Ternary {-1,0,+1} | 1.58 | 13.8 GB |
| (log₂(3) ≈ 1.585) |
Pourquoi 1.58 et pas 1 ou 2 ?#
L'analogie pour néophyte#
Imagine que chaque poids d'un réseau de neurones est normalement un nombre à virgule complexe (0.0372...). BitNet dit : remplaçons chaque nombre par un simple signe : positif (+), négatif (−), ou zéro (rien). Au lieu de faire des multiplications compliquées, on ne fait qu'additionner ou soustraire les valeurs d'entrée. C'est comme remplacer une calculatrice scientifique par un compteur d'étiquettes : beaucoup plus rapide, beaucoup moins d'énergie — et étonnamment, ça marche aussi bien !
Papier source#
| Élément | BitNet (b1) | BitNet b1.58 |
|---|---|---|
| Titre | BitNet: Scaling 1-bit Transformers for Large Language Models | The Era of 1-bit LLMs: All Large Language Models are in 1.58 Bits |
| Auteurs | Hongyu Wang, Shuming Ma, Li Dong, et al. (Microsoft Research) | Shuming Ma, Hongyu Wang, Lingxiao Ma, et al. (Microsoft Research) |
| Date | Octobre 2023 | Février 2024 |
| Publication | JMLR 2025 (vol. 26) | — |
| arXiv | 2310.11453 | 2402.17764 |
Mécanisme technique#
BitNet b1 (binaire) : la fondation#
Chaque poids de la couche BitLinear (remplaçant nn.Linear) vaut exactement +1 ou -1.
(W contient des valeurs FP16)"] W1["W = [ 0.037, -0.142, 0.091, 0.218, ... ]"] OP1["→ Multiplication matricielle standard (GEMM)
→ Coûteux en compute et en énergie"] end
→ w_ij = +1 : X_j est additionné
→ w_ij = -1 : X_j est soustrait
→ Pas de multiplication du tout !"] end
BitNet b1.58 (ternaire) : l'amélioration décisive#
Chaque poids vaut -1, 0, ou +1. L'ajout du zéro permet la sparsité.
[ 0, +1, -1, 0, ... ]"] OP["→ w_ij = +1 : X_j additionné
→ w_ij = -1 : X_j soustrait
→ w_ij = 0 : X_j ignoré (gratuit !)"] RES["→ ~30-40% de zéros typiquement → sparsité implicite
→ Encore moins de compute que le binaire pur"] end
La matrice ternaire en détail#
R0: +1, 0, -1, +1, 0, 0, +1, -1
R1: 0, +1, +1, 0, -1, +1, 0, 0
R2: -1, 0, 0, +1, +1, 0, -1, +1
R3: +1, -1, 0, 0, 0, +1, +1, 0
R4: 0, +1, -1, +1, 0, -1, 0, +1"] d["Stockage : chaque poids = 2 bits (log₂(3) arrondi)
Sparsité : ~35% de zéros → compute réduit
Pas de multiplication : additions/soustractions uniquement"]
Comment entraîner un réseau ternaire ?#
Le défi : l'opération round() n'est pas différentiable. Comment backpropagé à travers une quantification ?
Réponse : Straight-Through Estimator (STE)
où β = moyenne absolue des poids (|w|̄)"] RES1["Résultat : w_ternary ∈ {-1, 0, +1}
L'activation passe à travers w_ternary (additions/soustractions)"] WC1 --> WT1 --> RES1 end subgraph BWD["BACKWARD PASS (gradients)"] G1["Le gradient « passe à travers » la fonction round comme si elle était l'identité (STE)"] G2["∂L/∂w_continu ≈ ∂L/∂w_ternary"] G3["+ Clipping : gradient = 0 si |w_continu| > 1
(pour éviter que les poids ne dérivent trop loin)"] G4["→ w_continu est mis à jour par SGD/Adam
→ À la convergence, la plupart des w_continu ≈ -1, 0, ou +1"] G1 --> G2 --> G3 --> G4 end
Architecture complète BitNet#
W ∈ {-1,0,+1} × X (INT8) = additions"] LN --> BLK["BitLinear (K projection)
W ∈ {-1,0,+1} × X (INT8) = additions"] LN --> BLV["BitLinear (V projection)
W ∈ {-1,0,+1} × X (INT8) = additions"] BLQ --> ATT["Attention (INT8)"] BLK --> ATT BLV --> ATT ATT --> BLFFN["BitLinear (FFN)
W ∈ {-1,0,+1} × activations = additions"] BLFFN --> OUT["OUTPUT"]
Performance comparée à FP16#
Le résultat choc de BitNet b1.58#
BitNet b1.58 matche ou surpasse les Transformers FP16/BF16 à taille de modèle équivalente :
| Modèle | FP16 Transformer | BitNet b1.58 | Résultat |
|---|---|---|---|
| 3B | ~10.5 | ~10.5 | ✅ ÉQUIVALENT |
| 4B | ~9.8 | ~9.8 | ✅ ÉQUIVALENT |
b1.58 matche FP16 en perplexité ET en zero-shot tasks.
Avantages systémiques de BitNet b1.58#
| Métrique | FP16 | BitNet b1.58 |
|---|---|---|
| Bits par poids | 16 | 1.58 (10× moins) |
| Mémoire modèle | 100% | ~10% |
| Type d'opération | Multiply | Add/Subtract seulement |
| Énergie/op | ~100% | ~5-10% |
| Latence | 100% | nettement réduite |
| Throughput | 100% | nettement supérieur |
| Qualité (PPL) | référence | équivalente ✅ |
| Entraînement | standard | from scratch requis |
Scaling law de BitNet#
BitNet b1.58 (ligne 2) suit la même courbe de scaling que FP16 Transformer (ligne 1) — les deux courbes convergent à mesure que la taille augmente.
BitNet b1.58 suit la même loi de scaling que les Transformers classiques : doubler la taille du modèle réduit la perplexité de la même manière. C'est ce qui rend cette approche crédible à grande échelle.
Pourquoi BitNet est potentiellement l'avenir de l'inférence LLM#
1. Élimination des multiplications#
y_i = Σ (x_j × w_ij)"] F2["N multiplications"] F3["❌ Les multiplications coûtent cher
en énergie et en silicium"] end subgraph BITNET_TER["BitNet ternaire"] T1["Pour chaque élément de Y :
y_i = Σ (±x_j) + skip(0)"] T2["N additions/soustractions"] T3["✅ Les additions sont ~10× moins
énergétiques et en silicium"] end
2. Latence et throughput#
Sans multiplications, le bottleneck devient purement la bande passante mémoire pour charger les activations. Les poids ternaires sont si petits qu'ils tiennent entièrement en cache.
3. Nouveaux paradigmes hardware#
BitNet ouvre la voie à des chips spécialisés conçus pour les opérations ternaires :
- Pas besoin de FPU (floating-point unit)
- Pas besoin de multipliers
- Unités arithmétiques simplifiées → plus de cœurs sur le même silicium
- Consommation énergétique drastiquement réduite
avoir 10× plus d'unités de calcul
pour la même surface de silicium"| CHIP
Le défi majeur : entraînement from scratch#
BitNet b1.58 2B4T : premier modèle open-source#
| Élément | Détail |
|---|---|
| Nom | BitNet b1.58 2B4T |
| Taille | 2 milliards de paramètres |
| Poids | Ternaires {-1, 0, +1} |
| Source | Microsoft Research |
| arXiv | 2504.12285 |
| Hugging Face | microsoft/bitnet-b1.58-2B-4T |
C'est le premier modèle BitNet open-weight entraîné à grande échelle, permettant à la communauté de tester et développer l'écosystème.
BitNet vs quantification PTQ classique#
| Aspect | PTQ (GPTQ/AWQ) | BitNet b1.58 |
|---|---|---|
| Quand ? | Après training | Pendant training |
| Modèle source | Existe (FP16) | From scratch |
| Bits/poids | 2-8 | 1.58 |
| Qualité à 2-bit | Dégradée | Équivalente à FP16 |
| Opérations | Déquant + GEMM | Additions seulement |
| Hardware requis | GPU standard | Idéalement dédié |
| Maturité | Production ✅ | Recherche ⚠️ |
| Flexibilité | Convertir n'importe quel modèle | Ré-entraîner obligatoirement |
Exemple pratique#
Utiliser BitNet b1.58 2B4T#
# Installer le runtime BitNet
pip install bitnet
# Ou cloner le repository officiel
git clone https://github.com/microsoft/BitNet.git
cd BitNet
pip install -e .
from bitnet import BitNetModel
from transformers import AutoTokenizer
# Charger le modèle ternaire
model = BitNetModel.from_pretrained("microsoft/bitnet-b1.58-2B-4T")
tokenizer = AutoTokenizer.from_pretrained("microsoft/bitnet-b1.58-2B-4T")
# Inférence
inputs = tokenizer("Explique le concept de quantification ternaire :", return_tensors="pt")
outputs = model.generate(**inputs, max_new_tokens=200)
print(tokenizer.decode(outputs[0]))
Inférence optimisée avec le runtime bitnet.cpp#
# Compiler le runtime C++ optimisé
cd bitnet
mkdir build && cd build
cmake ..
make -j
# Inférence CPU avec kernels ternaires optimisés
./bin/bitnet \
-m models/bitnet-b1.58-2B-4T \
-p "Que sont les LLMs 1-bit ?" \
-n 200
Aperçu de l'entraînement d'un BitLinear#
import torch
import torch.nn as nn
class BitLinear(nn.Linear):
"""Couche linéaire ternaire BitNet b1.58"""
def __init__(self, in_features, out_features, bias=False):
super().__init__(in_features, out_features, bias=bias)
def forward(self, x):
# Quantification ternaire des poids avec STE
w = self.weight # poids continus (appris)
# β = moyenne absolue des poids
beta = w.abs().mean()
# Quantification : round(w / β) → {-1, 0, +1}
w_quant = torch.clamp(
torch.round(w / (beta + 1e-8)),
min=-1, max=1
)
# STE : en backward, le gradient passe à travers
# (torch.detach() pour le forward, identité pour le backward)
w_ste = w_quant.detach() + w - w.detach()
# Multiplication = additions (le hardware le fera nativement)
return torch.nn.functional.linear(x, w_ste, self.bias)
TernaryLM et autres implémentations#
| Implémentation | Source | Notes |
|---|---|---|
| BitNet b1.58 2B4T | arXiv:2504.12285 | Modèle officiel Microsoft, 2B params |
| bitnet.cpp | github.com/microsoft/BitNet | Runtime C/C++ optimisé CPU/GPU |
| TernaryLM | arXiv:2602.07374 | Implémentation alternative, entraînement |
| BitNet (b1) | arXiv:2310.11453 | Version binaire originale (moins performante) |
Résumé : BitNet en 5 points#
- Poids ternaires {-1, 0, +1} = 1.58 bits/poids → mémoire ÷ 10
- Pas de multiplications → additions seulement → latence et énergie réduites
- Qualité équivalente à FP16 (même loi de scaling)
- Mais : entraînement from scratch obligatoire + hardware non optimisé
- Potentiel énorme si le hardware ternaire émerge → pourrait redéfinir l'inférence LLM
Références#
- BitNet (b1) — Wang et al., "BitNet: Scaling 1-bit Transformers for Large Language Models", JMLR 2025 — arXiv:2310.11453
- BitNet b1.58 — Ma et al., "The Era of 1-bit LLMs: All Large Language Models are in 1.58 Bits", 2024 — arXiv:2402.17764
- BitNet b1.58 2B4T — "BitNet b1.58 2B4T Technical Report", 2025 — arXiv:2504.12285
- TernaryLM — arXiv:2602.07374
- Code officiel — github.com/microsoft/BitNet
- Voir aussi : Sub-byte Quantification · QAT · QuIP# · AQLM · Index quantification