Есть вопрос? Присоединяйтесь к сообществу на форуме TensorFlow. Посетите форум.

Смешанная точность

Посмотреть на TensorFlow.org Запускаем в Google Colab Посмотреть исходный код на GitHub Скачать блокнот

Обзор

Смешанная точность - это использование в модели во время обучения как 16-битных, так и 32-битных типов с плавающей запятой, чтобы она работала быстрее и использовала меньше памяти. Сохраняя определенные части модели в 32-битных типах для числовой стабильности, модель будет иметь меньшее время шага и одинаково хорошо обучаться с точки зрения метрик оценки, таких как точность. В этом руководстве описывается, как использовать API смешанной точности Keras для ускорения ваших моделей. Использование этого API может повысить производительность более чем в 3 раза на современных графических процессорах и 60% на TPU.

Сегодня в большинстве моделей используется тип float32 dtype, который занимает 32 бита памяти. Однако есть два типа данных с более низкой точностью, float16 и bfloat16, каждый из которых вместо этого занимает 16 бит памяти. Современные ускорители могут быстрее выполнять операции в 16-битных типах данных, поскольку у них есть специализированное оборудование для выполнения 16-битных вычислений, а 16-битные типы данных могут быстрее считываться из памяти.

Графические процессоры NVIDIA могут выполнять операции в float16 быстрее, чем в float32, а TPU могут выполнять операции в bfloat16 быстрее, чем float32. Следовательно, эти типы данных с более низкой точностью следует использовать, когда это возможно, на этих устройствах. Однако переменные и несколько вычислений должны по-прежнему находиться в float32 по числовым причинам, чтобы модель обучалась с таким же качеством. API смешанной точности Keras позволяет вам использовать сочетание float16 или bfloat16 с float32, чтобы получить преимущества производительности от float16 / bfloat16 и преимущества числовой стабильности от float32.

Настраивать

import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras import mixed_precision

Поддерживаемое оборудование

Хотя смешанная точность будет работать на большинстве оборудования, она ускорит только модели на последних графических процессорах NVIDIA и облачных TPU. Графические процессоры NVIDIA поддерживают сочетание float16 и float32, а TPU поддерживают сочетание bfloat16 и float32.

Среди графических процессоров NVIDIA GPU с вычислительной мощностью 7.0 или выше получат наибольший выигрыш в производительности от смешанной точности, поскольку они имеют специальные аппаратные блоки, называемые тензорными ядрами, для ускорения умножения и свертки матриц float16. Старые графические процессоры не дают преимущества в математической производительности при использовании смешанной точности, однако экономия памяти и пропускной способности может обеспечить некоторое ускорение. Вы можете посмотреть вычислительные возможности своего графического процессора на веб-странице NVIDIA CUDA GPU . Примеры графических процессоров, которые больше всего выиграют от смешанной точности, включают графические процессоры RTX, V100 и A100.

Вы можете проверить свой тип графического процессора следующим образом. Команда существует только в том случае, если установлены драйверы NVIDIA, поэтому в противном случае возникнет ошибка.

nvidia-smi -L
GPU 0: NVIDIA Tesla V100-SXM2-16GB (UUID: GPU-5fbd083a-e390-c0a4-23e2-c42f67b39b4a)

Все облачные TPU поддерживают bfloat16.

Даже на ЦП и старых графических процессорах, где не ожидается ускорения, API-интерфейсы смешанной точности все еще можно использовать для модульного тестирования, отладки или просто для опробования API. Однако на процессорах смешанная точность будет работать значительно медленнее.

Установка политики dtype

Чтобы использовать смешанную точность в Keras, вам необходимо создать tf.keras.mixed_precision.Policy , обычно называемую политикой dtype . Политики Dtype определяют уровни dtypes, в которых будут выполняться. В этом руководстве вы 'mixed_float16' политику из строки 'mixed_float16' и установите ее в качестве глобальной политики. Это приведет к тому, что впоследствии созданные слои будут использовать смешанную точность со смесью float16 и float32.

policy = mixed_precision.Policy('mixed_float16')
mixed_precision.set_global_policy(policy)
INFO:tensorflow:Mixed precision compatibility check (mixed_float16): OK
Your GPU will likely run quickly with dtype policy mixed_float16 as it has compute capability of at least 7.0. Your GPU: NVIDIA Tesla V100-SXM2-16GB, compute capability 7.0

