FP16・bfloat16ビットパターン可視化ツール

半精度浮動小数点数(FP16、IEEE 754 binary16)とbfloat16のビットパターンを可視化する無料ツール。10進数からビットへ、ビットから10進数へ相互変換でき、符号・指数部・仮数部を色分け表示します。機械学習の量子化・推論高速化の学習に。

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は指数部がfloat32(単精度)と同じ8ビット・同じバイアス(127)であるため、float32の仮数部を単純に切り捨てるだけで変換できるという実装上の利点があります。

使い方のヒント

  • 同じ0.1という値でも、FP16と bfloat16 では丸め誤差の出方がまったく異なります。フォーマットを切り替えて仮数部のビット列を見比べてみてください。
  • bfloat16はfloat32と指数部のビット幅・バイアスが同じため、65504を超えるような大きな値でもオーバーフローしにくいのが特徴です。逆にFP16は65504を超えるとすぐに無限大になります。
  • 「70000」をFP16に変換するとオーバーフローして無限大になりますが、bfloat16では正常に(精度は落ちつつも)表現できます。
  • 機械学習フレームワーク(PyTorch・TensorFlow)でモデルの量子化を行う際、bfloat16はfloat32からの変換が容易な一方、FP16は表現範囲が狭いため事前のスケーリングが必要になることがあります。
  • ビットパターンからの逆変換では、`0x`接頭辞付きの4桁16進数か、16桁の2進数(`0b`接頭辞は任意)で入力する必要があります。

よくある質問

どちらも合計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はfloat32と指数部のビット幅(8ビット)・バイアス(127)が完全に一致しているため、float32のビットパターンの仮数部を上位7ビットだけ残して切り捨てる(丸める)だけで変換できます。指数部の再計算や範囲チェックが不要なため、実装がシンプルになります。
ツールくん

余談ですが ― なぜ機械学習は「精度を落とした」数値表現を求めたのか

2018年前後、Googleが自社のTPU(Tensor Processing Unit)向けにbfloat16という新しい16ビット浮動小数点フォーマットを考案しました。それ以前から存在したFP16(IEEE 754の半精度)は画像処理やグラフィックス分野ですでに実用化されていましたが、指数部がわずか5ビットしかないため表現できる値の範囲が狭く、ディープラーニングの学習時に勾配が非常に小さくなったり大きくなったりする現象(勾配消失・勾配爆発)に対応しきれないという課題がありました。

bfloat16の設計思想は明快です。仮数部の精度を犠牲にする代わりに、指数部のビット幅をfloat32(単精度)とまったく同じ8ビットに保つことで、学習中に頻発する極端に大きい・小さい値を安全に扱えるようにしたのです。「Brain Floating Point」という名前は、Googleの機械学習研究部門「Google Brain」に由来します。

通常のコンピューター科学では、浮動小数点数の精度を落とすことは「バグの温床」として避けられてきました。しかしディープラーニングのモデルは、多少の数値誤差があっても最終的な予測精度にはほとんど影響しないという特殊な性質を持っています。この「多少不正確でも全体としては機能する」という性質を逆手に取り、メモリ使用量と計算コストを半分に抑えられる16ビット表現が広く普及した点は、コンピューター科学の常識とは一線を画す、機械学習分野ならではの最適化と言えるでしょう。