FP16 (половинная точность): в FP16 число с плавающей запятой представляется с использованием 16 бит. Он состоит из 1 бита знака, 5 бит для показателя степени и 10 бит для дроби (мантиссы). Этот формат обеспечивает более высокую точность представления дробных значений в пределах его диапазона.
BF16 (BFloat16): BF16 также использует 16 бит, но с другим распределением. Он имеет 1 бит знака, 8 бит для экспоненты и 7 бит для мантиссы. В этом формате жертвуется некоторая точность дробной части, чтобы охватить более широкий диапазон показателей.
FP16 имеет меньший диапазон, но более высокую точность в этом диапазоне из-за 10-битной мантиссы.
BF16 имеет более широкий диапазон, но более низкую точность для дробных значений из-за 8-битной экспоненты и 7-битной мантиссы.
Давайте воспользуемся примерами, чтобы проиллюстрировать различия между FP16 и BF16 на трех примерах. TensorFlow используется для размещения тестов и кода внизу:
Исходное значение: 0,0001 — Оба метода могут представлять
FP16: 0,00010001659393 (двоичный: 0|00001|1010001110, шестнадцатеричный: 068E) — 10 мантисс и 5 экспонент
BF16: 0,00010013580322 (двоичный: 0|01110001|1010010, шестнадцатеричный: 38D2) — 7 мантисс и 8 экспонент
Как видите, они имеют разные показатель степени и мантиссу и, следовательно, могут представлять по-разному. Но мы видим, что FP16 представил это более точно и с более близким значением.
Исходное значение: 1e-08 (0.00000001)
FP16: 0.00000000000000 (двоичный: 0|00000|0000000000, шестнадцатеричный: 0000)
BF16: 0.00000001001 172 (Двоичный: 0|01100100| 0101100, Hex: 322C)
Это очень интересный случай. FP16 терпит неудачу и возвращает результат 0, но BF16 может представить его в специальном форматировании.
Исходное значение: 100000.00001
FP16: inf (двоичный: 0|11111|0000000000, шестнадцатеричный: 7C00)
BF16: 99840.00000000000000 (двоичный: 0|10001 111|1000011, Шестнадцатеричный: 47C3 )
В приведенном выше случае FP16 завершается неудачей, поскольку все биты экспоненты становятся полными и недостаточными для представления значения. Однако BF16 работает
FP16 обычно используется при обучении глубокому обучению и умозаключении, особенно для задач, требующих высокой точности представления небольших дробных значений в ограниченном диапазоне.
BF16 становится популярным в аппаратных архитектурах, предназначенных для задач машинного обучения, которые выигрывают от более широкого диапазона представимых значений, даже за счет некоторой точности дробной части. Это особенно полезно при работе с большими градиентами или когда численная стабильность в широком диапазоне важнее точности малых значений.
FP16 обеспечивает более высокую точность для дробных значений в меньшем диапазоне, что делает его подходящим для задач, требующих точного представления небольших чисел. BF16, с другой стороны, обеспечивает более широкий диапазон за счет некоторой точности, что делает его выгодным для задач, которые включают более широкий спектр значений или где решающее значение имеет числовая стабильность в широком диапазоне. Выбор между FP16 и BF16 зависит от конкретных требований решаемой задачи машинного обучения.
По всем вышеперечисленным причинам при обучении Stable Diffusion 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))
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3