Cómo ajustar YOLO con 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 entrenar desde cero durante cientos de épocas, el ajuste fino aprovecha las características preentrenadas de COCO y converge con datos personalizados en mucho menos tiempo.
Esta guía explica cómo ajustar YOLO26 con conjuntos de datos personalizados, desde el uso básico hasta técnicas avanzadas como la congelación 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 el ajuste fino reutiliza esos conocimientos y solo enseña al modelo el aspecto de las nuevas clases; por eso converge más rápido y requiere menos datos. El entrenamiento desde cero descarta todo eso 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 de YAML del modelo para saber en qué se diferencian los archivos .yaml, que solo definen la arquitectura, de los puntos de control.
| 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 muy distintos de COCO (médico, satelital, radar) |
Cuando se carga un archivo .pt con YOLO("yolo26n.pt"), los pesos preentrenados se almacenan en el modelo. Después, al llamar a .train(data="custom.yaml"), 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 cambia el número de clases) y comienza el entrenamiento. No hace falta 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 con un conjunto de datos que tiene un número distinto de clases (por ejemplo, las 80 clases de COCO frente a 5 clases personalizadas), Ultralytics realiza una transferencia de pesos que tiene en cuenta las dimensiones:
- La transferencia del backbone y el neck es completa: estas capas extraen características visuales generales y sus dimensiones 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 dimensiones que dependen del número de clases (80 frente a 5). Antes de inicializar las filas sin correspondencia, se reasignan las filas compatibles cuyos nombres de clase coinciden. Las capas de regresión de cajas (cv2,one2one_cv2) de la cabeza tienen dimensiones fijas, independientemente del número de clases, por lo que se transfieren con normalidad. - Se transfiere la gran mayoría de los pesos 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 los 708 tensores de pesos, además de las filas de clasificación compatibles que coinciden por nombre.
En los conjuntos de datos que tienen 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 mediante alias de nombre#
Ultralytics transfiere las filas coincidentes de la cabeza de clasificación entre conjuntos de datos según el nombre de la clase, sin distinguir entre mayúsculas y minúsculas ni tener en cuenta los espacios en blanco al principio o al final. Si las clases equivalentes tienen nombres distintos, cambia en memoria los nombres de las clases del punto de control de origen antes de cargarlo. Así se conservan los pesos de clasificación preentrenados para los conceptos compartidos que, de otro modo, se considerarían sin correspondencia y se inicializarían aleatoriamente.
Este ejemplo de Objects365 v2 a COCO cambia el nombre de las clases de origen en el punto de control cargado, que train() utiliza después como pesos preentrenados:
from ultralytics import YOLO
# Nombre de origen de Objects365 v2 (en minúsculas) -> nombre de destino de COCO
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")
# Los nombres de las clases de Objects365 están en formato de título, así que busca coincidencias con el nombre en minúsculas
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)La opción cls_remap habilita de forma predeterminada esta transferencia basada en nombres. 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") # cargar modelo preentrenado
model.train(data="custom.yaml", epochs=50, imgsz=640)Elegir el tamaño del modelo#
Los modelos más grandes tienen más capacidad, pero también más parámetros que actualizar, lo que puede aumentar el riesgo de sobreajuste cuando hay pocos datos de entrenamiento. Empezar con un modelo más pequeño (YOLO26n o YOLO26s) y aumentar su tamaño solo si las métricas de validación se estancan es una opción práctica. 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 la implementación. Consulta la página del modelo YOLO26 para ver los tamaños disponibles y las métricas de rendimiento.
Selección del optimizador y de la tasa de aprendizaje#
La opción predeterminada optimizer=auto selecciona el optimizador y la tasa de aprendizaje según el 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, la opción predeterminada funciona bien sin ajustes manuales. Plantéate especificar el optimizador 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 con un conjunto de datos pequeño: especificar un optimizador con una tasa de aprendizaje más baja, como
optimizer=AdamW, lr0=0.001, puede ayudar a conservar las características preentrenadas
Cuando se usa optimizer=auto, se ignoran los valores lr0 y momentum. Para controlar manualmente la tasa de aprendizaje, especifica el optimizador: optimizer=SGD, lr0=0.005.
Congelar capas#
La congelación 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. El 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 incluir índices de capa 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 concretas de una capa (en este caso, las dos 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 congelación adecuada depende de cuánto se parezca el dominio de destino a los datos preentrenados y de cuántos datos de entrenamiento haya disponibles:
| Situación | Recomendación | Justificación |
|---|---|---|
| Conjunto de datos grande, dominio similar | freeze=None (predeterminado) | Hay datos suficientes 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 muy distinto de COCO | freeze=None | Es posible que las características del backbone no se transfieran bien y haya que volver a entrenarlas |
La profundidad de congelación también puede tratarse como un hiperparámetro: probar algunos valores (0, 5, 10) y comparar el mAP de validación es una forma práctica de encontrar la mejor opción para un conjunto de datos concreto.
Hiperparámetros clave para el ajuste fino#
Por lo general, el ajuste fino requiere menos cambios en los 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 cuando las métricas de validación se estanquen.patience: el valor predeterminado de 100 está pensado para entrenamientos largos. Reducirlo a 10-20 evita perder tiempo en entrenamientos que ya han convergido.warmup_epochs: el calentamiento lleva gradualmente la tasa de aprendizaje hasta el valor programado durante las primeras épocas, lo que reduce la probabilidad de que los primeros lotes alteren las características preentrenadas. Mantenlo por encima de cero al ajustar un modelo, pero no es necesario usar el valor predeterminado completo de 3 épocas: la búsqueda evolutiva del ajuste fino oficial de YOLO26 con COCO —una continuación de varias épocas a partir de pesos de Objects365— determinó que bastaba con aproximadamente una época para cada tamaño de modelo.
Consulta la referencia de configuración del entrenamiento para ver la lista completa de parámetros de entrenamiento. Si necesitas controlar aspectos que los parámetros no permiten configurar —tasas de aprendizaje por capa, recorte del gradiente o métricas de validación personalizadas—, subclasifica el 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 más baja para adaptar el backbone al dominio de destino.
Este método resulta especialmente útil cuando el dominio de destino difiere mucho de COCO (imágenes médicas, imágenes aéreas, microscopía), ya que quizá haya que adaptar el backbone, pero entrenarlo todo a la vez provoca inestabilidad. Para descongelar automáticamente las capas mediante una estrategia basada en callbacks, consulta Congelar y descongelar el backbone.
from ultralytics import YOLO
# Etapa 1: congelar el backbone y entrenar la cabeza y el neck
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=20, freeze=10, name="stage1", exist_ok=True)
# Etapa 2: descongelar todo y ajustar el modelo con una tasa de aprendizaje menor
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 genera predicciones#
-
Datos de entrenamiento insuficientes: entrenar con muy pocas muestras es la causa más habitual; con tan pocos datos, el modelo no puede aprender ni generalizar. Asegúrate de tener 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 análisis; si una partición de entrenamiento no contiene etiquetas, se 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 hay predicciones, pero se filtran, prueba
conf=0.1durante la inferencia. -
Verifica el número de clases: asegúrate de que
ncendata.yamlcoincida 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 mucho de más datos de entrenamiento, especialmente de ejemplos variados con diferentes ángulos, iluminación y fondos.
- Comprueba el equilibrio entre clases: las clases con pocos ejemplos tendrán un AP bajo. Añade más ejemplos o ajusta
cls_pwcon el conjunto de validación. - Reduce el aumento de datos: en conjuntos de datos muy pequeños, un aumento de datos agresivo puede perjudicar más de lo que ayuda. Prueba
mosaic=0.5omosaic=0.0. - Aumenta la resolución: si el conjunto de datos contiene objetos pequeños, prueba
imgsz=1280para conservar los detalles.
El rendimiento en las clases originales empeora después del ajuste fino#
Esto se conoce como olvido catastrófico: el modelo pierde conocimientos que había aprendido anteriormente cuando se ajusta exclusivamente con datos nuevos. El olvido es prácticamente inevitable si no se incluyen 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. 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 puede ayudar en ajustes finos breves con una tasa de aprendizaje muy baja.
- Entrena durante menos épocas: cuanto más tiempo se entrena el modelo exclusivamente con datos nuevos, más aumenta el olvido.
Preguntas frecuentes#
No hay un mínimo fijo: los resultados dependen de la complejidad de la tarea, del número de clases y de cuánto se parezca el dominio a COCO. La variedad de las imágenes (diferentes condiciones de iluminación, ángulos y fondos) importa más que la cantidad total. Empieza con lo que tengas y amplía el conjunto si las métricas de validación no son suficientes.
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 completo de código.Las causas más habituales son rutas de imagen no válidas, archivos de etiquetas que faltan o están 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 para solucionar problemas.Depende del tamaño del conjunto de datos y de la similitud del dominio. En conjuntos de datos pequeños con un dominio similar al de COCO, congelar el backbone (
freeze=10) evita el sobreajuste. En dominios muy distintos de COCO, dejar todas las capas sin congelar (freeze=None) permite que el backbone se adapte. Consulta Congelación de 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 más) y usar una tasa de aprendizaje más baja ayuda a conservar el conocimiento preentrenado. Consulta El rendimiento se degrada en las clases originales para obtener más información.