Ir al contenido

Validaci贸n cruzada K-Fold con Ultralytics

Introducci贸n

Esta completa gu铆a ilustra la implementaci贸n de la validaci贸n cruzada K-Fold para conjuntos de datos de detecci贸n de objetos dentro del ecosistema Ultralytics . Aprovecharemos el formato de detecci贸n YOLO y las bibliotecas clave de Python como sklearn, pandas y PyYaml para guiarle a trav茅s de la configuraci贸n necesaria, el proceso de generaci贸n de vectores de caracter铆sticas y la ejecuci贸n de una divisi贸n de conjuntos de datos K-Fold.

Resumen de la validaci贸n cruzada K-Fold

Tanto si su proyecto incluye el conjunto de datos de Fruit Detection como una fuente de datos personalizada, este tutorial pretende ayudarle a comprender y aplicar la validaci贸n cruzada K-Fold para reforzar la fiabilidad y solidez de su proyecto. aprendizaje autom谩tico modelos. Mientras aplicamos k=5 para este tutorial, tenga en cuenta que el n煤mero 贸ptimo de pliegues puede variar en funci贸n de su conjunto de datos y de las caracter铆sticas espec铆ficas de su proyecto.

Sin m谩s dilaci贸n, 隆entremos en materia!

Configurar

  • Sus anotaciones deben estar en el formato de detecci贸nYOLO .

  • Esta gu铆a asume que los archivos de anotaci贸n est谩n disponibles localmente.

  • Para nuestra demostraci贸n, utilizamos el conjunto de datos Fruit Detection.

    • Este conjunto de datos contiene un total de 8479 im谩genes.
    • Incluye 6 etiquetas de clase, cada una con su recuento total de instancias indicado a continuaci贸n.
Etiqueta de clase Recuento de instancias
Manzana 7049
Uvas 7202
Pi帽a 1613
Naranja 15549
Pl谩tano 3536
Sand铆a 1976
  • Los paquetes necesarios de Python incluyen:

    • ultralytics
    • sklearn
    • pandas
    • pyyaml
  • Este tutorial funciona con k=5 pliegues. Sin embargo, debe determinar el mejor n煤mero de pliegues para su conjunto de datos espec铆fico.

  • Inicie un nuevo entorno virtual Python (venv) para su proyecto y act铆velo. Utilice pip (o su gestor de paquetes preferido) para instalar:

    • La biblioteca Ultralytics : pip install -U ultralytics. Como alternativa, puede clonar la p谩gina oficial repo.
    • Scikit-learn, pandas y PyYAML: pip install -U scikit-learn pandas pyyaml.
  • Compruebe que sus anotaciones est谩n en el formato de detecci贸nYOLO .

    • Para este tutorial, todos los archivos de anotaci贸n se encuentran en la carpeta Fruit-Detection/labels directorio.

