Ultralytics YOLO27:

Guía de configuración del YAML del modelo#

El archivo de configuración YAML del modelo sirve como plano arquitectónico para las redes neuronales de Ultralytics. Define cómo se conectan las capas, qué parámetros utiliza cada módulo y cómo escala toda la red en los distintos tamaños de modelo.

Model YAML configuration workflow.

Estructura de la configuración#

Los archivos YAML del modelo se organizan en tres secciones principales que funcionan conjuntamente para definir la arquitectura.

Sección de parámetros#

La sección de parámetros especifica las características globales y el comportamiento de escalado del modelo:

# Parameters
nc: 80 # number of classes
scales: # compound scaling constants [depth, width, max_channels]
    n: [0.50, 0.25, 1024] # nano: shallow layers, narrow channels
    s: [0.50, 0.50, 1024] # small: shallow depth, standard width
    m: [0.50, 1.00, 512] # medium: moderate depth, full width
    l: [1.00, 1.00, 512] # large: full depth and width
    x: [1.00, 1.50, 512] # extra-large: maximum performance
kpt_shape: [17, 3] # pose models only
  • nc establece el número de clases que predice el modelo.
  • scales define factores de escalado compuesto que ajustan la profundidad, la anchura y el número máximo de canales del modelo para producir variantes de distintos tamaños (de nano a extragrande).
  • kpt_shape se aplica a los modelos de pose. Puede ser [N, 2] para (x, y) puntos clave o [N, 3] para (x, y, visibility).
Reduce la redundancia con `scales`

El parámetro scales permite generar varios tamaños de modelo a partir de un único YAML base. Por ejemplo, al cargar yolo26n.yaml, Ultralytics lee el yolo26.yaml base y aplica los factores de escalado n (depth=0.50, width=0.25) para crear la variante nano.

`nc` y `kpt_shape` dependen del conjunto de datos

Si tu conjunto de datos especifica un nc o kpt_shape diferente, Ultralytics sobrescribirá automáticamente la configuración del modelo durante la ejecución para que coincida con el YAML del conjunto de datos.

Arquitectura del backbone y de la head#

La arquitectura del modelo consta de las secciones del backbone (extracción de características) y de la head (específica de la tarea):

nc: 80

backbone:
    # [from, repeats, module, args]
    - [-1, 1, Conv, [64, 3, 2]] # 0: Initial convolution
    - [-1, 1, Conv, [128, 3, 2]] # 1: Downsample
    - [-1, 3, C2f, [128, True]] # 2: Feature processing

head:
    - [-1, 1, nn.Upsample, [None, 2, nearest]] # 3: Upsample
    - [[-1, 0], 1, Concat, [1]] # 4: Spatially compatible skip connection
    - [-1, 3, C2f, [256]] # 5: Process features
    - [[5], 1, Detect, [nc]] # 6: Detection layer

Los índices de las capas continúan a lo largo del backbone y de la head, y los mapas de características concatenados deben tener dimensiones espaciales coincidentes.

Formato de especificación de las capas#

Cada capa sigue el patrón uniforme: [from, repeats, module, args]

ComponenteFinalidadEjemplos
fromConexiones de entrada-1 (anterior), 6 (capa 6), [4, 6, 8] (entrada múltiple)
repeatsNúmero de repeticiones1 (única), 3 (repetir 3 veces)
moduleTipo de móduloConv, C2f, TorchVision, Detect
argsArgumentos del módulo[64, 3, 2] (canales, kernel, stride)

Patrones de conexión#

El campo from crea patrones flexibles de flujo de datos en toda tu red:

- [-1, 1, Conv, [64, 3, 2]]    # Takes input from previous layer
Indexación de capas

Las capas se indexan empezando por 0. Los índices negativos hacen referencia a las capas anteriores (-1 = capa anterior), mientras que los índices positivos hacen referencia a capas concretas según su posición.

Repetición de módulos#

El parámetro repeats crea secciones de red más profundas:

- [-1, 3, C2f, [128, True]] # Creates 3 consecutive C2f blocks
- [-1, 1, Conv, [64, 3, 2]] # Single convolution layer

El número real de repeticiones se multiplica por el factor de escalado de profundidad de la configuración del tamaño de tu modelo.

Módulos disponibles#

Los módulos se organizan por funcionalidad y se definen en el directorio de módulos de Ultralytics. Las tablas siguientes muestran los módulos más utilizados por categoría, aunque hay muchos más disponibles en el código fuente:

Operaciones básicas#

MóduloFinalidadOrigenArgumentos
ConvConvolución + BatchNorm + activaciónconv.py[out_ch, kernel, stride, pad, groups]
nn.UpsampleAumento de resolución espacialPyTorch[size, scale_factor, mode]
nn.IdentityOperación de paso directoPyTorch[]

Bloques compuestos#

MóduloFinalidadOrigenArgumentos
C2fCuello de botella CSP con 2 convolucionesblock.py[out_ch, shortcut, groups, expansion]
SPPFSpatial Pyramid Pooling (rápido)block.py[out_ch, kernel_size]
ConcatConcatenación por canalesconv.py[dimension]

Módulos especializados#

MóduloFinalidadOrigenArgumentos
TorchVisionCargar cualquier modelo de torchvisionblock.py[out_ch, model_name, weights, unwrap, truncate, split]
IndexExtraer un tensor específico de una listaconv.py[out_ch, index]
DetectHead de detección de YOLOhead.py[nc]
Lista completa de módulos

Esto representa un subconjunto de los módulos disponibles. Para consultar la lista completa de módulos y sus parámetros, explora el directorio de módulos.

Funciones avanzadas#

Integración con TorchVision#

El módulo TorchVision permite integrar sin problemas cualquier modelo de TorchVision como backbone:

from ultralytics import YOLO

# Model with ConvNeXt backbone
model = YOLO("convnext_backbone.yaml")
results = model.train(data="imagenet10", epochs=100)
Características multiescala

Establece el último parámetro en True para obtener mapas de características intermedios para la detección multiescala.

Módulo Index para la selección de características#

Al utilizar modelos que generan varios mapas de características, el módulo Index selecciona salidas específicas:

nc: 80

backbone:
    - [-1, 1, TorchVision, [768, convnext_tiny, DEFAULT, True, 2, True]] # Multi-output
head:
    - [0, 1, Index, [192, 4]] # Select 4th feature map (192 channels)
    - [0, 1, Index, [384, 6]] # Select 6th feature map (384 channels)
    - [0, 1, Index, [768, 8]] # Select 8th feature map (768 channels)
    - [[1, 2, 3], 1, Detect, [nc]] # Multi-scale detection

Sistema de resolución de módulos#

Comprender cómo Ultralytics localiza e importa los módulos es fundamental para la personalización:

Proceso de búsqueda de módulos#

Ultralytics utiliza un sistema de tres niveles en parse_model:

# Core resolution logic
m = (
    getattr(torch.nn, m[3:])
    if m.startswith("nn.")
    else getattr(__import__("torchvision").ops, m[16:])
    if m.startswith("torchvision.ops.")
    else globals()[m]
)  # get module
  1. Módulos de PyTorch: los nombres que empiezan por 'nn.' → espacio de nombres torch.nn
  2. Operaciones de TorchVision: los nombres que empiezan por 'torchvision.ops.' → espacio de nombres torchvision.ops
  3. Módulos de Ultralytics: todos los demás nombres → espacio de nombres global mediante importaciones

Cadena de importación de módulos#

Los módulos estándar están disponibles mediante las importaciones de tasks.py:

from ultralytics.nn.modules import (  # noqa: F401
    SPPF,
    C2f,
    Conv,
    Detect,
    # ... many more modules
    Index,
    TorchVision,
)

Integración de módulos personalizados#

Modificación del código fuente#

