FP16 (半精度): FP16 では、浮動小数点数が 16 ビットを使用して表現されます。符号ビット 1 ビット、指数部 5 ビット、小数部 (仮数部) 10 ビットで構成されます。この形式では、範囲内の小数値をより高い精度で表現できます。
BF16 (BFloat16): BF16 も 16 ビットを使用しますが、分布が異なります。 1 つの符号ビット、8 ビットの指数、7 ビットの仮数があります。この形式では、より広範囲の指数に対応するために、小数部の精度がある程度犠牲になります。
FP16 の範囲は狭いですが、仮数部が 10 ビットであるため、その範囲内の精度は高くなります。
BF16 は範囲が広いですが、8 ビットの指数と 7 ビットの仮数があるため、小数値の精度は低くなります。
3 つの例を使用して、FP16 と BF16 の違いを説明しましょう。 TensorFlow は、下部で共有されるテストとコードを作成するために使用されます:
元の値: 0.0001 — どちらのメソッドも
FP16: 0.00010001659393 (バイナリ: 0|00001|1010001110、16 進数: 068E) — 10 個の仮数と 5 つの指数
BF16: 0.00010013580322 (バイナリ: 0|01110001|1010010、16 進数: 38D2) — 7 つの仮数と 8 つの指数
ご覧のとおり、それらは異なる指数と仮数を持っているため、異なる方法で表現できます。 しかし、FP16 はより近い値でより正確に表現していることがわかります。
元の値: 1e-08 (0.00000001)
FP16: 0.00000000000000 (バイナリ: 0|00000|0000000000、16 進数: 0000)
BF16: 0.0000000100 1172 (バイナリ: 0|01100100| 0101100、16 進数: 322C)
これは非常に興味深い事例です。 FP16 は失敗し、結果は 0 になりますが、BF16 は特別な形式でそれを表すことができます。
元の値: 100000.00001
FP16: inf (バイナリ: 0|11111|0000000000、16 進数: 7C00)
BF16: 99840.00000000000000 (バイナリ: 0|1000) 1111|1000011、16 進数: 47C3 )
上記の場合、すべての指数ビットがいっぱいになり、値を表すのに十分ではないため、FP16 は失敗します。ただし、BF16 は動作します
FP16 は、ディープラーニングのトレーニングと推論、特に限られた範囲内で小さな小数値を表現する際に高い精度が必要なタスクによく使用されます。
BF16 は、小数部分の精度が多少犠牲になっても、より広範囲の表現可能な値から恩恵を受ける機械学習タスク用に設計されたハードウェア アーキテクチャで人気が高まっています。これは、大きな勾配を扱う場合、または小さな値の精度よりも広い範囲にわたる数値の安定性が重要な場合に特に役立ちます。
FP16 は、より狭い範囲内の分数値の精度が高いため、小さな数値を正確に表現する必要があるタスクに適しています。一方、BF16 は、ある程度の精度を犠牲にしてより広い範囲を提供するため、より広範囲の値を扱うタスクや、広範囲にわたる数値の安定性が重要なタスクに有利です。 FP16 と BF16 のどちらを選択するかは、当面の機械学習タスクの特定の要件によって異なります。
上記の理由により、安定拡散 XL (SDXL) トレーニングを行う場合、FP16 と BF16 ではわずかに異なる学習率が必要となり、BF16 の方が効果的であることがわかりました。
上記の例の生成に使用したコード
import tensorflow as tf import struct def float_to_binary(f): return ''.join(f'{b:08b}' for b in struct.pack('>f', f)) def display_fp16(value): fp16 = tf.cast(tf.constant(value, dtype=tf.float32), tf.float16) fp32 = tf.cast(fp16, tf.float32) binary = format(int.from_bytes(fp16.numpy().tobytes(), 'big'), '016b') sign = binary[0] exponent = binary[1:6] fraction = binary[6:] return f"FP16: {fp32.numpy():14.14f} (Binary: {sign}|{exponent}|{fraction}, Hex: {fp16.numpy().view('uint16'):04X})" def display_bf16(value): bf16 = tf.cast(tf.constant(value, dtype=tf.float32), tf.bfloat16) bf32 = tf.cast(bf16, tf.float32) binary = format(int.from_bytes(bf16.numpy().tobytes(), 'big'), '016b') sign = binary[0] exponent = binary[1:9] fraction = binary[9:] return f"BF16: {bf32.numpy():14.14f} (Binary: {sign}|{exponent}|{fraction}, Hex: {bf16.numpy().view('uint16'):04X})" values = [0.0001, 0.00000001, 100000.00001] for value in values: print(f"\nOriginal value: {value}") print(display_fp16(value)) print(display_bf16(value))
以上がFP と BF の違いは何ですか。ここでわかりやすい説明をしますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。