Mixed Precision
El entrenamiento de precisión mixta utiliza cálculos de 16 bits y pesos maestros FP32 para las redes neuronales, lo que reduce el uso de memoria y el tiempo de entrenamiento. Descubre el escalado de pérdidas, BF16 y AMP.
La precisión mixta es una técnica de entrenamiento que realiza la mayoría de los cálculos de una red neuronal en un formato de coma flotante de 16 bits, ya sea FP16 (precisión media) o BF16, mientras mantiene una copia maestra de 32 bits (FP32) de los pesos del modelo y ejecuta en FP32 las operaciones numéricamente sensibles. Los valores de 16 bits ocupan la mitad de memoria y ancho de banda que los de FP32, y los Tensor Cores de las GPU modernas los multiplican mucho más rápido; por eso, la precisión mixta reduce el tiempo de entrenamiento y permite alojar en memoria tamaños de lote mayores, manteniendo una precisión equivalente a FP32. La receta descrita por Micikevicius et al. en 2018, con pesos maestros FP32, operaciones aritméticas FP16 y escalado de la pérdida, es lo que los frameworks de aprendizaje profundo automatizan hoy bajo el nombre de precisión mixta automática (AMP).
Cómo funciona la precisión mixta#
Tres componentes permiten que la retropropagación y las actualizaciones de pesos en el entrenamiento de 16 bits alcancen la misma precisión que el entrenamiento FP32:
- Pesos maestros FP32: El optimizador aplica cada actualización a una copia FP32 de los pesos. Una actualización minúscula añadida directamente a un peso FP16 a menudo se perdería por redondeo, porque FP16 conserva solo unas tres cifras decimales significativas.
- Precisión por operación: Un contexto autocast ejecuta multiplicaciones de matrices y convoluciones en 16 bits, donde los Tensor Cores ofrecen la mayor aceleración, y mantiene las reducciones, softmax y la función de pérdida en FP32.
- Escalado de la pérdida: FP16 no puede representar magnitudes inferiores a aproximadamente 6 × 10⁻⁸, por lo que muchos gradientes pequeños sufrirían subdesbordamiento y pasarían a ser cero. Multiplicar la pérdida por un factor de escala antes de la retropropagación desplaza todos los gradientes al rango de FP16, y los gradientes se dividen por el mismo factor antes de actualizar los pesos.
En PyTorch AMP, torch.autocast gestiona la conversión de tipos por operación y GradScaler gestiona el escalado de la pérdida:
import torch
from torch import nn
# Use FP16 on an NVIDIA GPU and BF16 on CPU
device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.float16 if device == "cuda" else torch.bfloat16
model = nn.Linear(512, 10).to(device) # master weights stay in FP32
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scaler = torch.amp.GradScaler(device, enabled=dtype == torch.float16) # loss scaling for FP16 only
x = torch.randn(64, 512, device=device)
with torch.autocast(device_type=device, dtype=dtype):
out = model(x) # the matrix multiply runs in 16-bit
loss = out.float().pow(2).mean()
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
print(f"Output: {out.dtype}, weights: {model.weight.dtype}, gradients: {model.weight.grad.dtype}")En CPU, el fragmento muestra torch.bfloat16 para la salida de la capa y torch.float32 para los pesos y sus gradientes; en una GPU NVIDIA, la salida es torch.float16. Las operaciones de 16 bits y los pesos maestros FP32 coexisten en un mismo paso de entrenamiento.
GradScaler de PyTorch ajusta dinámicamente la escala. Empieza en 65,536, reduce la escala a la mitad y omite el paso siempre que los gradientes escalados contienen valores inf o NaN, y duplica la escala tras 2,000 pasos consecutivos sin desbordamiento, de modo que el factor se estabiliza justo por debajo del punto en que los gradientes se desbordan.
FP16, BF16 y precisiones inferiores#
FP16 dedica 5 bits al exponente y 10 a la mantisa, por lo que ofrece precisión, pero se desborda por encima de 65,504. BF16 conserva los 8 bits de exponente de FP32 y cubre el mismo rango, hasta aproximadamente 3.4 × 10³⁸, pero solo tiene 7 bits de mantisa; así, no necesita escalado de la pérdida, a cambio de un redondeo menos preciso. BF16 funciona en GPU NVIDIA a partir de la generación Ampere, en las TPU de Google y en muchas CPU recientes, y es el formato de entrenamiento habitual para los modelos de lenguaje grandes. La misma idea se extiende a FP8 en GPU Hopper y Blackwell mediante Transformer Engine de NVIDIA, y a formatos FP4 como NVFP4 en Blackwell.
La precisión mixta en la práctica#
El principal riesgo práctico de AMP es que un modelo o una GPU genere pérdidas NaN con operaciones de 16 bits. El entrenamiento de Ultralytics YOLO26 activa AMP de forma predeterminada con amp=True: primero compara las predicciones FP32 y AMP de un modelo YOLO26n en GPU CUDA y vuelve a FP32 si no coinciden o si la GPU pertenece a una serie conocida por generar pérdidas NaN con AMP, como la serie GTX 16. Al establecer amp="bf16", se activa autocast BF16 y se desactiva el escalado de la pérdida.
La precisión mixta se utiliza ampliamente siempre que el entrenamiento está limitado por la memoria o el tiempo. Los equipos que desarrollan vehículos autónomos entrenan modelos de detección de objetos con millones de fotogramas de alta resolución; reducir a la mitad la memoria de activaciones permite utilizar imágenes y lotes mayores. En el análisis de imágenes médicas, los volúmenes 3D de TC y RM suelen superar la memoria de la GPU en FP32, y las activaciones de 16 bits permiten entrenar modelos de segmentación con volúmenes completos.
Precisión mixta frente a conceptos relacionados#
- Cuantización de modelos: La cuantización convierte un modelo entrenado a enteros de baja precisión, como INT8, para acelerar la inferencia, mientras que la precisión mixta acelera el entrenamiento y mantiene los pesos en coma flotante.
- Entrenamiento con cuantización consciente: QAT simula el redondeo a enteros durante el entrenamiento para que el modelo conserve su precisión tras el despliegue INT8.
- Precisión media: El término precisión media designa el propio formato numérico FP16, mientras que la precisión mixta es la técnica de entrenamiento que lo combina con FP32. Entrenar exclusivamente en FP16, sin pesos maestros FP32 ni escalado de la pérdida, hace que las actualizaciones pequeñas se pierdan por redondeo y los gradientes pequeños sufran subdesbordamiento, por lo que a menudo no converge.










