FP16与bfloat16位模式可视化工具

可视化半精度浮点数(FP16、IEEE 754 binary16)和bfloat16的位模式。支持十进制与位模式互相转换,符号位、指数部、尾数部分色显示。适合学习机器学习中的量化与推理加速。

FP16与bfloat16的结构比较

两者合计都是16位,但指数部与尾数部的位数分配不同,导致可表示的数值范围和精度完全不同。

项目 FP16(IEEE 754 半精度) bfloat16
总位数 16 16
指数部位数 5 8
尾数部位数 10 7
可表示的数值范围 约±6.1×10⁻⁵ 至 ±65504(范围较窄但尾数位多、精度较高) 约±1.2×10⁻³⁸ 至 ±3.4×10³⁸(与float32相同的宽范围,但精度较低)
主要用途 图像处理、图形学、推理时的省内存化(半精度训练) 深度学习训练(TPU、最新GPU)。从float32转换时无需担心指数溢出

bfloat16的指数部位数(8位)和偏移量(127)与float32(单精度)完全相同,因此只需截断float32的尾数部即可转换,这是实现上的一个优势。

看清 FP16 与 bfloat16 的位是怎样排布的

虽同占十六位,FP16(即 IEEE 754 binary16)与 bfloat16 分配这些位的方式却大不相同。本工具在十进制数与位模式之间双向转换,并把符号、指数、尾数分别着色,让这份差别看得见,而不只是读得到。

**关键正在于分配之别。FP16 给指数五位、给尾数十位,bfloat16 则给指数八位、给尾数七位。** 八位指数恰与单精度相同,由此生出两条性质:其一,**bfloat16 所能表示的取值范围与 FP32 相同**;其二,**由 FP32 转换过来,不过是截取高十六位而已。** 机器学习偏爱 bfloat16 正是为此——训练途中数值飞出范围而把整轮毁掉的风险小得多。代价则是尾数只有七位,**精度比 FP16 来得粗。** 要精度便取 FP16,要范围便取 bfloat16。

使用方法

  1. 选择转换的方向 十进制到位,或位到十进制,两者皆可。
  2. 输入数值 十进制数或一串 0 与 1 皆可。
  3. 阅读着色的位 **符号、指数、尾数各以自己的颜色标出。**
  4. 把 FP16 与 bfloat16 并置 **同一个数用两种格式表示,便知它们在何处分道扬镳。**

用好本工具的小技巧

  • 即使是同一个值0.1,FP16和bfloat16的舍入误差表现也完全不同。切换格式比较尾数部的位模式吧。
  • bfloat16的指数部位数和偏移量与float32相同,因此即使是超过65504的大数值也不易溢出。相反FP16一旦超过65504就会立即变为无穷大。
  • 将"70000"转换为FP16会溢出变为无穷大,而bfloat16则能正常表示(精度有所下降)。
  • 在PyTorch、TensorFlow等机器学习框架中进行模型量化时,bfloat16容易从float32转换,而FP16由于范围较窄有时需要预先缩放。
  • 从位模式逆向转换为十进制时,需输入带`0x`前缀的4位十六进制值,或16位二进制值(`0b`前缀可省略)。

这些场景会用到

理解量化的代价

**可以具体弄清:模型降到十六位时,数值会被舍入到什么地步。**

在两种格式间取舍

它为「您这件事要的是范围还是精度」提供了判断的材料。

找出溢出的起点

**可以拿真实数值试一试:一旦超过 FP16 所能表示的最大数会怎样。**

学习浮点数的机理

可以一位一位地追下去,看指数与尾数如何合力表出一个数。

浮点数的术语

符号位
最高的那一位,给出正负:0 为正,1 为负。
指数
表示数值量级的部分。**FP16 拨给它五位,bfloat16 拨给它八位。**
尾数
相当于有效数字的部分。**FP16 有十位,bfloat16 有七位,这道差距正是精度之别。**
bfloat16
**一种把指数保持在 FP32 的八位的十六位格式。** 它把存储减半,而不牺牲范围。
次正规数
指数取到最小时所用的表示,可表出极其贴近零的数值。
量化
以更少的位数表示模型权重的做法。**存储与计算随之减少,精度也随之下降。**

常见问题

两者合计都是16位,但FP16(IEEE 754半精度)是指数部5位、尾数部10位,而bfloat16是指数部8位、尾数部7位。FP16尾数位多精度更高但范围较窄,bfloat16能表示与float32相同的宽范围但精度较低。

深度学习训练中,梯度和参数可能变得非常大或非常小,因此更倾向于使用能保持float32那样宽的表示范围(不易溢出/下溢)同时将内存和计算量减半的bfloat16。FP16范围较窄容易溢出,训练时有时需要额外的损失缩放(loss scaling)。

约65504。若将超过此值的数转换为FP16,会因溢出而变为无穷大(Infinity)。而bfloat16与float32指数部位数相同,可表示约3.4×10³⁸的数值。

指数部全为0而尾数部不为0的位模式。常规(正规化)浮点数尾数有隐含的前导1,而非正规数省略了这一点,从而能表示比通常最小值更接近零的值(但牺牲了有效精度)。

bfloat16的指数部位数(8位)和偏移量(127)与float32完全一致,因此只需保留float32位模式尾数部的高7位(并四舍五入)即可转换,无需重新计算指数或检查范围,实现十分简单。
工具君

闲话 ― 为何机器学习需要"降低精度"的数值表示

2018年前后,Google为其TPU(Tensor Processing Unit)设计了一种新的16位浮点格式bfloat16。此前已存在的FP16(IEEE 754半精度)已在图像处理和图形学领域实用化,但由于指数部仅5位,可表示的数值范围较窄,难以应对深度学习训练中梯度时而极小、时而极大的现象(梯度消失、梯度爆炸)。

bfloat16的设计思路很明确:牺牲尾数部的精度,换取与float32(单精度)完全相同的8位指数部宽度,从而能安全处理训练过程中频繁出现的极大极小值。"Brain Floating Point"这个名字来源于Google的机器学习研究部门"Google Brain"。

在传统计算机科学中,降低浮点数精度一直被视为"漏洞的温床"而被避免。但深度学习模型有一种特殊性质:即使存在一定的数值误差,对最终预测精度的影响也微乎其微。利用这种"稍有不精确但整体仍能工作"的特性,将内存占用和计算成本减半的16位表示得以广泛普及,这可以说是有别于传统计算机科学常识的、机器学习领域独有的优化。