Cómo ajustar YOLO con precisión en un conjunto de datos personalizado#
El ajuste fino adapta un modelo preentrenado para reconocer nuevas clases, partiendo de pesos aprendidos en lugar de una inicialización aleatoria. En vez de entrenarlo desde cero durante cientos de épocas, el ajuste fino aprovecha las características preentrenadas de COCO y converge con datos personalizados en una fracción del tiempo.
Esta guía explica cómo realizar el ajuste fino de YOLO26 en conjuntos de datos personalizados, desde el uso básico hasta técnicas avanzadas como el congelado de capas y el entrenamiento en dos etapas.
Ajuste fino frente a entrenamiento desde cero#
Un modelo preentrenado ya ha aprendido características visuales generales —detección de bordes, reconocimiento de texturas y comprensión de formas— a partir de millones de imágenes. El aprendizaje por transferencia mediante ajuste fino reutiliza ese conocimiento y solo enseña al modelo el aspecto de las nuevas clases, por lo que converge más rápido y requiere menos datos. El entrenamiento desde cero descarta todo ese conocimiento y obliga al modelo a aprenderlo todo desde patrones a nivel de píxel, lo que exige muchos más recursos. Consulta la guía de configuración YAML de modelos para saber en qué se diferencian los archivos .yaml que solo contienen la arquitectura de los checkpoints.
| Ajuste fino | Entrenamiento desde cero | |
|---|---|---|
| Pesos iniciales | Preentrenado con COCO (80 clases) | Inicialización aleatoria |
| Comando | YOLO("yolo26n.pt") | YOLO("yolo26n.yaml") |
| Convergencia | Más rápida: el backbone ya está entrenado | Más lenta: todas las capas aprenden desde cero |
| Requisitos de datos | Menores: las características preentrenadas compensan la falta de datos | Mayores: el modelo debe aprender todas las características únicamente a partir del conjunto de datos |
| Cuándo usarlo | Clases personalizadas con imágenes naturales | Dominios fundamentalmente diferentes de COCO (médico, satelital, radar) |
Cuando se carga un archivo .pt con YOLO("yolo26n.pt"), los pesos preentrenados se almacenan en el modelo. Al llamar a .train(data="custom.yaml") después, todos los pesos compatibles se transfieren automáticamente a la nueva arquitectura del modelo, se reinicializan las capas que no coinciden (como la cabeza de detección cuando difiere el número de clases) y comienza el entrenamiento. No se requiere cargar pesos manualmente, manipular capas ni escribir código personalizado de aprendizaje por transferencia.
Cómo funciona la transferencia de pesos preentrenados#
Cuando se ajusta un modelo preentrenado en un conjunto de datos con un número de clases diferente (por ejemplo, de las 80 clases de COCO a 5 clases personalizadas), Ultralytics realiza una transferencia de pesos teniendo en cuenta las formas:
- La transferencia del backbone y el neck es completa: estas capas extraen características visuales generales y sus formas son independientes del número de clases.
- La cabeza de detección se reinicializa parcialmente: las capas de salida de clasificación (
cv3,one2one_cv3) tienen formas vinculadas al número de clases (80 frente a 5). Las filas compatibles cuyos nombres de clase coinciden se reasignan antes de inicializar las filas no coincidentes. Las capas de regresión de cajas (cv2,one2one_cv2) de la cabeza tienen formas fijas independientemente del número de clases, por lo que se transfieren con normalidad. - La gran mayoría de los pesos se transfieren al cambiar el número de clases. Por ejemplo, al ajustar YOLO26n de COCO (80 clases) a un conjunto de datos de 5 clases se transfieren 606 de 708 tensores de pesos, además de las filas de clasificación compatibles que coincidan por nombre.
En conjuntos de datos con el mismo número de clases que el modelo preentrenado (por ejemplo, al ajustar pesos preentrenados con COCO en otro conjunto de datos de 80 clases), se transfiere el 100 % de los pesos, incluida la cabeza de detección.
Transferir clases con alias de nombre#
Ultralytics transfiere las filas coincidentes de la cabeza de clasificación por nombre de clase entre conjuntos de datos, ignorando las mayúsculas y minúsculas y los espacios en blanco circundantes. Cuando clases equivalentes utilizan nombres diferentes, cambia en memoria los nombres de las clases del checkpoint de origen antes de cargarlo. Así se conservan los pesos de clasificación preentrenados para conceptos compartidos que, de otro modo, se tratarían como no coincidentes y se inicializarían aleatoriamente.
Este ejemplo de Objects365 v2 a COCO cambia los nombres de las clases de origen en el checkpoint cargado, que train() pasa después como pesos preentrenados:
from ultralytics import YOLO
# Source Objects365 v2 name (lowercased) -> target COCO name
ALIASES = {
"wild bird": "bird",
"handbag/satchel": "handbag",
"luggage": "suitcase",
"bowl/basin": "bowl",
"orange/tangerine": "orange",
"monitor/tv": "tv",
"stuffed toy": "teddy bear",
"hair dryer": "hair drier",
}
model = YOLO("path/to/yolo26s-objects365.pt")
# Objects365 class names are Title-Cased, so match on the lowercased name
model.model.names = {i: ALIASES.get(name.lower(), name) for i, name in model.model.names.items()}
model.train(data="coco.yaml", epochs=100, imgsz=640)El ajuste cls_remap habilita esta transferencia basada en nombres de forma predeterminada. Durante el entrenamiento se muestra Remapped N/M cls head rows from pretrained weights by class name cuando se copian filas compatibles; establece cls_remap=False para desactivarla.
Ejemplo básico de ajuste fino#
from ultralytics import YOLO
model = YOLO("yolo26n.pt") # load pretrained model
model.train(data="custom.yaml", epochs=50, imgsz=640)Elegir el tamaño del modelo#
Los modelos más grandes tienen mayor capacidad, pero también más parámetros que actualizar, lo que puede aumentar el riesgo de sobreajuste cuando los datos de entrenamiento son limitados. Empezar con un modelo más pequeño (YOLO26n o YOLO26s) y aumentar el tamaño solo si las métricas de validación se estancan es un enfoque práctico. El tamaño óptimo del modelo depende de la complejidad de la tarea, el número de clases, la diversidad del conjunto de datos y el hardware disponible para el despliegue. Consulta la página completa del modelo YOLO26 para ver los tamaños disponibles y las métricas de rendimiento.
Selección del optimizador y la tasa de aprendizaje#
El ajuste predeterminado optimizer=auto selecciona el optimizador y la tasa de aprendizaje en función del número total de iteraciones de entrenamiento:
- 10 000 iteraciones o menos (conjuntos de datos pequeños o pocas épocas): AdamW con una tasa de aprendizaje baja calculada automáticamente
- Más de 10 000 iteraciones (conjuntos de datos grandes): MuSGD (un optimizador híbrido Muon+SGD) con lr=0.01
Para la mayoría de las tareas de ajuste fino, el ajuste predeterminado funciona bien sin necesidad de ajustes manuales. Considera especificar el optimizador explícitamente cuando:
- El entrenamiento sea inestable (la pérdida aumenta bruscamente o diverge): prueba
optimizer=AdamW, lr0=0.001para lograr una convergencia más estable - Ajustes un modelo grande en un conjunto de datos pequeño: un optimizador explícito con una tasa de aprendizaje menor, como
optimizer=AdamW, lr0=0.001, puede ayudar a conservar las características preentrenadas
Cuando optimizer=auto, los valores lr0 y momentum se ignoran. Para controlar manualmente la tasa de aprendizaje, especifica el optimizador explícitamente: optimizer=SGD, lr0=0.005.
Congelar capas#
El congelado impide que determinadas capas se actualicen durante el entrenamiento. Esto acelera el entrenamiento y reduce el sobreajuste cuando el conjunto de datos es pequeño en relación con la capacidad del modelo.
El parámetro freeze acepta un entero o una lista. Un entero freeze=10 congela las 10 primeras capas (índices 0-9), que abarcan la mayor parte del backbone de YOLO26. El backbone comprende las capas 0-10, por lo que freeze=10 deja entrenable el bloque C2PSA final (capa 10); usa freeze=11 para congelar todo el backbone. Una lista puede contener índices de capas como freeze=[0, 3, 5] para congelar parcialmente el backbone, o cadenas con nombres de módulos como freeze=["23.cv2", "23.one2one_cv2"] para controlar con precisión ramas específicas dentro de una capa (en este caso, ambas ramas de regresión de cajas de la cabeza de detección).
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=50, freeze=10)La profundidad de congelado adecuada depende de la similitud entre el dominio objetivo y los datos preentrenados, así como de la cantidad de datos de entrenamiento disponible:
| Escenario | Recomendación | Justificación |
|---|---|---|
| Conjunto de datos grande, dominio similar | freeze=None (predeterminado) | Hay suficientes datos para adaptar todas las capas sin sobreajustar |
| Conjunto de datos pequeño, dominio similar | freeze=10 | Conserva las características del backbone y reduce los parámetros entrenables |
| Conjunto de datos muy pequeño | freeze=23 | Solo se entrena la cabeza de detección, lo que minimiza el riesgo de sobreajuste |
| Dominio alejado de COCO | freeze=None | Es posible que las características del backbone no se transfieran bien y necesiten volver a entrenarse |
La profundidad de congelado también puede tratarse como un hiperparámetro: probar varios valores (0, 5, 10) y comparar el mAP de validación es una forma práctica de encontrar el mejor ajuste para un conjunto de datos concreto.
Hiperparámetros clave para el ajuste fino#
Por lo general, el ajuste fino requiere menos modificaciones de hiperparámetros que el entrenamiento desde cero. Los parámetros más importantes son:
epochs: el ajuste fino converge más rápido que el entrenamiento desde cero. Empieza con un valor moderado y usapatiencepara detener el entrenamiento pronto cuando las métricas de validación se estanquen.patience: el valor predeterminado de 100 está diseñado para entrenamientos largos. Reducirlo a 10-20 evita perder tiempo en ejecuciones que ya han convergido.warmup_epochs: el calentamiento lleva gradualmente la tasa de aprendizaje hasta su valor programado durante las primeras épocas, por lo que es menos probable que los primeros lotes alteren las características preentrenadas. Mantenlo distinto de cero al realizar un ajuste fino, pero no es necesario usar el valor predeterminado completo de 3 épocas: la búsqueda evolutiva tras el ajuste fino oficial de YOLO26 con COCO —una continuación de varias épocas a partir de pesos de Objects365— estableció aproximadamente una época para cada tamaño de modelo.
Para consultar la lista completa de parámetros de entrenamiento, mira la referencia de configuración del entrenamiento. Para comportamientos que no exponen los parámetros —tasas de aprendizaje por capa, recorte de gradiente o métricas de validación personalizadas—, crea una subclase del entrenador.
Ajuste fino en dos etapas#
El ajuste fino en dos etapas divide el entrenamiento en dos fases. En la primera, se congela el backbone y solo se entrenan el neck y la cabeza, lo que permite que las capas de detección se adapten a las nuevas clases sin alterar las características preentrenadas. En la segunda, se descongelan todas las capas y se entrena el modelo completo con una tasa de aprendizaje menor para adaptar el backbone al dominio objetivo.
Este enfoque resulta especialmente útil cuando el dominio objetivo difiere significativamente de COCO (imágenes médicas, imágenes aéreas o microscopía), ya que el backbone puede necesitar adaptación, pero entrenarlo todo a la vez provoca inestabilidad. Para descongelar automáticamente mediante un enfoque basado en callbacks, consulta Congelar y descongelar el backbone.
from ultralytics import YOLO
# Stage 1: freeze backbone, train head and neck
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=20, freeze=10, name="stage1", exist_ok=True)
# Stage 2: unfreeze all, fine-tune with lower lr
model = YOLO("runs/detect/stage1/weights/best.pt")
model.train(data="custom.yaml", epochs=30, optimizer="AdamW", lr0=0.001, name="stage2", exist_ok=True)Problemas habituales#
El modelo no produce predicciones#
-
Datos de entrenamiento insuficientes: entrenar con muy pocas muestras es la causa más habitual; el modelo no puede aprender ni generalizar con tan pocos datos. Asegúrate de disponer de suficientes ejemplos variados por clase antes de investigar otras causas.
-
Comprueba las rutas del conjunto de datos: las rutas de imagen no válidas generan un error del conjunto de datos. Los archivos de etiquetas individuales que faltan o están vacíos se tratan como imágenes de fondo y se notifican durante el escaneado; una división de entrenamiento sin etiquetas genera un error. Valida el conjunto de datos antes de entrenar:
yolo detect val model=yolo26n.pt data=custom.yaml -
Reduce el umbral de confianza: si existen predicciones pero se filtran, prueba
conf=0.1durante la inferencia. -
Verifica el número de clases: asegúrate de que
ncendata.yamlcoincide con el número real de clases de los archivos de etiquetas.
El mAP de validación se estanca pronto#
- Añade más datos: el ajuste fino se beneficia considerablemente de datos de entrenamiento adicionales, especialmente de ejemplos variados con distintos ángulos, condiciones de iluminación y fondos.
- Comprueba el equilibrio entre clases: las clases infrarrepresentadas tendrán un AP bajo. Añade más ejemplos o ajusta
cls_pwen el conjunto de validación. - Reduce el aumento de datos: en conjuntos de datos muy pequeños, un aumento de datos intenso puede perjudicar más de lo que ayuda. Prueba
mosaic=0.5omosaic=0.0. - Aumenta la resolución: en conjuntos de datos con objetos pequeños, prueba
imgsz=1280para conservar los detalles.
El rendimiento empeora en las clases originales después del ajuste fino#
Esto se conoce como olvido catastrófico: el modelo pierde conocimientos aprendidos anteriormente cuando se ajusta exclusivamente con datos nuevos. El olvido es prácticamente inevitable si no incluyes imágenes del conjunto de datos original junto con los datos nuevos. Para mitigarlo:
- Combina los conjuntos de datos: incluye ejemplos de las clases originales junto con las nuevas durante el ajuste fino. Esta es la única forma fiable de evitar el olvido.
- Congela el backbone y el neck: congelar ambos para que solo se entrene la cabeza de detección ayuda en ajustes finos breves con una tasa de aprendizaje muy baja.
- Entrena durante menos épocas: cuanto más tiempo entrene el modelo exclusivamente con datos nuevos, mayor será el olvido.
Preguntas frecuentes#
No existe un mínimo fijo: los resultados dependen de la complejidad de la tarea, el número de clases y la similitud del dominio con COCO. Las imágenes más variadas (con distintas condiciones de iluminación, ángulos y fondos) son más importantes que la cantidad absoluta. Empieza con lo que tengas y amplía el conjunto si las métricas de validación son insuficientes.
Carga un archivo
.ptpreentrenado y llama a.train()con la ruta a undata.yamlpersonalizado. Ultralytics gestiona automáticamente la transferencia de pesos, la reinicialización de la cabeza de detección y la selección del optimizador. Consulta la sección Ajuste fino básico para ver el ejemplo de código completo.Las causas más habituales son rutas de imagen no válidas, archivos de etiquetas ausentes o vacíos, una discrepancia entre
ncen el YAML y los archivos de etiquetas reales, o un umbral de confianza demasiado alto. Consulta Problemas habituales para ver una lista completa de comprobaciones.Depende del tamaño del conjunto de datos y de la similitud del dominio. En conjuntos de datos pequeños con un dominio similar a COCO, congelar el backbone (
freeze=10) evita el sobreajuste. En dominios muy diferentes de COCO, dejar todas las capas descongeladas (freeze=None) permite que el backbone se adapte. Consulta Congelar capas para obtener recomendaciones detalladas.Incluye ejemplos de las clases originales en los datos de entrenamiento junto con las clases nuevas. Si no es posible, congelar más capas (
freeze=10o superior) y usar una tasa de aprendizaje menor ayuda a conservar el conocimiento preentrenado. Consulta El rendimiento empeora en las clases originales para obtener más información.