#
BitNet

BitNet replaces traditional Linear layers in Multi-Head Attention and Feed-Forward Networks with specialized layers called BitLinear with ternary (or binary in the older version) precision. The BitLinear layers introduced here quantize the weights using ternary precision (with values of -1, 0, and 1) and quantize the activations to 8-bit precision.

The architecture of BitNet with BitLinear layers

During training, we start by quantizing the weights into ternary values, using symmetric per tensor quantization. First, we compute the average of the absolute values of the weight matrix and use this as a scale. We then divide the weights by the scale, round the values, constrain them between -1 and 1, and finally rescale them to continue in full precision. s c a l e w=1 1 n m∑i j∣W i j∣ scale_w = \frac{1}{\frac{1}{nm} \sum_{ij} |W_{ij}|} sc a l e w​=nm 1​∑ij​∣W ij​∣1​ W q=clamp[−1,1](round(W∗s c a l e)) W_q = \text{clamp}_{[-1,1]}(\text{round}(W*scale)) W q​=clamp[−1,1]​(round(W∗sc a l e)) W d e q u a n t i z e d=W q∗s c a l e w W_{dequantized} = W_q*scale_w W d e q u an t i ze d​=W q​∗sc a l e w​

Activations are then quantized to a specified bit-width (e.g., 8-bit) using absmax quantization (symmetric per channel quantization). This involves scaling the activations into a range [−128,127[. The quantization formula is: s c a l e x=127∣X∣max, dim=−1 scale_x = \frac{127}{|X|_{\text{max}, \, \text{dim}=-1}} sc a l e x​=∣X∣max,dim=−1​127​ X q=clamp[−128,127](round(X∗s c a l e)) X_q = \text{clamp}_{[-128,127]}(\text{round}(X*scale)) X q​=clamp[−128,127]​(round(X∗sc a l e)) X d e q u a n t i z e d=X q∗s c a l e x X_{dequantized} = X_q * scale_x X d e q u an t i ze d​=X q​∗sc a l e x​

To learn more about how we trained, and fine-tuned bitnet models checkout the blogpost here

##
Load a BitNet Model from the Hub

BitNet models can’t be quantized on the fly—they need to be pre-trained or fine-tuned with the quantization applied (it’s a Quantization aware training technique). Once trained, these models are already quantized and available as packed versions on the hub.

A quantized model can be load :

    from transformers import AutoModelForCausalLM
    path = "/path/to/model"
    model = AutoModelForCausalLM.from_pretrained(path, device_map="auto")

##
Pre-training / Fine-tuning a BitNet Model

If you’re looking to pre-train or fine-tune your own 1.58-bit model using Nanotron, check out this PR, all you need to get started is there !

For fine-tuning, you’ll need to convert the model from Hugging Face format to Nanotron format (which has some differences). You can find the conversion steps in this PR.

##
Kernels

In our initial version, we chose to use `@torch.compile` to unpack the weights and perform the forward pass. It’s very straightforward to implement and delivers significant speed improvements. We plan to integrate additional optimized kernels in future versions.

< > Update on GitHub