[YOLOv6 implementa y entrena su propio conjunto de datos en detalle (muchos registros de pasos de BUG)]

Prefacio:

Recientemente, vi el artículo YOLOv6 publicado por Meituan, cuya velocidad puede alcanzar los 1234FPS, así que quise intentar implementar la prueba y entrenar mi propio conjunto de datos. Inesperadamente, el código fuente del clon oficial está lleno de errores. Durante la implementación proceso, vi que otros académicos también encontraron problemas Preocupados por el mismo BUG, ​​algunos funcionarios de BUG no dieron una solución clara. Después de combinar la experiencia de otros académicos y mi propia comprensión, he completado con éxito una serie completa de implementación del modelo, que incluye: capacitación, evaluación y razonamiento (el seguimiento de TensorRT se acelera y continúa actualizándose), y resumiré el registros de trampas, con la esperanza de ayudar a los novatos a evitar las trampas.

Descarga del modelo y despliegue del entorno.

Código del modelo Yolov6: https://github.com/meituan/YOLOv6/tree/0.2.0
Papel Yolov6: https://arxiv.org/abs/2209.02976

Configuración del entorno

El código de la serie YOLO proporcionará el archivo "requirements.txt" del paquete de funciones requerido y la información de la versión, ingrese el entorno donde va a ejecutar el modelo, cd al directorio del proyecto yolo y ejecute el comando de instalación para automáticamente instale los paquetes de funciones "requirements.txt" enumerados en el archivo:

cd YOLOv6
pip install -r requirements.txt

Nota: si necesita usar GPU para la inferencia, debe instalar el controlador de la tarjeta gráfica, CUDA, cudnn y la versión de GPU de la antorcha correspondiente a la computadora antes. (Para conocer el funcionamiento de esta parte, consulte mi otro blog: Tutorial de instalación detallado de PyTorch de la versión de GPU )

prueba de razonamiento

Una vez completada la configuración del entorno, puede utilizar los pesos oficiales para comprobar si la implementación del entorno básico es correcta:
(Descargue los pesos oficiales y haga clic en el nombre del peso deseado en la tabla de comparación de rendimiento en el LÉAME para pasar a la descarga: )
inserte la descripción de la imagen aquí
Instrucciones de prueba:

python tools/infer.py --weights yolov6s.pt --source img.jpg / imgdir 

Nota: Aún no se admite llamar a la cámara para detectar

El hoyo en el proceso de prueba! ! !

Puede observar la estructura del proyecto YOLOv6 y encontrará que es inusual. Al igual que los pasos de prueba anteriores, el autor coloca el código de razonamiento, capacitación y evaluación en herramientas, y hay otra subcarpeta de yolov6 en el proyecto, que contiene muchas funciones. Esta estructura compleja también conduce a algunos errores en el proceso de llamada:

1. La ruta en infer.py es incorrecta

De hecho, este punto se puede resolver leyendo atentamente el informe de error. El autor no consideró la estructura de la carpeta en el código fuente, y la ruta de carga de algunos parámetros es incorrecta, como las rutas en la figura a continuación. está en herramientas, por lo que cuando llame al archivo en el directorio superior, agregue ".../" al frente:
inserte la descripción de la imagen aquí

2. Error: AssertionError: la ruta de la fuente no existe: ./yolov6/utils/Arial.ttf

Este error sigue siendo el mismo problema. El código oficial ha escrito la ruta incorrecta. Específicamente, en el programa yolov6/core/inferer.py, en la línea 244, también se agrega un "." delante de esta ruta. El código correcto se muestra en la siguiente figura: Después de
inserte la descripción de la imagen aquí
la modificación, simplemente ejecute el comando de prueba:
inserte la descripción de la imagen aquí

entrena tu propio conjunto de datos

1. Preparación del conjunto de datos

