1、bfloat16 可以直接截取 float32 的前 16 位得到,所以在 float32 和 bfloat16 之间进行转换时非常容易,事实上 TF 也只提供了 bfloat16 和 float32 之间的转换,见 bfloat16.cc。
2、bfloat16 是 TPU 专用数据类型,其他硬件都不原生支持,因此对非 TPU 用户来说比较鸡肋,不如 IEEE float16;
3、和 IEEE float16 相比,动态范围更大(和 float32 一样大),但是尾数位更少(精度更低)。更大的动态范围意味着不容易下溢(上溢在实践中几乎不会发生,这里不考虑)。下溢的原因应该不是如 @张汉东 所说的梯度消失(现代网络已经不存在这种问题了吧?),而是网络训到一定程度之后很多数据样本过于简单,模型非常确定应该给出什么预测结果,导致 loss 很小,进而梯度很小。
先看看普通的 float16 训练神经网络存在什么困难:
NVidia 有篇文章Mixed Precision Training,里面画了一下 Multibox SSD network 的梯度分布,可以看到其中有很大一部分梯度都不在 float16 的范围内(红线左边会归零),导致模型没法在此基础上更新参数。于是 NVidia 提出了一个软件上的解决方案: loss scaling(先把 loss 扩大 S 倍,算完梯度再缩小 1/S 更新模型参数)。
还有另一种可能的硬件上的解决方案是重新定制一个 float16 标准,修改现行 float16 的指数位 bias,从 15 修改成 28 之类的值(相当于把 float16 的范围往下移动 2^13 左右)。我猜这种方案也可以取得类似的效果,但从 NVidia 的文章来看,不同任务需要的 scaling factor 不同,如果搞一个适合 dectection 的动态范围(或者说指数位 bias),很可能又不适合 language modelling 等任务,所以不好在硬件上实现(除非这个硬件专为某一个任务定制,这也太专门了)。
所以说 bfloat16 应该挺有前途的,动态范围大、适合的任务广,猜测未来可能有更多 ASIC 支持这种格式。但我不太看好 CPU/GPU 将对 bfloat16 提供原生支持,毕竟已经有 float16 了。
4、最后提一个奇葩问题,为什么看不到用 TPU 训多层 LSTM 语言模型的例子?看一些测评/听一些朋友说,TPU 上 LSTM 很难收敛= = 这个跟 bfloat16 的精度太低有关系吗?不过这个问题可能也不是特别重要,毕竟现在 Transformer 逐渐成了显学,加了 LayerNorm 以后稳定性拔群,随便训练随便收敛。
本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度,google,bing,sogou 等
© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有