Generaci贸n de vectores de caracter铆sticas para el conjunto de datos de detecci贸n de objetos

  1. Empiece por crear un nuevo example.py Python para los pasos siguientes.

  2. Proceda a recuperar todos los archivos de etiquetas de su conjunto de datos.

    from pathlib import Path
    
    dataset_path = Path("./Fruit-detection")  # replace with 'path/to/dataset' for your custom data
    labels = sorted(dataset_path.rglob("*labels/*.txt"))  # all data in 'labels'
    
  3. Ahora, lea el contenido del archivo YAML del conjunto de datos y extraiga los 铆ndices de las etiquetas de clase.

    yaml_file = "path/to/data.yaml"  # your data YAML with data directories and names dictionary
    with open(yaml_file, "r", encoding="utf8") as y:
        classes = yaml.safe_load(y)["names"]
    cls_idx = sorted(classes.keys())
    
  4. Inicializar un pandas DataFrame.

    import pandas as pd
    
    indx = [label.stem for label in labels]  # uses base filename as ID (no extension)
    labels_df = pd.DataFrame([], columns=cls_idx, index=indx)
    
  5. Contar las instancias de cada clase-etiqueta presentes en los archivos de anotaci贸n.

    from collections import Counter
    
    for label in labels:
        lbl_counter = Counter()
    
        with open(label, "r") as lf:
            lines = lf.readlines()
    
        for line in lines:
            # classes for YOLO label uses integer at first position of each line
            lbl_counter[int(line.split(" ")[0])] += 1
    
        labels_df.loc[label.stem] = lbl_counter
    
    labels_df = labels_df.fillna(0.0)  # replace `nan` values with `0.0`
    
  6. A continuaci贸n se muestra una vista de ejemplo del DataFrame rellenado:

                                                           0    1    2    3    4    5
    '0000a16e4b057580_jpg.rf.00ab48988370f64f5ca8ea4...'  0.0  0.0  0.0  0.0  0.0  7.0
    '0000a16e4b057580_jpg.rf.7e6dce029fb67f01eb19aa7...'  0.0  0.0  0.0  0.0  0.0  7.0
    '0000a16e4b057580_jpg.rf.bc4d31cdcbe229dd022957a...'  0.0  0.0  0.0  0.0  0.0  7.0
    '00020ebf74c4881c_jpg.rf.508192a0a97aa6c4a3b6882...'  0.0  0.0  0.0  1.0  0.0  0.0
    '00020ebf74c4881c_jpg.rf.5af192a2254c8ecc4188a25...'  0.0  0.0  0.0  1.0  0.0  0.0
     ...                                                  ...  ...  ...  ...  ...  ...
    'ff4cd45896de38be_jpg.rf.c4b5e967ca10c7ced3b9e97...'  0.0  0.0  0.0  0.0  0.0  2.0
    'ff4cd45896de38be_jpg.rf.ea4c1d37d2884b3e3cbce08...'  0.0  0.0  0.0  0.0  0.0  2.0
    'ff5fd9c3c624b7dc_jpg.rf.bb519feaa36fc4bf630a033...'  1.0  0.0  0.0  0.0  0.0  0.0
    'ff5fd9c3c624b7dc_jpg.rf.f0751c9c3aa4519ea3c9d6a...'  1.0  0.0  0.0  0.0  0.0  0.0
    'fffe28b31f2a70d4_jpg.rf.7ea16bd637ba0711c53b540...'  0.0  6.0  0.0  0.0  0.0  0.0
    

Las filas indexan los archivos de etiquetas, cada uno de los cuales corresponde a una imagen del conjunto de datos, y las columnas corresponden a los 铆ndices de las etiquetas de clase. Cada fila representa un pseudo-vector de caracter铆sticas, con el recuento de cada etiqueta de clase presente en el conjunto de datos. Esta estructura de datos permite la aplicaci贸n de la Validaci贸n Cruzada K-Fold a un conjunto de datos de detecci贸n de objetos.

Dividir el conjunto de datos en K-Fold

  1. Ahora utilizaremos el KFold clase de sklearn.model_selection para generar k divisiones del conjunto de datos.

    • Importante:
      • Configuraci贸n shuffle=True garantiza una distribuci贸n aleatoria de las clases en sus divisiones.
      • Estableciendo random_state=M donde M es un n煤mero entero elegido, puede obtener resultados repetibles.
    from sklearn.model_selection import KFold
    
    ksplit = 5
    kf = KFold(n_splits=ksplit, shuffle=True, random_state=20)  # setting random_state for repeatable results
    
    kfolds = list(kf.split(labels_df))
    
  2. El conjunto de datos se ha dividido en k pliegues, cada uno con una lista de train y val 铆ndices. Construiremos un DataFrame para mostrar estos resultados con mayor claridad.

    folds = [f"split_{n}" for n in range(1, ksplit + 1)]
    folds_df = pd.DataFrame(index=indx, columns=folds)
    
    for idx, (train, val) in enumerate(kfolds, start=1):
        folds_df[f"split_{idx}"].loc[labels_df.iloc[train].index] = "train"
        folds_df[f"split_{idx}"].loc[labels_df.iloc[val].index] = "val"
    
  3. Ahora calcularemos la distribuci贸n de las etiquetas de clase de cada pliegue como proporci贸n de las clases presentes en val a los presentes en train.

    fold_lbl_distrb = pd.DataFrame(index=folds, columns=cls_idx)
    
    for n, (train_indices, val_indices) in enumerate(kfolds, start=1):
        train_totals = labels_df.iloc[train_indices].sum()
        val_totals = labels_df.iloc[val_indices].sum()
    
        # To avoid division by zero, we add a small value (1E-7) to the denominator
        ratio = val_totals / (train_totals + 1e-7)
        fold_lbl_distrb.loc[f"split_{n}"] = ratio
    

    Lo ideal es que todas las proporciones de clase sean razonablemente similares en cada divisi贸n y en todas las clases. Sin embargo, esto depender谩 de las caracter铆sticas espec铆ficas de su conjunto de datos.

  4. A continuaci贸n, creamos los directorios y los archivos YAML del conjunto de datos para cada divisi贸n.

    import datetime
    
    supported_extensions = [".jpg", ".jpeg", ".png"]
    
    # Initialize an empty list to store image file paths
    images = []
    
    # Loop through supported extensions and gather image files
    for ext in supported_extensions:
        images.extend(sorted((dataset_path / "images").rglob(f"*{ext}")))
    
    # Create the necessary directories and dataset YAML files (unchanged)
    save_path = Path(dataset_path / f"{datetime.date.today().isoformat()}_{ksplit}-Fold_Cross-val")
    save_path.mkdir(parents=True, exist_ok=True)
    ds_yamls = []
    
    for split in folds_df.columns:
        # Create directories
        split_dir = save_path / split
        split_dir.mkdir(parents=True, exist_ok=True)
        (split_dir / "train" / "images").mkdir(parents=True, exist_ok=True)
        (split_dir / "train" / "labels").mkdir(parents=True, exist_ok=True)
        (split_dir / "val" / "images").mkdir(parents=True, exist_ok=True)
        (split_dir / "val" / "labels").mkdir(parents=True, exist_ok=True)
    
        # Create dataset YAML files
        dataset_yaml = split_dir / f"{split}_dataset.yaml"
        ds_yamls.append(dataset_yaml)
    
        with open(dataset_yaml, "w") as ds_y:
            yaml.safe_dump(
                {
                    "path": split_dir.as_posix(),
                    "train": "train",
                    "val": "val",
                    "names": classes,
                },
                ds_y,
            )
    
  5. Por 煤ltimo, copie las im谩genes y las etiquetas en el directorio respectivo ('train' o 'val') para cada divisi贸n.

    • NOTA: El tiempo necesario para esta parte del c贸digo variar谩 en funci贸n del tama帽o del conjunto de datos y del hardware del sistema.
    import shutil
    
    for image, label in zip(images, labels):
        for split, k_split in folds_df.loc[image.stem].items():
            # Destination directory
            img_to_path = save_path / split / k_split / "images"
            lbl_to_path = save_path / split / k_split / "labels"
    
            # Copy image and label files to new directory (SamefileError if file already exists)
            shutil.copy(image, img_to_path / image.name)
            shutil.copy(label, lbl_to_path / label.name)
    

Guardar registros (opcional)

Opcionalmente, puede guardar los registros de los DataFrames de divisi贸n K-Fold y distribuci贸n de etiquetas como archivos CSV para futuras consultas.

folds_df.to_csv(save_path / "kfold_datasplit.csv")
fold_lbl_distrb.to_csv(save_path / "kfold_label_distribution.csv")

Entrenar YOLO utilizando K-Fold Data Splits

  1. En primer lugar, cargue el modelo YOLO .

    from ultralytics import YOLO
    
    weights_path = "path/to/weights.pt"
    model = YOLO(weights_path, task="detect")
    
  2. A continuaci贸n, itere sobre los archivos YAML del conjunto de datos para ejecutar el entrenamiento. Los resultados se guardar谩n en un directorio especificado por el par谩metro project y name argumentos. Por defecto, este directorio es 'exp/runs#' donde # es un 铆ndice entero.

    results = {}
    
    # Define your additional arguments here
    batch = 16
    project = "kfold_demo"
    epochs = 100
    
    for k in range(ksplit):
        dataset_yaml = ds_yamls[k]
        model = YOLO(weights_path, task="detect")
        model.train(data=dataset_yaml, epochs=epochs, batch=batch, project=project)  # include any train arguments
        results[k] = model.metrics  # save output metrics for further analysis
    

Conclusi贸n

En esta gu铆a, hemos explorado el proceso de utilizar la validaci贸n cruzada K-Fold para entrenar el modelo de detecci贸n de objetos YOLO . Hemos aprendido a dividir nuestro conjunto de datos en K particiones, garantizando una distribuci贸n de clases equilibrada en los distintos pliegues.

Tambi茅n exploramos el procedimiento de creaci贸n de informes DataFrames para visualizar las divisiones de datos y las distribuciones de etiquetas en estas divisiones, lo que nos proporciona una visi贸n clara de la estructura de nuestros conjuntos de entrenamiento y validaci贸n.

Opcionalmente, guardamos nuestros registros para futuras consultas, lo que podr铆a resultar especialmente 煤til en proyectos a gran escala o a la hora de solucionar problemas de rendimiento del modelo.

Por 煤ltimo, implementamos el entrenamiento real del modelo utilizando cada divisi贸n en un bucle, guardando nuestros resultados de entrenamiento para su posterior an谩lisis y comparaci贸n.

