MCPcopy Create free account
hub / github.com/bitsandbytes-foundation/bitsandbytes / create_normal_map

Function create_normal_map

bitsandbytes/functional.py:169–224  ·  view source on GitHub ↗

Create the NormalFloat (NF4) quantization map. Constructs a lookup table of 16 quantization values (stored in a 256-element tensor for indexing convenience) derived from quantiles of the standard normal distribution N(0, 1). Each bin has approximately equal probability mass under the no

(offset=0.9677083, use_extra_value=True)

Source from the content-addressed store, hash-verified

167
168
169def create_normal_map(offset=0.9677083, use_extra_value=True):
170 """Create the NormalFloat (NF4) quantization map.
171
172 Constructs a lookup table of 16 quantization values (stored in a 256-element tensor for
173 indexing convenience) derived from quantiles of the standard normal distribution N(0, 1).
174 Each bin has approximately equal probability mass under the normal distribution, which is
175 optimal for normally-distributed data like neural network weights.
176
177 Unlike floating-point types (FP4, FP8), NF4 is NOT a float encoding — the 4-bit index is
178 simply a lookup into this table. There is no sign/exponent/mantissa decomposition.
179
180 The values are generated by computing ``scipy.stats.norm.ppf()`` (inverse CDF) at evenly
181 spaced quantile points, then normalizing to [-1, 1].
182
183 For more details, see: QLoRA: Efficient Finetuning of Quantized LLMs
184 (https://arxiv.org/abs/2305.14314)
185
186 Args:
187 offset: The outermost quantile boundary, controlling the range of the normal distribution
188 that is covered. ``norm.ppf(offset)`` gives the largest bin edge in standard deviations.
189 The default (0.9677083) covers up to ~1.845 standard deviations and was empirically
190 optimized to minimize quantization error for typical neural network weight distributions.
191 use_extra_value: If True, creates an asymmetric type with 8 negative and 9 positive values
192 (including zero), for 15 non-zero values total. If False, creates a symmetric type
193 with 7 negative and 7 positive values (14 non-zero values total).
194
195 Returns:
196 A 256-element tensor where the first 16 values are the sorted NF4 quantization levels
197 normalized to [-1, 1], and the remaining values are zero (padding for 8-bit indexing).
198 """
199 try:
200 from scipy.stats import norm
201 except ImportError as ie:
202 raise ImportError(
203 "Scipy is required for `create_normal_map`. Install `bitsandbytes` with the `[test]` extra.",
204 ) from ie
205
206 if use_extra_value:
207 # one more positive value, this is an asymmetric type
208 v1 = norm.ppf(torch.linspace(offset, 0.5, 9)[:-1]).tolist()
209 v2 = [0] * (256 - 15) ## we have 15 non-zero values in this data type
210 v3 = (-norm.ppf(torch.linspace(offset, 0.5, 8)[:-1])).tolist()
211 else:
212 v1 = norm.ppf(torch.linspace(offset, 0.5, 8)[:-1]).tolist()
213 v2 = [0] * (256 - 14) ## we have 14 non-zero values in this data type
214 v3 = (-norm.ppf(torch.linspace(offset, 0.5, 8)[:-1])).tolist()
215
216 v = v1 + v2 + v3
217
218 values = torch.Tensor(v)
219 values = values.sort().values
220 values /= values.max()
221
222 assert values.numel() == 256
223
224 return values
225
226

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected