很明显,为什么16位浮点格式开始被用于机器学习;它降低了存储和计算的成本,而且神经网络对数字精度出奇地不敏感。
我发现特别令人惊讶的是,从业者放弃了已经定义的半精度格式,转而支持只给有效数分配7位,而给指数分配8位的格式——完全和32位FP一样多。(维基百科比较了大脑浮动bfloat16
布局与IEEE binary16和一些24位格式。)
为什么有这么多指数位?到目前为止,我只找到了https://cloud.google.com/blog/products/ai-machine-learning/bfloat16-the-secret-to-high-performance-on-cloud-tpus
基于我们多年在谷歌产品和服务中训练和部署各种神经网络的经验,我们知道当我们设计Cloud tpu时,神经网络对指数的大小比尾数的大小要敏感得多。为了确保下溢、溢出和nan具有相同的行为,bfloat16具有与FP32相同的指数大小。然而,bfloat16处理异常的方式与FP32不同:它将异常刷新为零。与FP16不同,FP16通常需要通过损耗缩放等技术进行特殊处理[Mic 17], BF16在训练和运行深度神经网络时接近于成为FP32的直接替代品。
我还没有在任何类似谷歌规模的东西上进行神经网络实验,但在我所运行的实验中,绝对值大于1.0的权重或激活意味着它已经进入杂草,将螺旋上升到无穷大,如果计算机立即崩溃并显示错误信息,那么它将帮你一个忙。我从未见过或听说过任何情况下需要像单精度浮点的1e38这样的动态范围。
我错过了什么?
是否存在神经网络真的需要巨大动态范围的情况?如果是,如何,为什么?
是否有理由认为bfloat16使用与单精度相同的指数非常有益,即使有效数要小得多?
或者,真正的目标是将显着值缩小到绝对最小,以便将乘数器的芯片面积和能源成本最小化,这是FPU中最昂贵的部分;碰巧的是,这大约是7位;出于对齐的原因,总尺寸应该是2的幂;它不太适合8位;直到16,剩下的多余的位可以用来做点什么,最优雅的解决方案是保留8位指数?
从评论中收集一些讨论:
- 这大大简化了在没有硬件支持bfloat16的系统上的实现,因为实现可以通过忽略最后16位来简单地转换为IEEE单精度。
- 你引用Shibo Wang和Pankaj Kanwar的话说,发明者优先考虑的是动态范围而不是精度。这种实现保留了单精度浮点数的动态范围,并通过牺牲精度将存储空间减少了一半。
- 一些实现可能能够通过将尾数和指数表示为8位量(包括尾数的隐式前导1)来获得良好的性能。