Esta t茅cnica de validaci贸n cruzada K-Fold es una forma s贸lida de aprovechar al m谩ximo los datos disponibles, y ayuda a garantizar que el rendimiento del modelo es fiable y coherente en diferentes subconjuntos de datos. El resultado es un modelo m谩s generalizable y fiable, con menos probabilidades de sobreajustarse a patrones de datos espec铆ficos.

Recuerde que, aunque en esta gu铆a hemos utilizado YOLO , estos pasos son en su mayor铆a transferibles a otros modelos de aprendizaje autom谩tico. Comprender estos pasos te permitir谩 aplicar la validaci贸n cruzada de forma efectiva en tus propios proyectos de aprendizaje autom谩tico. 隆Feliz programaci贸n!

PREGUNTAS FRECUENTES

驴Qu茅 es la validaci贸n cruzada K-Fold y por qu茅 es 煤til en la detecci贸n de objetos?

La validaci贸n cruzada por K pliegues es una t茅cnica en la que el conjunto de datos se divide en "k" subconjuntos (pliegues) para evaluar el rendimiento del modelo de forma m谩s fiable. Cada pliegue sirve tanto de datos de entrenamiento como de datos de validaci贸n. En el contexto de la detecci贸n de objetos, el uso de la Validaci贸n Cruzada K-Fold ayuda a asegurar que el rendimiento de su modelo Ultralytics YOLO es robusto y generalizable a trav茅s de diferentes divisiones de datos, mejorando su fiabilidad. Para obtener instrucciones detalladas sobre la configuraci贸n de la validaci贸n cruzada K-Fold con Ultralytics YOLO , consulte Validaci贸n cruzada K-Fold con Ultralytics.

驴C贸mo implemento la validaci贸n cruzada K-Fold utilizando Ultralytics YOLO ?

Para implementar la Validaci贸n Cruzada K-Fold con Ultralytics YOLO , debe seguir los siguientes pasos:

  1. Verifique que las anotaciones est茅n en el formato de detecci贸nYOLO .
  2. Utilice las bibliotecas Python como sklearn, pandasy pyyaml.
  3. Cree vectores de caracter铆sticas a partir de su conjunto de datos.
  4. Divida el conjunto de datos mediante KFold de sklearn.model_selection.
  5. Entrene el modelo YOLO en cada divisi贸n.

Para obtener una gu铆a completa, consulte la secci贸n Dividir conjuntos de datos K-Fold de nuestra documentaci贸n.

驴Por qu茅 utilizar Ultralytics YOLO para la detecci贸n de objetos?

Ultralytics YOLO ofrece detecci贸n de objetos de 煤ltima generaci贸n en tiempo real con gran precisi贸n y eficacia. Es vers谩til y admite m煤ltiples tareas de visi贸n por ordenador, como la detecci贸n, la segmentaci贸n y la clasificaci贸n. Adem谩s, se integra a la perfecci贸n con herramientas como Ultralytics HUB para el entrenamiento y despliegue de modelos sin c贸digo. Para m谩s detalles, explore las ventajas y caracter铆sticas en nuestra p谩ginaUltralytics YOLO .

驴C贸mo puedo asegurarme de que mis anotaciones est谩n en el formato correcto para Ultralytics YOLO ?

Sus anotaciones deben seguir el formato de detecci贸n YOLO . Cada archivo de anotaci贸n debe enumerar la clase de objeto, junto con las coordenadas de su cuadro delimitador en la imagen. El formato YOLO garantiza un procesamiento de datos racionalizado y estandarizado para el entrenamiento de modelos de detecci贸n de objetos. Para m谩s informaci贸n sobre el formato adecuado de las anotaciones, visite la gu铆a del formato de detecci贸nYOLO .

驴Puedo utilizar la validaci贸n cruzada K-Fold con conjuntos de datos personalizados distintos de la detecci贸n de frutas?

S铆, puede utilizar la validaci贸n cruzada K-Fold con cualquier conjunto de datos personalizado siempre que las anotaciones est茅n en el formato de detecci贸n YOLO . Sustituya las rutas del conjunto de datos y las etiquetas de clase por las espec铆ficas de su conjunto de datos personalizado. Esta flexibilidad garantiza que cualquier proyecto de detecci贸n de objetos pueda beneficiarse de una s贸lida evaluaci贸n del modelo mediante la validaci贸n cruzada K-Fold. Para ver un ejemplo pr谩ctico, consulte nuestra secci贸n Generaci贸n de vectores de caracter铆sticas.

Creado hace 1 a帽o 鉁忥笍 Actualizado hace 1 mes

Comentarios