viva_tensor/nf4
NF4 (NormalFloat4) Quantization - QLoRA Style
DESCOBERTA VIA HUGGINGCHAT + PESQUISA: NF4 usa 16 níveis derivados dos quantis da distribuição normal Isso é ÓTIMO para pesos de NNs que seguem distribuição gaussiana!
Referências:
- QLoRA Paper: https://arxiv.org/abs/2305.14314
- bitsandbytes: create_normal_map function
- MLSys 2024: AWQ Best Paper
Vantagens sobre Q4 uniforme:
- Mais precisão próximo de zero (onde concentram os pesos)
- 8x compressão com ~0.1% erro
- Matematicamente ótimo para dados normais
Types
Double Quantization: quantiza os próprios scales Reduz overhead de metadados de 0.5 bits/param para 0.127 bits/param
pub type DoubleQuantNF4 {
DoubleQuantNF4(
blocks: List(NF4Block),
quantized_scales: List(Int),
scales_scale: Float,
shape: List(Int),
num_elements: Int,
memory_bytes: Int,
)
}
Constructors
-
DoubleQuantNF4( blocks: List(NF4Block), quantized_scales: List(Int), scales_scale: Float, shape: List(Int), num_elements: Int, memory_bytes: Int, )Arguments
- blocks
-
Blocos com índices NF4
- quantized_scales
-
Scales quantizados (INT8)
- scales_scale
-
Scale global para os scales
- shape
-
Shape original
- num_elements
-
Número de elementos
- memory_bytes
-
Memória em bytes
Bloco NF4 quantizado (tipicamente 64 valores)
pub type NF4Block {
NF4Block(indices: List(Int), abs_max: Float, block_size: Int)
}
Constructors
-
NF4Block(indices: List(Int), abs_max: Float, block_size: Int)Arguments
- indices
-
Índices 4-bit (0-15) para cada valor
- abs_max
-
Escala do bloco (abs_max original)
- block_size
-
Tamanho do bloco
Configuração de quantização
pub type NF4Config {
NF4Config(block_size: Int, double_quant: Bool)
}
Constructors
-
NF4Config(block_size: Int, double_quant: Bool)Arguments
- block_size
-
Tamanho do bloco (64 é padrão QLoRA)
- double_quant
-
Usar Double Quantization (quantiza os scales também)
Estatísticas de quantização
pub type NF4Stats {
NF4Stats(
original_bytes: Int,
compressed_bytes: Int,
compression_ratio: Float,
mean_error: Float,
max_error: Float,
num_blocks: Int,
)
}
Constructors
-
NF4Stats( original_bytes: Int, compressed_bytes: Int, compression_ratio: Float, mean_error: Float, max_error: Float, num_blocks: Int, )
Tensor completo quantizado em NF4
pub type NF4Tensor {
NF4Tensor(
blocks: List(NF4Block),
shape: List(Int),
num_elements: Int,
memory_bytes: Int,
compression_ratio: Float,
)
}
Constructors
-
NF4Tensor( blocks: List(NF4Block), shape: List(Int), num_elements: Int, memory_bytes: Int, compression_ratio: Float, )Arguments
- blocks
-
Lista de blocos quantizados
- shape
-
Shape original
- num_elements
-
Número de elementos
- memory_bytes
-
Memória em bytes
- compression_ratio
-
Taxa de compressão
Values
pub fn benchmark_nf4() -> Nil
pub fn compute_stats(
original: tensor.Tensor,
nf4: NF4Tensor,
) -> NF4Stats
Calcula estatísticas de erro
pub fn dequantize(nf4: NF4Tensor) -> tensor.Tensor
Dequantiza tensor NF4 de volta para FP32
pub fn double_quantize(
t: tensor.Tensor,
config: NF4Config,
) -> DoubleQuantNF4
Aplica Double Quantization
pub fn nf4_levels() -> List(Float)
Os 16 níveis NF4 são os quantis de N(0,1) normalizados para [-1, 1] Esses valores são hardcoded em bitsandbytes e usados em QLoRA
pub fn quantize(t: tensor.Tensor, config: NF4Config) -> NF4Tensor
Quantiza tensor para NF4