Короче говоря, вы можете напрямую передать строку в set_global_policy , что обычно и делается на практике.

# Equivalent to the two lines above
mixed_precision.set_global_policy('mixed_float16')

Политика определяет два важных аспекта уровня: dtype, в котором выполняются вычисления уровня, и dtype переменных уровня. Выше вы создали политику mixed_float16 (т. mixed_precision.Policy созданную путем передачи строки 'mixed_float16' ее конструктору). С этой политикой слои используют вычисления с плавающей запятой 16 и переменные с плавающей запятой 32. Вычисления выполняются в float16 для производительности, но переменные должны храниться в float32 для числовой стабильности. Вы можете напрямую запросить эти свойства политики.

print('Compute dtype: %s' % policy.compute_dtype)
print('Variable dtype: %s' % policy.variable_dtype)
Compute dtype: float16
Variable dtype: float32

Как упоминалось ранее, политика mixed_float16 наиболее значительно повысит производительность графических процессоров NVIDIA с вычислительной мощностью не ниже 7,0. Политика будет работать на других графических процессорах и процессорах, но не может улучшить производительность. Для mixed_bfloat16 вместо этого следует использовать политику mixed_bfloat16 .

Построение модели

Далее приступим к построению простой модели. Очень маленькие игрушечные модели обычно не выигрывают от смешанной точности, потому что накладные расходы из среды выполнения TensorFlow обычно доминируют над временем выполнения, делая любое улучшение производительности на GPU незначительным. Поэтому давайте построим два больших Dense слоя по 4096 единиц в каждом, если используется графический процессор.

inputs = keras.Input(shape=(784,), name='digits')
if tf.config.list_physical_devices('GPU'):
  print('The model will run with 4096 units on a GPU')
  num_units = 4096
else:
  # Use fewer units on CPUs so the model finishes in a reasonable amount of time
  print('The model will run with 64 units on a CPU')
  num_units = 64
dense1 = layers.Dense(num_units, activation='relu', name='dense_1')
x = dense1(inputs)
dense2 = layers.Dense(num_units, activation='relu', name='dense_2')
x = dense2(x)
The model will run with 4096 units on a GPU

Каждый уровень имеет политику и по умолчанию использует глобальную политику. Таким образом, каждый из Dense слоев имеет политику mixed_float16 потому что вы ранее установили глобальную политику на mixed_float16 . Это заставит плотные слои выполнять вычисления float16 и иметь переменные float32. Они передают свои входные данные в float16 для выполнения вычислений float16, в результате чего их выходные данные становятся float16. Их переменные - это float32, и они будут преобразованы в float16 при вызове слоев, чтобы избежать ошибок из-за несоответствия dtype.

print(dense1.dtype_policy)
print('x.dtype: %s' % x.dtype.name)
# 'kernel' is dense1's variable
print('dense1.kernel.dtype: %s' % dense1.kernel.dtype.name)
<Policy "mixed_float16">
x.dtype: float16
dense1.kernel.dtype: float32

Затем создайте прогнозы вывода. Обычно вы можете создавать прогнозы выходных данных следующим образом, но это не всегда численно стабильно с float16.

# INCORRECT: softmax and model output will be float16, when it should be float32
outputs = layers.Dense(10, activation='softmax', name='predictions')(x)
print('Outputs dtype: %s' % outputs.dtype.name)
Outputs dtype: float16

Активация softmax в конце модели должна быть float32. Поскольку политика dtype - mixed_float16 , активация softmax обычно будет иметь тензоры вычисления dtype float16 и вывода float16.

Это можно исправить, разделив слои Dense и softmax и передав dtype='float32' слою softmax:

# CORRECT: softmax and model output are float32
x = layers.Dense(10, name='dense_logits')(x)
outputs = layers.Activation('softmax', dtype='float32', name='predictions')(x)
print('Outputs dtype: %s' % outputs.dtype.name)
Outputs dtype: float32