El conjunto de datos en formato coco se recomienda en el LÉAME oficial. Utilicé el conjunto de datos VOC durante el entrenamiento. No explicaré la anotación del conjunto de datos aquí, que es similar a YOLOv5. Las etiquetas exportadas se pueden exportar en formato XML. Utilice el script de conversión para convertir las etiquetas XML en las etiquetas txt requeridas por yolo y organice automáticamente el formato del conjunto de datos voc. El script de conversión se compartirá con usted a continuación: (La secuencia de comandos se usa al implementar yolov5, y el archivo final generado lleva el nombre de yolov5, que no es un error y no afecta el uso.

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import random
from shutil import copyfile

classes=["A""B"]   #标签标注时的name

TRAIN_RATIO = 80       #数据集划分比:训练80%     

def clear_hidden_files(path):
    dir_list = os.listdir(path)
    for i in dir_list:
        abspath = os.path.join(os.path.abspath(path), i)
        if os.path.isfile(abspath):
            if i.startswith("._"):
                os.remove(abspath)
        else:
            clear_hidden_files(abspath)

def convert(size, box):
    dw = 1./size[0]
    dh = 1./size[1]
    x = (box[0] + box[1])/2.0
    y = (box[2] + box[3])/2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return (x,y,w,h)

def convert_annotation(image_id):
    in_file = open('VOCdevkit/VOC2007/Annotations/%s.xml' %image_id)        #只用修改这里加载的XML标签地址即可,执行脚本后会自动生成标准的VOC格式数据集
    out_file = open('VOCdevkit/VOC2007/YOLOLabels/%s.txt' %image_id, 'w')
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)

    for obj in root.iter('object'):
        difficult = obj.find('difficult').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult) == 1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
        bb = convert((w,h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
    in_file.close()
    out_file.close()

wd = os.getcwd()
wd = os.getcwd()
data_base_dir = os.path.join(wd, "VOCdevkit/")
if not os.path.isdir(data_base_dir):
    os.mkdir(data_base_dir)
work_sapce_dir = os.path.join(data_base_dir, "VOC2007/")
if not os.path.isdir(work_sapce_dir):
    os.mkdir(work_sapce_dir)
annotation_dir = os.path.join(work_sapce_dir, "Annotations/")
if not os.path.isdir(annotation_dir):
        os.mkdir(annotation_dir)
clear_hidden_files(annotation_dir)
image_dir = os.path.join(work_sapce_dir, "JPEGImages/")
if not os.path.isdir(image_dir):
        os.mkdir(image_dir)
clear_hidden_files(image_dir)
yolo_labels_dir = os.path.join(work_sapce_dir, "YOLOLabels/")
if not os.path.isdir(yolo_labels_dir):
        os.mkdir(yolo_labels_dir)
clear_hidden_files(yolo_labels_dir)
yolov5_images_dir = os.path.join(data_base_dir, "images/")
if not os.path.isdir(yolov5_images_dir):
        os.mkdir(yolov5_images_dir)
clear_hidden_files(yolov5_images_dir)
yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
if not os.path.isdir(yolov5_labels_dir):
        os.mkdir(yolov5_labels_dir)
clear_hidden_files(yolov5_labels_dir)
yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
if not os.path.isdir(yolov5_images_train_dir):
        os.mkdir(yolov5_images_train_dir)
clear_hidden_files(yolov5_images_train_dir)
yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
if not os.path.isdir(yolov5_images_test_dir):
        os.mkdir(yolov5_images_test_dir)
clear_hidden_files(yolov5_images_test_dir)
yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
if not os.path.isdir(yolov5_labels_train_dir):
        os.mkdir(yolov5_labels_train_dir)
clear_hidden_files(yolov5_labels_train_dir)
yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
if not os.path.isdir(yolov5_labels_test_dir):
        os.mkdir(yolov5_labels_test_dir)
clear_hidden_files(yolov5_labels_test_dir)

train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'w')
train_file.close()
test_file.close()
train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')
list_imgs = os.listdir(image_dir) # list image files
prob = random.randint(1, 100)
print("Probability: %d" % prob)
for i in range(0,len(list_imgs)):
    path = os.path.join(image_dir,list_imgs[i])
    if os.path.isfile(path):
        image_path = image_dir + list_imgs[i]
        voc_path = list_imgs[i]
        (nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))
        (voc_nameWithoutExtention, voc_extention) = os.path.splitext(os.path.basename(voc_path))
        annotation_name = nameWithoutExtention + '.xml'
        annotation_path = os.path.join(annotation_dir, annotation_name)
        label_name = nameWithoutExtention + '.txt'
        label_path = os.path.join(yolo_labels_dir, label_name)
    prob = random.randint(1, 100)
    print("Probability: %d" % prob)
    if(prob < TRAIN_RATIO): # train dataset
        if os.path.exists(annotation_path):
            train_file.write(image_path + '\n')
            convert_annotation(nameWithoutExtention) # convert label
            copyfile(image_path, yolov5_images_train_dir + voc_path)
            copyfile(label_path, yolov5_labels_train_dir + label_name)
    else: # test dataset
        if os.path.exists(annotation_path):
            test_file.write(image_path + '\n')
            convert_annotation(nameWithoutExtention) # convert label
            copyfile(image_path, yolov5_images_test_dir + voc_path)
            copyfile(label_path, yolov5_labels_test_dir + label_name)
