# quantization-demo
**Repository Path**: mirrors_maruel/quantization-demo
## Basic Information
- **Project Name**: quantization-demo
- **Description**: Demo to go along https://maruel.ca/post/weights-part-1/
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2024-11-11
- **Last Updated**: 2026-09-05
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Quantization demo
Python code to demonstrate quantization techniques as described in my blog post
[maruel.ca/post/weights-part-1/](https://maruel.ca/post/weights-part-1/)
## Affine transformation
This encodes the numbers with `y = ax + b`.
By saving one `a` (scale) and `b` (zero point/bias) per block, we can reduce the precision of each `x`
(weight) significantly.
Source: [affine_transformation.py](affine_transformation.py)
affine_transformation.py output
```
$ python3 affine_transformation.py
Original tensor of 256 random values between -5 and 5:
- [2.5763, -2.2069, -0.9693, 2.3468, -4.7072, 2.9986, -1.0286, 2.5437, ...]
- storage: 1024 bytes (256*4)
Quantizing as 8 bits:
Quantized tensor:
- scale: 0.0387268
- zero_point: -4.88672
- packed: [192, 69, 101, 186, 4, 203, 99, 191, ...]
- storage: 260 bytes ((2+2+256*8/8))
Dequantized tensor:
- [2.5488, -2.2146, -0.9753, 2.3165, -4.7318, 2.9748, -1.0528, 2.5101, ...]
- Mean squared error: 0.000525236
Quantizing as 4 bits:
Quantized tensor:
- scale: 0.658691
- zero_point: -4.88672
- packed: [11, 4, 5, 10, 0, 11, 5, 11, ...]
- storage: 132 bytes ((2+2+256*4/8))
Dequantized tensor:
- [2.3589, -2.2520, -1.5933, 1.7002, -4.8867, 2.3589, -1.5933, 2.3589, ...]
- Mean squared error: 0.153035
```
➡️ We see reasonable [MSE](https://en.wikipedia.org/wiki/Mean_squared_error) with
great size reduction; from 1024 (float32) to 260 or 132 bytes.
## Affine transformation in blocks
This is an affine transformation where the tensor is sliced up in blocks. This
improves precision a little bit at the cost of a few more bytes.
Source: [affine_transformation_block.py](affine_transformation_block.py)
affine_transformation_block.py output
```
$ python3 affine_transformation_block.py
Original tensor of 256 random values between -5 and 5:
- [2.5763, -2.2069, -0.9693, 2.3468, -4.7072, 2.9986, -1.0286, 2.5437, ...]
- storage: 1024 bytes (256*4)
Quantizing as 8 bits:
Quantized tensor:
- scale: 0.0377808
- zero_point: -4.88672
- packed: [197, 70, 103, 191, 4, 208, 102, 196, ...]
- storage: 288 bytes (8*(2+2+32*8/8))
Dequantized tensor:
- [2.5561, -2.2421, -0.9953, 2.3294, -4.7356, 2.9717, -1.0331, 2.5183, ...]
- Mean squared error: 0.0004177
Quantizing as 4 bits:
Quantized tensor:
- scale: 0.64209
- zero_point: -4.88672
- packed: [11, 4, 6, 11, 0, 12, 6, 11, ...]
- storage: 160 bytes (8*(2+2+32*4/8))
Dequantized tensor:
- [2.1763, -2.3184, -1.0342, 2.1763, -4.8867, 2.8184, -1.0342, 2.1763, ...]
- Mean squared error: 0.122715
```
➡️ We see improved [MSE](https://en.wikipedia.org/wiki/Mean_squared_error)
compared to whole tensor encoding. 8 bits improved from 0.000525236 to
0.0004177 and 4 bits improved from 0.153035 to 0.122715. The cost is a
corresponding increase (260->288 bytes) and (132->160 bytes) in storage size.
## K-Quantization
This encodes the numbers with two sets of scales and offsets. One global and one per subblock. This leads to
`y = c(ax + b) + d` where `c` (scale) and `d` (zero point) have the same precision as for the affine
transformation, but the subblock `a` (scale) and `b` (zero point) are saved with only 6 bits of precision.
Source: [k_quantization.py](k_quantization.py)
k_quantization.py output
```
$ python3 k_quantization.py
Original tensor of 256 random values between -5 and 5:
- [2.5763, -2.2069, -0.9693, 2.3468, -4.7072, 2.9986, -1.0286, 2.5437, ...]
- storage: 1024 bytes (256*4)
Quantized tensor:
- scale: 0.0456238
- zero_point: 0.338623
- subscales: [14, 14, 12, 14, 14, 14, 14, 14]
- suboffsets: [14, 14, 14, 14, 14, 13, 13, 14]
- packed: [11, 3, 5, 11, 0, 12, 5, 11, 8, 6, 9, 7, 10, 4, 6, 6, ...]
- storage: 144 bytes (1*(2+2+6+6+128))
Dequantized tensor:
- [2.2812, -2.8262, -1.5488, 2.2812, -4.7422, 2.9219, -1.5488, 2.2812, ...]
- Mean squared error: 0.144666
```
➡️ Compared to affine transformation in block, the
[MSE](https://en.wikipedia.org/wiki/Mean_squared_error) increases a little
(0.122715->0.144666) for a reduction in storage (160->144 bytes).