Передача dtype='float32' конструктору уровня softmax заменяет политику dtype уровня на политику float32 , которая выполняет вычисления и сохраняет переменные в float32. dtype=mixed_precision.Policy('float32') вы могли бы вместо этого передать dtype=mixed_precision.Policy('float32') ; слои всегда преобразуют аргумент dtype в политику. Поскольку уровень Activation не имеет переменных, переменная dtype политики игнорируется, но вычисляемый dtype политики float32 приводит к тому, что softmax и выход модели будут float32.

Добавление softmax float16 в середине модели нормально, но softmax в конце модели должно быть в float32. Причина в том, что если промежуточным тензором, текущим от softmax к проигрышу, является float16 или bfloat16, могут возникнуть числовые проблемы.

Вы можете заменить dtype любого слоя на float32, передав dtype='float32' если вы думаете, что он не будет численно стабильным с вычислениями float16. Но обычно это необходимо только на последнем слое модели, так как большинство уровней имеют достаточную точность при использовании mixed_float16 и mixed_bfloat16 .

Даже если модель не заканчивается softmax, на выходе все равно должно быть float32. Хотя это и не требуется для этой конкретной модели, выходные данные модели могут быть преобразованы в float32 следующим образом:

# The linear activation is an identity function. So this simply casts 'outputs'
# to float32. In this particular case, 'outputs' is already float32 so this is a
# no-op.
outputs = layers.Activation('linear', dtype='float32')(outputs)

Затем закончите и скомпилируйте модель и сгенерируйте входные данные:

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(loss='sparse_categorical_crossentropy',
              optimizer=keras.optimizers.RMSprop(),
              metrics=['accuracy'])

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step

В этом примере приведение входных данных из int8 в float32. Вы не выполняете приведение к float16, поскольку деление на 255 выполняется процессором, который выполняет операции float16 медленнее, чем операции float32. В этом случае разница в производительности незначительна, но в целом вы должны запускать математику обработки ввода в float32, если она выполняется на ЦП. Первый уровень модели будет преобразовывать входные данные в float16, поскольку каждый уровень преобразует входные данные с плавающей запятой в свой вычисляемый dtype.

Получены начальные веса модели. Это позволит снова тренироваться с нуля, нагружая веса.

initial_weights = model.get_weights()

Тренировка модели с помощью Model.fit

Далее обучаем модель:

history = model.fit(x_train, y_train,
                    batch_size=8192,
                    epochs=5,
                    validation_split=0.2)
test_scores = model.evaluate(x_test, y_test, verbose=2)
print('Test loss:', test_scores[0])
print('Test accuracy:', test_scores[1])
Epoch 1/5
6/6 [==============================] - 1s 61ms/step - loss: 8.6004 - accuracy: 0.3090 - val_loss: 1.2854 - val_accuracy: 0.6582
Epoch 2/5
6/6 [==============================] - 0s 29ms/step - loss: 0.8481 - accuracy: 0.7540 - val_loss: 0.4211 - val_accuracy: 0.8837
Epoch 3/5
6/6 [==============================] - 0s 29ms/step - loss: 0.3853 - accuracy: 0.8770 - val_loss: 0.4489 - val_accuracy: 0.8570
Epoch 4/5
6/6 [==============================] - 0s 29ms/step - loss: 0.2945 - accuracy: 0.9076 - val_loss: 0.3176 - val_accuracy: 0.9022
Epoch 5/5
6/6 [==============================] - 0s 28ms/step - loss: 0.3327 - accuracy: 0.8990 - val_loss: 0.1799 - val_accuracy: 0.9427
313/313 - 0s - loss: 0.1818 - accuracy: 0.9425
Test loss: 0.1818101704120636
Test accuracy: 0.9424999952316284

Обратите внимание, что модель печатает время на шаг в журналах: например, «25 мс / шаг». Первая эпоха может быть медленнее, поскольку TensorFlow тратит некоторое время на оптимизацию модели, но впоследствии время на шаг должно стабилизироваться.

Если вы запускаете это руководство в Colab, вы можете сравнить производительность смешанной точности с float32. Для этого измените политику с mixed_float16 на float32 в разделе «Установка политики dtype», затем повторно запустите все ячейки до этого момента. На графических процессорах с вычислительными возможностями 7.X вы должны увидеть, что время на шаг значительно увеличится, что указывает на то, что модель ускорена за счет смешанной точности. Обязательно измените политику обратно на mixed_float16 и повторно запустите ячейки, прежде чем продолжить работу с руководством.