Modificar el código fuente es la forma más versátil de integrar tus módulos personalizados, pero puede resultar complicado. Para definir y utilizar un módulo personalizado, sigue estos pasos:

  1. Instala Ultralytics en modo de desarrollo utilizando el método de clonación de Git de la guía de inicio rápido.

  2. Define tu módulo en ultralytics/nn/modules/block.py:

    class CustomBlock(nn.Module):
        """Custom block with Conv-BatchNorm-ReLU sequence."""
    
        def __init__(self, c1, c2):
            """Initialize CustomBlock with input and output channels."""
            super().__init__()
            self.layers = nn.Sequential(nn.Conv2d(c1, c2, 3, 1, 1), nn.BatchNorm2d(c2), nn.ReLU())
    
        def forward(self, x):
            """Forward pass through the block."""
            return self.layers(x)
  3. Expón tu módulo en el nivel del paquete en ultralytics/nn/modules/__init__.py:

    from .block import CustomBlock  # noqa makes CustomBlock available as ultralytics.nn.modules.CustomBlock
  4. Añádelo a las importaciones en ultralytics/nn/tasks.py:

    from ultralytics.nn.modules import CustomBlock  # noqa
  5. Añade el módulo a base_modules dentro de parse_model(). Los módulos de este conjunto reciben automáticamente los canales de entrada y salida:

    base_modules = frozenset(
        {
            # Existing modules...
            CustomBlock,
        }
    )
  6. Utiliza el módulo en el YAML de tu modelo:

    # custom_model.yaml
    nc: 1
    backbone:
        - [-1, 1, CustomBlock, [64]]
    head:
        - [-1, 1, Classify, [nc]]
  7. Comprueba los FLOPs para asegurarte de que el paso hacia delante funciona:

    from ultralytics import YOLO
    
    model = YOLO("custom_model.yaml", task="classify")
    model.info()  # should print non-zero FLOPs if working

Configuraciones de ejemplo#

Modelo de detección básico#

# Simple YOLO detection model
nc: 80
scales:
    n: [0.33, 0.25, 1024]

backbone:
    - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
    - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
    - [-1, 3, C2f, [128, True]] # 2
    - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
    - [-1, 6, C2f, [256, True]] # 4
    - [-1, 1, SPPF, [256, 5]] # 5

head:
    - [-1, 1, Conv, [256, 3, 1]] # 6
    - [[6], 1, Detect, [nc]] # 7

Modelo con backbone de TorchVision#

# ConvNeXt backbone with YOLO head
nc: 80

backbone:
    - [-1, 1, TorchVision, [768, convnext_tiny, DEFAULT, True, 2, True]]

head:
    - [0, 1, Index, [192, 4]] # P3 features
    - [0, 1, Index, [384, 6]] # P4 features
    - [0, 1, Index, [768, 8]] # P5 features
    - [[1, 2, 3], 1, Detect, [nc]] # Multi-scale detection

Modelo de clasificación#

# Simple classification model
nc: 1000

backbone:
    - [-1, 1, Conv, [64, 7, 2, 3]]
    - [-1, 1, nn.MaxPool2d, [3, 2, 1]]
    - [-1, 4, C2f, [64, True]]
    - [-1, 1, Conv, [128, 3, 2]]
    - [-1, 8, C2f, [128, True]]

head:
    - [-1, 1, Classify, [nc]]

Classify ya realiza internamente un average pooling adaptativo.

Buenas prácticas#

Consejos para diseñar arquitecturas#

Empieza por lo sencillo: Comienza con arquitecturas probadas antes de personalizarlas. Usa configuraciones de YOLO existentes como plantillas y modifícalas progresivamente en lugar de construirlas desde cero.

Prueba progresivamente: Valida cada modificación paso a paso. Añade un módulo personalizado cada vez y comprueba que funciona antes de pasar al siguiente cambio.

Supervisa los canales: Asegúrate de que las dimensiones de los canales coincidan entre las capas conectadas. Los canales de salida (c2) de una capa deben coincidir con los canales de entrada (c1) de la siguiente capa de la secuencia.

Usa conexiones de salto: Aprovecha la reutilización de características con patrones [[-1, N], 1, Concat, [1]]. Estas conexiones ayudan al flujo de gradientes y permiten que el modelo combine características de diferentes escalas.

Escala adecuadamente: Elige las escalas del modelo en función de tus limitaciones computacionales. Usa nano (n) para dispositivos periféricos, small (s) para obtener un rendimiento equilibrado y escalas mayores (m, l, x) para lograr la máxima precisión.

Consideraciones de rendimiento#

Profundidad frente a anchura: Las redes profundas capturan características jerárquicas complejas mediante múltiples capas de transformación, mientras que las redes anchas procesan más información en paralelo en cada capa. Equilibra estos aspectos en función de la complejidad de tu tarea.

Conexiones de salto: Mejoran el flujo de gradientes durante el entrenamiento y permiten reutilizar características en toda la red. Son especialmente importantes en arquitecturas más profundas para evitar la desaparición de gradientes.

Bloques cuello de botella: Reducen el coste computacional manteniendo la capacidad expresiva del modelo. Módulos como C2f usan menos parámetros que las convoluciones estándar y conservan la capacidad de aprendizaje de características.