train_file.close()
test_file.close()

No diré mucho sobre la producción de conjuntos de datos, también hay muchos tutoriales para la producción de conjuntos de datos VOC.

2. Modificar voc.yaml

Modifica la ruta del conjunto de datos de entrenamiento en data/voc.yaml:
inserte la descripción de la imagen aquí

3. Modifica los parámetros cargados en tools/train.py y empieza a entrenar

Preste atención a la ruta aquí, así como a la carga de pesos de entrenamiento, sobre '--batch-size' y '--workers' según el rendimiento de su computadora, por ejemplo:

如果报错:RuntimeError: CUDA sin memoria. Intenté asignar 200,00 MiB (GPU 0; 4,00 GiB de capacidad total; 2,88 GiB ya asignados; 0 bytes libres; 2,89 GiB reservados en total por PyTorch)
就减小'–batch-size'。

Si se informa un error: la página es demasiado pequeña para completar la operación.
solo reduce '--trabajadores'

El pozo en el proceso de formación! ! !

1、报错:AttributeError: el objeto 'Entrenador' no tiene el atributo 'época'

inserte la descripción de la imagen aquí
Análisis y solución:
De acuerdo con el mensaje de error, significa que no hay una clase o parámetro "época" en la clase "Entrenador", que se remonta a la clase "Entrenador" del programa yolov6/core/engine.py: en la línea 261 , el programa llama a "self.epoch
" , de la siguiente manera: ¡
inserte la descripción de la imagen aquí
Continúe rastreando la causa del problema hacia arriba y me sorprende descubrir que el atributo "epoch" no está definido en esta clase! ! ! ¡Entonces causó un error de muy bajo nivel que no se pudo llamar! ! ! La solución también es muy simple, solo defina este atributo en la inicialización de la clase. De hecho, la época no es desconocida, es el parámetro definido en "args". Por lo tanto, como se muestra en la figura a continuación, obtenga el parámetro de " args" y páselo al atributo epoch. :
inserte la descripción de la imagen aquí

Entrenamiento exitoso:

Después de lidiar con los pozos anteriores, puedes entrenar:
inserte la descripción de la imagen aquí

Inferencia acelerada TensorRT

La aceleración tensorRT de yolov6 se implementó recientemente, ¡y esta parte del contenido se actualizará después de finalizar el arreglo!

Supongo que te gusta

Origin blog.csdn.net/uuhhy/article/details/127622432
Recomendado
Clasificación