На графических процессорах с вычислительной мощностью не менее 8,0 (графические процессоры Ampere и выше) вы, вероятно, не увидите улучшения производительности игрушечной модели в этом руководстве при использовании смешанной точности по сравнению с float32. Это связано с использованием TensorFloat-32 , который автоматически использует математику с более низкой точностью в некоторых операциях float32, таких как tf.linalg.matmul . TensorFloat-32 дает некоторые преимущества смешанной точности при использовании float32. Однако в реальных моделях вы по-прежнему обычно будете видеть значительное улучшение производительности за счет смешанной точности из-за экономии полосы пропускания памяти и операций, которые TensorFloat-32 не поддерживает.

Если вы используете смешанную точность на TPU, вы не увидите такого большого прироста производительности по сравнению с запуском смешанной точности на графических процессорах, особенно графических процессорах до Ampere. Это связано с тем, что TPU выполняют определенные операции в bfloat16 под капотом даже с политикой dtype по умолчанию float32. Это похоже на то, как графические процессоры Ampere по умолчанию используют TensorFloat-32. По сравнению с графическими процессорами Ampere, TPU обычно демонстрируют меньший прирост производительности при смешанной точности на реальных моделях.

Для многих реальных моделей смешанная точность также позволяет удвоить размер пакета без нехватки памяти, поскольку тензоры float16 занимают половину памяти. Однако это не относится к этой игрушечной модели, поскольку вы, вероятно, можете запустить модель в любом dtype, где каждый пакет состоит из всего набора данных MNIST из 60 000 изображений.

Масштаб потерь

Масштабирование потерь - это метод, который tf.keras.Model.fit автоматически выполняет с политикой mixed_float16 чтобы избежать mixed_float16 числового значения. В этом разделе описывается, что такое масштабирование потерь, а в следующем разделе описано, как его использовать с настраиваемым циклом обучения.

Незаполнение и переполнение

Тип данных float16 имеет более узкий динамический диапазон по сравнению с float32. Это означает, что значения выше $ 65504 $ будут переполняться до бесконечности, а значения ниже $ 6.0 \ times 10 ^ {- 8} $ будут переполняться до нуля. float32 и bfloat16 имеют гораздо более высокий динамический диапазон, поэтому переполнение и потеря значимости не являются проблемой.

Например:

x = tf.constant(256, dtype='float16')
(x ** 2).numpy()  # Overflow
inf
x = tf.constant(1e-5, dtype='float16')
(x ** 2).numpy()  # Underflow
0.0

На практике переполнение с float16 случается редко. Кроме того, недостаточное заполнение во время прямого прохода также редко возникает. Однако во время обратного прохода градиенты могут опуститься до нуля. Масштабирование убытков - это метод предотвращения такого переполнения.

Обзор масштабирования потерь

Основная концепция масштабирования потерь проста: просто умножьте потери на какое-нибудь большое число, скажем, $ 1024, и вы получите значение масштаба потерь . Это вызовет масштабирование градиентов на 1024 доллара США, что значительно снизит вероятность потери значимости. После того, как окончательные градиенты вычислены, разделите их на 1024 $, чтобы вернуть им правильные значения.

Псевдокод этого процесса:

loss_scale = 1024
loss = model(inputs)
loss *= loss_scale
# Assume `grads` are float32. You do not want to divide float16 gradients.
grads = compute_gradient(loss, model.trainable_variables)
grads /= loss_scale

Выбор шкалы убытков может быть сложной задачей. Если шкала потерь слишком мала, градиенты все равно могут опуститься до нуля. Если слишком высоко, возникает обратная проблема: градиенты могут выходить за пределы бесконечности.

Чтобы решить эту проблему, TensorFlow динамически определяет масштаб потерь, поэтому вам не нужно выбирать его вручную. Если вы используете tf.keras.Model.fit , масштабирование потерь выполняется за вас, поэтому вам не нужно выполнять дополнительную работу. Если вы используете настраиваемый цикл обучения, вы должны явно использовать специальную оболочку оптимизатора tf.keras.mixed_precision.LossScaleOptimizer , чтобы использовать масштабирование потерь. Это описано в следующем разделе.