Características multiescala: Son esenciales para detectar objetos de distintos tamaños en una misma imagen. Usa patrones de Red de pirámide de características (FPN) con varias cabezas de detección en diferentes escalas.

Solución de problemas#

Problemas habituales#

ProblemaCausaSolución
KeyError: 'ModuleName'Módulo no importadoAñádelo a las importaciones de tasks.py
La dimensión de los canales no coincideEspecificación incorrecta de argsVerifica la compatibilidad de los canales de entrada y salida
AttributeError: 'int' object has no attributeTipo de argumento incorrectoConsulta la documentación del módulo para comprobar los tipos de argumento correctos
El modelo no se puede construirReferencia no válida de fromAsegúrate de que las capas referenciadas existan

Consejos para depurar#

Al desarrollar arquitecturas personalizadas, una depuración sistemática ayuda a identificar los problemas desde el principio:

Usa una cabeza de identidad para las pruebas

Sustituye las cabezas complejas por nn.Identity para aislar los problemas del backbone:

nc: 1
backbone:
    - [-1, 1, CustomBlock, [64]]
head:
    - [-1, 1, nn.Identity, []] # Pass-through for debugging

Esto permite inspeccionar directamente las salidas del backbone:

import torch

from ultralytics import YOLO

model = YOLO("debug_model.yaml", task="detect")
output = model.model(torch.randn(1, 3, 640, 640))
print(f"Output shape: {output.shape}")  # Should match expected dimensions

Inspección de la arquitectura del modelo

Comprobar el número de FLOPs y mostrar cada capa también puede ayudar a depurar problemas con la configuración de tu modelo personalizado. El número de FLOPs debe ser distinto de cero en un modelo válido. Si es cero, es probable que haya un problema con el paso hacia delante. Ejecutar un paso hacia delante sencillo debería mostrar el error exacto que se está produciendo.

from ultralytics import YOLO

# Build model with verbose output to see layer details
model = YOLO("debug_model.yaml", task="detect", verbose=True)

# Check model FLOPs. Failed forward pass causes 0 FLOPs.
model.info()

# Inspect individual layers
for i, layer in enumerate(model.model.model):
    print(f"Layer {i}: {layer}")

Validación paso a paso

  1. Empieza con lo mínimo: Prueba primero con la arquitectura más sencilla posible
  2. Añade progresivamente: Construye la complejidad capa a capa
  3. Comprueba las dimensiones: Verifica la compatibilidad de los canales y del tamaño espacial
  4. Valida el escalado: Prueba con diferentes escalas del modelo (n, s, m)

Preguntas frecuentes#

  • Establece el parámetro nc en la parte superior de tu archivo YAML para que coincida con el número de clases de tu conjunto de datos.

    nc: 5 # 5 classes
  • Sí. Puedes usar cualquier módulo compatible, incluidos los backbones de TorchVision, o definir tu propio módulo personalizado e importarlo tal como se describe en Integración de módulos personalizados.

  • Usa la sección scales de tu YAML para definir los factores de escalado de la profundidad, la anchura y el número máximo de canales. El modelo los aplicará automáticamente al cargar el archivo YAML base con la escala añadida al nombre del archivo (por ejemplo, yolo26n.yaml).

  • Este formato especifica cómo se construye cada capa:

    • from: fuente(s) de entrada
    • repeats: número de veces que se repite el módulo
    • module: tipo de capa
    • args: argumentos del módulo
  • Comprueba que los canales de salida de una capa coincidan con los canales de entrada esperados de la siguiente. Usa print(model.model.model) para inspeccionar la arquitectura de tu modelo.

  • Consulta el código fuente en el directorio ultralytics/nn/modules para ver todos los módulos disponibles y sus argumentos.

  • Define el módulo en el código fuente, impórtalo como se muestra en Modificación del código fuente y haz referencia a él por su nombre en tu archivo YAML.

  • Sí, puedes usar model.load("path/to/weights") para cargar pesos desde un checkpoint preentrenado. Sin embargo, solo se cargarán correctamente los pesos de las capas coincidentes.

  • Usa model.info() para comprobar que el número de FLOPs sea distinto de cero. Un modelo válido debería mostrar un número de FLOPs distinto de cero. Si es cero, sigue las sugerencias de Consejos para depurar para encontrar el problema.

Comentarios