Mixed precision lets TensorFlow and Keras run supported model math in 16-bit types while keeping variables and selected numerically sensitive operations in float32. It is most useful when training on accelerator hardware where matrix multiplication, convolution, or memory bandwidth limits the batch throughput.
The setting is a process-local Keras dtype policy, so it affects layers created after the policy is set. Use mixed_float16 for NVIDIA GPU training, and use mixed_bfloat16 for TPU or supported CPU paths where bfloat16 is the preferred lower-precision type.
Set the policy before building the model, then keep the final prediction or loss-facing output in float32 when the output feeds a loss, probability, or metric calculation. Keras model.fit() handles dynamic loss scaling for mixed_float16, while custom GradientTape loops need explicit loss-scaling handling.
Steps to enable TensorFlow mixed precision:
- Activate the Python environment that runs the training job.
$ source ~/venvs/tf-gpu/bin/activate (tf-gpu) $
Use conda activate <name> instead when the project uses Conda.
Related: How to create a virtual environment for TensorFlow
Related: How to create a Conda environment for TensorFlow - Save a mixed precision smoke test as
train_mixed_precision.py
.
- train_mixed_precision.py
import os os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2" import tensorflow as tf tf.get_logger().setLevel("ERROR") tf.keras.utils.set_random_seed(42) mixed_precision = tf.keras.mixed_precision mixed_precision.set_global_policy("mixed_float16") inputs = tf.keras.Input(shape=(4,), name="features") x = tf.keras.layers.Dense(16, activation="relu", name="hidden")(inputs) outputs = tf.keras.layers.Dense(1, activation="sigmoid", dtype="float32", name="score")(x) model = tf.keras.Model(inputs, outputs) model.compile( optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"], ) features = tf.random.normal((32, 4)) labels = tf.cast(tf.reduce_sum(features, axis=1, keepdims=True) > 0, tf.float32) history = model.fit(features, labels, epochs=1, batch_size=8, verbose=0) print(f"TensorFlow {tf.__version__}") print(f"global_policy={mixed_precision.global_policy().name}") print(f"hidden_compute_dtype={model.get_layer('hidden').compute_dtype}") print(f"hidden_variable_dtype={model.get_layer('hidden').variable_dtype}") print(f"output_compute_dtype={model.get_layer('score').compute_dtype}") print(f"prediction_dtype={model(features[:2]).dtype.name}") print(f"loss={history.history['loss'][-1]:.4f}") print(f"accuracy={history.history['accuracy'][-1]:.4f}")
The global policy call must run before creating layers. The hidden layer inherits mixed_float16, while the final layer overrides the compute dtype to float32.
- Run the smoke test and confirm the policy, layer dtypes, output dtype, and training result.
(tf-gpu) $ python train_mixed_precision.py TensorFlow 2.21.0 global_policy=mixed_float16 hidden_compute_dtype=float16 hidden_variable_dtype=float32 output_compute_dtype=float32 prediction_dtype=float32 loss=0.8104 accuracy=0.4688
A CPU-only process can validate the API path, but mixed_float16 normally speeds up training only on recent NVIDIA GPUs. Use mixed_bfloat16 instead when the target accelerator is TPU or a supported CPU bfloat16 path.
- Put the global policy call near the top of the real training entry point.
import tensorflow as tf mixed_precision = tf.keras.mixed_precision mixed_precision.set_global_policy("mixed_float16")
Do not set the policy after creating the model, optimizer, or layers. Existing layers keep the policy they were created with.
- Keep the final model output in float32 when it feeds a loss or probability output.
inputs = tf.keras.Input(shape=(num_features,)) x = tf.keras.layers.Dense(256, activation="relu")(inputs) x = tf.keras.layers.Dense(128, activation="relu")(x) outputs = tf.keras.layers.Dense( num_classes, activation="softmax", dtype="float32", name="predictions", )(x) model = tf.keras.Model(inputs, outputs)
Intermediate layers can keep the mixed policy. The output override avoids passing float16 predictions into the loss or downstream probability handling.
- Compile and train the model with Keras model.fit().
model.compile( optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"], ) model.fit(train_ds, validation_data=val_ds, epochs=10)
Keras applies dynamic loss scaling automatically for mixed_float16 during model.fit(). Custom tf.GradientTape loops that apply optimizer steps directly should use tf.keras.mixed_precision.LossScaleOptimizer.
Related: How to run a custom training loop in TensorFlow - Remove the smoke-test file after the project training path reports the expected policy and dtypes.
(tf-gpu) $ rm train_mixed_precision.py
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.