Обучение модели с помощью настраиваемого цикла обучения

До сих пор вы обучили модель tf.keras.Model.fit со смешанной точностью с помощью tf.keras.Model.fit . Далее вы будете использовать смешанную точность с настраиваемым циклом обучения. Если вы еще не знаете, что такое настраиваемый цикл обучения, сначала прочтите руководство по индивидуальному обучению .

Для запуска пользовательского цикла обучения со смешанной точностью требуется два изменения вместо его выполнения в float32:

  1. Постройте модель со смешанной точностью (вы уже это сделали)
  2. Явно используйте масштабирование потерь, если используется mixed_float16 .

На шаге (2) вы будете использовать класс tf.keras.mixed_precision.LossScaleOptimizer , который является tf.keras.mixed_precision.LossScaleOptimizer для оптимизатора и применяет масштабирование потерь. По умолчанию он динамически определяет масштаб убытков, поэтому вам не нужно выбирать его. LossScaleOptimizer следующим образом.

optimizer = keras.optimizers.RMSprop()
optimizer = mixed_precision.LossScaleOptimizer(optimizer)

При желании можно выбрать явную шкалу потерь или иным образом настроить поведение масштабирования потерь, но настоятельно рекомендуется сохранить поведение масштабирования потерь по умолчанию, так как было обнаружено, что оно хорошо работает на всех известных моделях. См. Документацию tf.keras.mixed_precision.LossScaleOptimizer если вы хотите настроить поведение масштабирования потерь.

Затем определите объект потерь иtf.data.Dataset s:

loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
train_dataset = (tf.data.Dataset.from_tensor_slices((x_train, y_train))
                 .shuffle(10000).batch(8192))
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(8192)

Затем определите функцию шага обучения. Вы будете использовать два новых метода из оптимизатора масштаба потерь для масштабирования потерь и масштабирования градиентов:

  • get_scaled_loss(loss) : get_scaled_loss(loss) на масштаб убытка
  • get_unscaled_gradients(gradients) : принимает список масштабированных градиентов в качестве входных данных и делит каждый из них на масштаб потерь, чтобы не масштабировать их.

Эти функции необходимо использовать для предотвращения потери значимости в градиентах. LossScaleOptimizer.apply_gradients затем применит градиенты, если ни один из них не имеет Inf s или NaN . Он также обновит шкалу потерь, уменьшив ее вдвое, если градиенты имеют Inf s или NaN и потенциально увеличив ее в противном случае.

@tf.function
def train_step(x, y):
  with tf.GradientTape() as tape:
    predictions = model(x)
    loss = loss_object(y, predictions)
    scaled_loss = optimizer.get_scaled_loss(loss)
  scaled_gradients = tape.gradient(scaled_loss, model.trainable_variables)
  gradients = optimizer.get_unscaled_gradients(scaled_gradients)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))
  return loss

LossScaleOptimizer , скорее всего, пропустит первые несколько шагов в начале обучения. Масштаб убытков начинается с высокого уровня, поэтому можно быстро определить оптимальный масштаб убытков. Через несколько шагов шкала потерь стабилизируется, и очень немногие шаги будут пропущены. Этот процесс происходит автоматически и не влияет на качество обучения.

Теперь определите тестовый шаг:

@tf.function
def test_step(x):
  return model(x, training=False)

Загрузите начальные веса модели, чтобы вы могли переучиться с нуля:

model.set_weights(initial_weights)

Наконец, запустите настраиваемый цикл обучения:

for epoch in range(5):
  epoch_loss_avg = tf.keras.metrics.Mean()
  test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(
      name='test_accuracy')
  for x, y in train_dataset:
    loss = train_step(x, y)
    epoch_loss_avg(loss)
  for x, y in test_dataset:
    predictions = test_step(x)
    test_accuracy.update_state(y, predictions)
  print('Epoch {}: loss={}, test accuracy={}'.format(epoch, epoch_loss_avg.result(), test_accuracy.result()))
Epoch 0: loss=3.7858102321624756, test accuracy=0.7168999910354614
Epoch 1: loss=0.5736480355262756, test accuracy=0.8765000104904175
Epoch 2: loss=0.3463210463523865, test accuracy=0.9394000172615051
Epoch 3: loss=0.33968204259872437, test accuracy=0.9503999948501587
Epoch 4: loss=0.2318723201751709, test accuracy=0.939300000667572

Советы по производительности графического процессора

Вот несколько советов по производительности при использовании смешанной точности на графических процессорах.

Увеличение размера партии

Если это не влияет на качество модели, попробуйте запустить с двойным размером партии при смешанной точности. Поскольку тензоры float16 используют половину памяти, это часто позволяет удвоить размер пакета без нехватки памяти. Увеличение размера пакета обычно увеличивает пропускную способность обучения, то есть количество обучающих элементов в секунду, на котором может работать ваша модель.

Обеспечение использования тензорных ядер графического процессора

Как упоминалось ранее, современные графические процессоры NVIDIA используют специальный аппаратный блок, называемый тензорными ядрами, который может очень быстро умножать матрицы float16. Однако тензорные ядра требуют, чтобы определенные размеры тензоров были кратны 8. В приведенных ниже примерах аргумент выделен жирным шрифтом тогда и только тогда, когда он должен быть кратен 8 для использования тензорных ядер.

  • tf.keras.layers.Dense ( единицы = 64 )
  • tf.keras.layers.Conv2d ( фильтры = 48 , размер ядра = 7, шаг = 3)
    • И аналогично для других сверточных слоев, таких как tf.keras.layers.Conv3d
  • tf.keras.layers.LSTM ( единицы = 64 )
    • И аналогично для других RNN, таких как tf.keras.layers.GRU
  • tf.keras.Model.fit (эпохи = 2, размер партии = 128 )

По возможности вам следует попробовать использовать тензорные ядра. Если вы хотите узнать больше, руководство по производительности глубокого обучения NVIDIA описывает точные требования для использования тензорных ядер, а также другую информацию о производительности, связанную с тензорными ядрами.

XLA

XLA - это компилятор, который может еще больше повысить производительность смешанной точности, а также производительность float32 в меньшей степени. Подробную информацию см. В руководстве XLA .

Советы по производительности Cloud TPU

Как и в случае с графическими процессорами, вам следует попробовать удвоить размер пакета при использовании облачных TPU, потому что тензоры bfloat16 используют половину памяти. Удвоение размера пакета может увеличить пропускную способность обучения.

TPU не требуют какой-либо другой настройки, ориентированной на смешанную точность, для достижения оптимальной производительности. Они уже требуют использования XLA. TPU выигрывают от того, что определенные размеры кратны 128 $, но это в равной степени относится и к типу float32, и к смешанной точности. Общие советы по производительности TPU, применимые как к тензорам со смешанной точностью, так и к тензорам float32, можно найти в руководстве по производительности Cloud TPU .

Резюме

  • Вам следует использовать смешанную точность, если вы используете TPU или графические процессоры NVIDIA с вычислительной мощностью не ниже 7.0, поскольку это повысит производительность до 3 раз.
  • Вы можете использовать смешанную точность со следующими строками:

    # On TPUs, use 'mixed_bfloat16' instead
    mixed_precision.set_global_policy('mixed_float16')
    
  • Если ваша модель заканчивается на softmax, убедитесь, что это float32. И независимо от того, на чем заканчивается ваша модель, убедитесь, что на выходе получается float32.

  • Если вы используете настраиваемый цикл обучения с mixed_float16 , в дополнение к приведенным выше строкам вам необходимо обернуть оптимизатор tf.keras.mixed_precision.LossScaleOptimizer . Затем вызовите optimizer.get_scaled_loss для масштабирования потерь и optimizer.get_unscaled_gradients для масштабирования градиентов.

  • Удвойте размер обучающего пакета, если это не снижает точность оценки

  • На графических процессорах убедитесь, что большинство тензорных размеров кратны 8 долларам, чтобы максимизировать производительность.

Дополнительные примеры смешанной точности с использованием API tf.keras.mixed_precision найти в официальном репозитории моделей . Большинство официальных моделей, таких как ResNet и Transformer , будут работать со смешанной точностью при передаче --dtype=fp16 .