MMYOLOEl marco es una caja de herramientas de código abierto para una serie de algoritmos basados PyTorchen . Posicionado como una serie de bibliotecas populares de código abierto y bibliotecas centrales de aplicaciones industriales, la dirección del proyecto framework GithubMMDetectionYOLOMMYOLOYOLOMMYOLO
Tareas admitidas: detección de objetos, detección de objetos giratorios
Este artículo es principalmente una pequeña extensión del tutorial anterior (sistema Win10), registra algunos problemas encontrados durante el uso, el proceso de solución y una explicación detallada del archivo de configuración.
problema de instalacion de pycocotools
Primero MMYOLOdescargue el proyecto completo desde la dirección del proyecto y luego ingréselo en la ventana de comandos pip install openmim. Luego use para cd mmyoloingresar el archivo del proyecto. Tenga en cuenta que esta mmyoloes una ruta. Por ejemplo, si su archivo de proyecto está en la unidad D, entonces debe escribirlo cd D:\mmyolo. Después de ingresar a la carpeta del proyecto, ingresemim install -r requirements/mminstall.txt
Durante el proceso de instalación, solo informé un error durante la instalación de una biblioteca, que es pycocotoolsla biblioteca Microsoft Visual C++ 14.0 or greater is required. El autor de la biblioteca Github enfatizó que el mensaje de error no estaba instalado Visual C++ 2015 build tools. En el documento, el autor proporcionó una dirección de descarga , pero una siempre se informaba de un error durante el proceso de descarga. Así que encontré la versión sin conexión, enlace de descarga
Una vez completada la instalación, intente nuevamente mim install -r requirements/mminstall.txtsin error, ¡el problema está resuelto!
problema con la ruta del archivo xml
Debido a que dos personas marcaron por separado durante la calibración, lo que resultó en rutas inconsistentes xmlen el archivo path, pero no todos tienen este problema, aquí hay solo un pequeño registro.
import xml.etree.ElementTree as ET
import os
defmodify_xml_path(xml_file):
tree = ET.parse(xml_file)
root = tree.getroot()for path_elem in root.iter('path'):
path_elem.text = os.path.basename(path_elem.text)
tree.write(xml_file)
folder_path ='./data/xml'forfilein os.listdir(folder_path):
file_path = os.path.join(folder_path,file)
modify_xml_path(file_path)
archivo xml a archivo json
MMYOLODebido a que no leí el documento del tutorial cuando estaba haciendo la calibración de datos antes , usé Labelimgel software para calibrar, VOCformatear y generar xmlarchivos.
LabelmeSin embargo, los archivos generados se utilizan en el tutorial jsony la subsiguiente separación de datos, inspección de etiquetado, exploración de conjuntos de datos, etc. se basan en jsonarchivos, por lo que xmllos archivos deben convertirse en jsonarchivos.
Primero organice los archivos de la siguiente manera:
-mmyolo
- data
- images
-0001.bmp
-0002.bmp
-...- xml
-0001.xml
-0002.xml
-...- configs
...
Cree una nueva carpeta en la carpeta del proyecto, coloque la imagen en mmyoloy coloque el archivo de calibración en .data.\data\images.\data\xml
Luego .\tools\dataset_converterscrea un nuevo archivo en la carpeta xml2json.pyy completa el código:
import xml.etree.ElementTree as ET
import os
import json
coco =dict()
coco['images']=[]
coco['type']='instances'
coco['annotations']=[]
coco['categories']=[]
category_set =dict()
image_set =set()
category_item_id =-1
image_id =0
annotation_id =0defaddCatItem(name):global category_item_id
category_item =dict()
category_item['supercategory']='none'
category_item_id +=1
category_item['id']= category_item_id
category_item['name']= name
coco['categories'].append(category_item)
category_set[name]= category_item_id
return category_item_id
defaddImgItem(file_name, size):global image_id
if file_name isNone:raise Exception('Could not find filename tag in xml file.')if size['width']isNone:raise Exception('Could not find width tag in xml file.')if size['height']isNone:raise Exception('Could not find height tag in xml file.')
image_id +=1
image_item =dict()
image_item['id']= image_id
print(file_name)
image_item['file_name']= file_name +".jpg"
image_item['width']= size['width']
image_item['height']= size['height']
coco['images'].append(image_item)
image_set.add(file_name)return image_id
defaddAnnoItem(object_name, image_id, category_id, bbox):global annotation_id
annotation_item =dict()
annotation_item['segmentation']=[]
seg =[]# bbox[] is x,y,w,h# left_top
seg.append(bbox[0])
seg.append(bbox[1])# left_bottom
seg.append(bbox[0])
seg.append(bbox[1]+ bbox[3])# right_bottom
seg.append(bbox[0]+ bbox[2])
seg.append(bbox[1]+ bbox[3])# right_top
seg.append(bbox[0]+ bbox[2])
seg.append(bbox[1])
annotation_item['segmentation'].append(seg)
annotation_item['area']= bbox[2]* bbox[3]
annotation_item['iscrowd']=0
annotation_item['ignore']=0
annotation_item['image_id']= image_id
annotation_item['bbox']= bbox
annotation_item['category_id']= category_id
annotation_id +=1
annotation_item['id']= annotation_id
coco['annotations'].append(annotation_item)defparseXmlFiles(xml_path):for f in os.listdir(xml_path):ifnot f.endswith('.xml'):continue
xmlname = f.split('.xml')[0]
bndbox =dict()
size =dict()
current_image_id =None
current_category_id =None
file_name =None
size['width']=None
size['height']=None
size['depth']=None
xml_file = os.path.join(xml_path, f)print(xml_file)
tree = ET.parse(xml_file)
root = tree.getroot()if root.tag !='annotation':raise Exception('pascal voc xml root element should be annotation, rather than {}'.format(root.tag))# elem is <folder>, <filename>, <size>, <object>for elem in root:
current_parent = elem.tag
current_sub =None
object_name =Noneif elem.tag =='folder':continueif elem.tag =='filename':
file_name = xmlname
if file_name in category_set:raise Exception('file_name duplicated')# add img item only after parse <size> tagelif current_image_id isNoneand file_name isnotNoneand size['width']isnotNone:if file_name notin image_set:
current_image_id = addImgItem(file_name, size)print('add image with {} and {}'.format(file_name, size))else:raise Exception('duplicated image: {}'.format(file_name))# subelem is <width>, <height>, <depth>, <name>, <bndbox>for subelem in elem:
bndbox['xmin']=None
bndbox['xmax']=None
bndbox['ymin']=None
bndbox['ymax']=None
current_sub = subelem.tag
if current_parent =='object'and subelem.tag =='name':
object_name = subelem.text
if object_name notin category_set:
current_category_id = addCatItem(object_name)else:
current_category_id = category_set[object_name]elif current_parent =='size':if size[subelem.tag]isnotNone:raise Exception('xml structure broken at size tag.')
size[subelem.tag]=int(subelem.text)# option is <xmin>, <ymin>, <xmax>, <ymax>, when subelem is <bndbox>for option in subelem:if current_sub =='bndbox':if bndbox[option.tag]isnotNone:raise Exception('xml structure corrupted at bndbox tag.')
bndbox[option.tag]=int(float(option.text))# only after parse the <object> tagif bndbox['xmin']isnotNone:if object_name isNone:raise Exception('xml structure broken at bndbox tag')if current_image_id isNone:raise Exception('xml structure broken at bndbox tag')if current_category_id isNone:raise Exception('xml structure broken at bndbox tag')
bbox =[]# x
bbox.append(bndbox['xmin'])# y
bbox.append(bndbox['ymin'])# w
bbox.append(bndbox['xmax']- bndbox['xmin'])# h
bbox.append(bndbox['ymax']- bndbox['ymin'])print('add annotation with {},{},{},{}'.format(object_name, current_image_id, current_category_id,
bbox))
addAnnoItem(object_name, current_image_id, current_category_id, bbox)if __name__ =='__main__':
xml_path ='./data/xml'
json_file ='./data/annotations/annotations_all.json'
parseXmlFiles(xml_path)
json.dump(coco,open(json_file,'w'))
Después de ejecutar el código, los archivos ./data/annotationsse pueden generar en la carpeta annotations_all.json. El código de conversión anterior es una referencia al blog de un blogger, no escrito por mí, pero debido a limitaciones de tiempo, olvidé la dirección de origen. Si alguien lo ve, envíeme un mensaje privado e indique la fuente.
Cabe señalar aquí que si el sufijo de su imagen no es jpgy png, abra el annotations_all.jsonarchivo generado, verifique file_namelos campos y use un editor de texto para reemplazar el sufijo. Por ejemplo, si mi imagen está .bmpen formato, entonces necesito .jpgreemplazarlo con.bmp
Finalmente, debe ./data/annotationscrear uno nuevo en la carpeta class_with_id.txtpara guardar el tipo correspondiente a la etiqueta de valor. Podemos abrir annotations_all.jsonel archivo nuevamente, arrastrar hasta el final y encontrar ''categories''el campo, como mi jsonarchivo
Puedes ver que el tipo 0corresponde al cattipo , abrimos el archivo y llenamos el siguiente contenido:1dogclass_with_id.txt
0 cat
1 dog
Hasta ahora, hemos completado la conversión del tutorial 3.1 usando scripts y su formato es el mismo que el del tutorial. Organización del formato de archivo final:
-mmyolo
- data
- images
-0001.bmp
-0002.bmp
-...- xml
-0001.xml
-0002.xml
-...- annotations
- annotations_all.json
- class_with_id.txt
- configs
...
Verifique la etiqueta COCO convertida
Verifique el formato de datos usando los archivos mmyoloen la carpeta del proyecto .\tools\analysis_tools\browse_coco_json.py.
Modifique el valor predeterminado del parámetro del archivo, de acuerdo con el tutorial, solo modifique --img-direl --ann-fileparámetro y, agregue defaultopciones, el código es el siguiente
defparse_args():
parser = argparse.ArgumentParser(description='Show coco json file')
parser.add_argument('--data-root', default=None,help='dataset root')
parser.add_argument('--img-dir', default='data/images',help='image folder path')
parser.add_argument('--ann-file',
default='data/annotations/annotations_all.json',help='ann file path')
parser.add_argument('--wait-time',type=float, default=2,help='the interval of show (s)')
parser.add_argument('--disp-all',
action='store_true',help='Whether to display all types of data, ''such as bbox and mask.'' Default is to display only bbox')
parser.add_argument('--category-names',type=str,
default=None,
nargs='+',help='Display category-specific data, e.g., "bicycle", "person"')
parser.add_argument('--shuffle',
action='store_true',help='Whether to display in disorder')
args = parser.parse_args()return args
También puede seguir el método en el tutorial e ingresar en la ventana de comandos:
Después de que la verificación sea correcta, este paso se completa
Dividir el conjunto de datos
Todavía podemos usar los archivos debajo del archivo del proyecto .\tools\misc\coco_split.pypara completar este paso
Modifique el valor predeterminado del parámetro del archivo, de acuerdo con el tutorial, solo modifique los --jsonparámetros y, agregue --out-diropciones , el código es el siguiente--ratiosdefault
defparse_args():
parser = argparse.ArgumentParser()
parser.add_argument('--json',type=str, default='./data/annotations/annotations_all.json',help='COCO json label path')
parser.add_argument('--out-dir',type=str, default='./data/annotations',help='output path')
parser.add_argument('--ratios',
default=[0.9,0.1],
nargs='+',type=float,help='ratio for sub dataset, if set 2 number then will generate ''trainval + test (eg. "0.8 0.1 0.1" or "2 1 1"), if set 3 number ''then will generate train + val + test (eg. "0.85 0.15" or "2 1")')
parser.add_argument('--shuffle',
action='store_true',help='Whether to display in disorder')
parser.add_argument('--seed', default=2023,type=int,help='seed')
args = parser.parse_args()return args
En particular, debe prestar atención --ratiosal método de escritura, ya que [0.9,0.1]también puede usar el método en el tutorial e ingresar en la ventana de comando:
Cree una nueva carpeta debajo de ./configsla carpeta custom_datasety custom_datasetcree un nuevo archivo debajo de la carpeta yolov6_l_syncbn_fast_1xb8-100e_animal.py. De hecho, el archivo de configuración se puede nombrar directamente, pero este nombre tiene un cierto significado, por ejemplo, el anterior yolov6_l_syncbn_fastsignifica que estoy entrenando YOLOV6-lel backbone, y syncbnsignifica que los datos en todas las tarjetas (datos de muestra global) se utilizan para calcule la capa BN durante el entrenamiento con varias tarjetas. La media y la desviación estándar fastson los modelos del modelo, 1xb8-100elo que indica que uso 1 GPU para el entrenamiento, batch sizeque es 8 y max_epoch100. De ahí el nombre.
Cree una nueva carpeta en la carpeta del proyecto work_dirscomo directorio para guardar modelos y otros trabajos. Abra el archivo en la carpeta del proyecto .\configs\yolov6\README.md, descargue el peso previo al entrenamiento de YOLOv6-l por adelantado yolov6_l_syncbn_fast_8xb32-300e_coco_20221109_183156-91e3c447.pthy colóquelo work_dirsen la carpeta.
Como estoy entrenando YOLOV6-lun modelo, lo que heredo es yolov6_l_syncbn_fast_8xb32-300e_coco.pyel archivo.
El archivo de configuración y sus comentarios son los siguientes:
No es difícil entender la primera mitad del archivo de configuración, pero train_cfgpuede ser un poco confuso en ese momento, lo explicaré con más detalle en secciones posteriores.
Explicación detallada de la sección de configuración
En general, todos los archivos de configuración se mmengine.runnerescriben en función de los métodos. Puede leer su API para tener una comprensión más profunda de los archivos de configuración.
tren_cfg
En mmengine.runnerel método, train_cfglos parámetros se describen de la siguiente manera: una contraseña para establecer un ciclo de entrenamiento. Si no proporciona una clave de "tipo", debe contener "by_epoch" para decidir qué tipo de bucle de entrenamiento se debe usar EpochBasedTrainLoopo no IterBasedTrainLoop. Si se especifica train_cfg, también debe especificarse train_dataloader. El valor predeterminado es Ninguno.
max_epochs = max_epochs: máxima max_epochsconducción de entrenamiento
val_begin = 20epoch: Evalúe el conjunto de prueba después del 20
val_interval = save_epoch_intervals: Una evaluación de prueba val_intervalpor iteración
dynamic_intervals = [(max_epochs - _base_.num_last_epochs, 1)]): Cuando max_epochs - _base_.num_last_epochsllega el momento, la evaluación se realiza cada 1 ronda
modelo
modelEsta pieza se utiliza principalmente para controlar la arquitectura del modelo, por lo que sus cambios están relacionados con el modelo original heredado, por ejemplo, lo que quiero entrenar es, luego seguiré buscando YOLOV6-lla _base_clase básica de acuerdo a lo siguiente, es decir, .\configs\yolov6\yolov6_s_syncbn_fast_8xb32-400e_coco.pypara encontrar bbox_headel campo El código es el siguiente:
model =dict(
bbox_head=dict(
head_module=dict(num_classes=num_classes)),
train_cfg=dict(
initial_assigner=dict(num_classes=num_classes),
assigner=dict(num_classes=num_classes)))
Se puede ver que solo se modifican los parámetros relacionados con el número de categorías.Para una explicación más detallada de los parámetros de la arquitectura, puede leer el tutorial oficial para aprender el archivo de configuración de YOLOV5
tren_cargador de datos
train_dataloader: Runner.train()se utiliza en , para proporcionar datos de entrenamiento para el modelo; para obtener DataLoadermás parámetros configurables, consulte la documentación de la API de PyTorch
Debido a la pequeña cantidad de datos en el tutorial, datasethay una operación en la que se repiten las veces del conjunto de datos actual RepeatDataseten cada , y configurar 5 significa repetir 5 veces. Si su conjunto de datos es lo suficientemente grande y no necesita tal operación, puede eliminarlo directamente y convertirse en:epochn
Debido a que hay un problema de muestras desequilibradas en mi conjunto de datos, utilizo ClassBalancedDatasetla operación, que hace que el número de muestras de cada categoría sea relativamente equilibrado al volver a muestrear el conjunto de datos original o ajustar los pesos de las muestras.
oversample_thres un número de punto flotante entre 0 y 1. Especifica un umbral para determinar qué clases de muestras deben sobremuestrearse. Específicamente, si el número de muestras de una determinada clase es menor que oversample_thr * max_samples, las muestras de esa clase se sobremuestrearán.
Para conocer otros métodos de procesamiento de datos, puede ver la documentación
Para datasetparámetros más detallados en , puede BASEDATASETencontrarlos en , consulte la documentación , MMYOLOtambién hay un nuevo parámetro en , el valor predeterminado typees el formato de datos 'CocoDataset'COCO
type: tipo de formato de datos
data_root: data_prefixy ann_fileel directorio raíz de
metainfo: metadatos del conjunto de datos, como información de clase
ann_file: ruta del archivo de anotación
data_prefix: El prefijo de los datos de entrenamiento. El valor predeterminado es dict(img_path='')
filter_cfg: configuración para el filtrado de datos
pipeline: tubería de procesamiento
val_cargador de datos
val_dataloaderAlgunos de datasetlos parámetros train_dataloaderson los mismos que los de , por lo que no entraré en detalles aquí.
val_evaluatorUn objeto evaluador para calcular métricas de validación. Puede ser un diccionario o una lista de diccionarios para construir el evaluador.
optim_wrapperCalcula el gradiente de los parámetros del modelo. Si se requiere un entrenamiento automático de precisión mixta o acumulación de gradientes. optim_wrapperEl tipo debe ser AmpOptimizerWrapper.
optim_wrapper =dict(optimizer=dict(lr=base_lr))
En el archivo de configuración heredado, el código completo del paquete optimizador es:
La forma de escribir en el tutorial es equivalente a solo cambiar la tasa de aprendizaje en el archivo de herencia
gancho
hookLa programación es un modo de programación, que se refiere a establecer una ubicación (punto de montaje) en una o más ubicaciones del programa. Cuando el programa se ejecuta en una determinada ubicación, llamará automáticamente a todos los métodos registrados en la ubicación en tiempo de ejecución.
hookEl tipo por defecto en el tutorial CheckpointHookes CheckpointHookguardar el peso del modelo en un intervalo dado, si se distribuye entrenamiento multitarjeta, solo el proceso master (maestro) guardará el peso.
Si quieres saber más sobre sus funciones, es decir, más parámetros, puedes consultar la documentación de la API de CheckpointHook , aquí selecciono los parámetros que aparecen en el archivo del tutorial.
interval: guardar ciclo. Si by_epoch=True, el intervalo representa épocas (período); de lo contrario, representa el número de iteraciones.
max_keep_ckpts: Máximo de puntos de control para mantener. En algunos casos, solo necesitamos los últimos puntos de control y queremos eliminar los antiguos para ahorrar espacio en disco.
save_best: si se especifica una métrica, medirá el mejor punto de control durante la evaluación. Si se aprueba un conjunto de métricas, mide el mejor conjunto de puntos de control correspondientes a las métricas aprobadas.
Acerca de ParamSchedulerHook, podemos encontrar los parámetros en el archivo de configuración heredado:
La forma en que está escrito el tutorial es equivalente a solo cambiar param_scheduleren max_epochs.
LoggerHookResponsable de recopilar registros y enviarlos a la terminal o enviarlos a archivos, TensorBoard y otros backends. interval=10Genere (o guarde) un registro cada 10 iteraciones ( ) en el tutorial
EMAHookSe realiza una operación de promedio móvil exponencial en el modelo durante el entrenamiento para mejorar la robustez del modelo. Nota: El modelo generado por el promedio móvil exponencial solo se usa para validación y prueba, y no afecta el entrenamiento.
momentum: emael impulso utilizado para actualizar los parámetros
update_buffers: En caso afirmativo True, calcula los promedios móviles de los parámetros del modelo y los búferes.
strict_load: si hacer cumplir estrictamente que state_dictlas claves en el punto de control coincidan con las claves devueltasself.module.state_dict
priority: hookprioridad
mmdet.PipelineSwitchHookes MMDetectionparte de la biblioteca para switch_epochcambiar canalizaciones de datos, documentos API
Visualización de conjuntos de datos
Podemos seguir el tutorial y usar .\tools\analysis_tools\dataset_analysis.pyel archivo para analizar los datos. Nota: Los datos en este momento se han transformado, como la operación ClassBalancedDatasetORRepeatDataset
Este archivo puede generar 4 tipos de gráficos de análisis:
Muestre bboxun gráfico de distribución de clases y recuentos de instancias:show_bbox_num
Muestre bboxla distribución de anchos y altos de clases e instancias:show_bbox_wh
bboxDiagrama de distribución que muestra las proporciones de ancho/alto de instancia y clase :show_bbox_wh_ratio
bboxMuestre la distribución de las áreas de clases e instancias bajo la regla basada en áreas :show_bbox_area
Modifique el valor predeterminado del parámetro del archivo, de acuerdo con el tutorial, modifique los ----configparámetros , --val-dataset, --class-name, y , (--area-rule--func--out-dirconfigTenga en cuenta que debe reemplazar el código en el código --configpara ejecutarlo; de lo contrario, se informará un error) para agregar defaultopciones, el código es el siguiente
defparse_args():
parser = argparse.ArgumentParser(
description='Distribution of categories and bbox instances')
parser.add_argument('--config', default='./configs/custom_dataset/yolov6_l_syncbn_fast_1xb8-100e_animal.py',help='config file path')
parser.add_argument('--val-dataset',
default=False,
action='store_true',help='The default train_dataset.''To change it to val_dataset, enter "--val-dataset"')
parser.add_argument('--class-name',
default=None,type=str,help='Display specific class, e.g., "bicycle"')
parser.add_argument('--area-rule',
default=None,type=int,
nargs='+',help='Redefine area rules,but no more than three numbers.'' e.g., 30 70 125')
parser.add_argument('--func',
default=None,type=str,
choices=['show_bbox_num','show_bbox_wh','show_bbox_wh_ratio','show_bbox_area'],help='Dataset analysis function selection.')
parser.add_argument('--out-dir',
default='./dataset_analysis',type=str,help='Output directory of dataset analysis visualization results,'' Save in "./dataset_analysis/" by default')
args = parser.parse_args()return args
También puede seguir el método en el tutorial e ingresar en la ventana de comandos:
Como estoy entrenando el modelo YOLOV6, este paso no es necesario.
La parte de procesamiento de datos en la configuración de configuración de visualización
Podemos seguir el tutorial y usar .\tools\analysis_tools\browse_dataset.pyla parte de procesamiento de datos de visualización de archivos.
Modifique el valor predeterminado del parámetro del archivo, siga el tutorial, modifique configa --config, ejecute el código
defparse_args():
parser = argparse.ArgumentParser(description='Browse a dataset')
parser.add_argument('--config', default='./configs/custom_dataset/yolov6_l_syncbn_fast_1xb8-100e_animal.py',help='train config file path')
parser.add_argument('--phase','-p',
default='train',type=str,
choices=['train','test','val'],help='phase of dataset to visualize, accept "train" "test" and "val".'' Defaults to "train".')
parser.add_argument('--mode','-m',
default='transformed',type=str,
choices=['original','transformed','pipeline'],help='display mode; display original pictures or ''transformed pictures or comparison pictures. "original" ''means show images load from disk; "transformed" means ''to show images after transformed; "pipeline" means show all ''the intermediate images. Defaults to "transformed".')
parser.add_argument('--out-dir',
default='output',type=str,help='If there is no display interface, you can save it.')
parser.add_argument('--not-show', default=False, action='store_true')
parser.add_argument('--show-number','-n',type=int,
default=sys.maxsize,help='number of images selected to visualize, ''must bigger than 0. if the number is bigger than length ''of dataset, show all the images in dataset; ''default "sys.maxsize", show all images in dataset')
parser.add_argument('--show-interval','-i',type=float,
default=3,help='the interval of show (s)')
parser.add_argument('--cfg-options',
nargs='+',
action=DictAction,help='override some settings in the used config, the key-value pair ''in xxx=yyy format will be merged into config file. If the value to ''be overwritten is a list, it should be like key="[a,b]" or key=a,b ''It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ''Note that the quotation marks are necessary and that no white space ''is allowed.')
args = parser.parse_args()return args
Puede usar el siguiente comando para verificar si el procesamiento de datos está a la altura:
MMYOLOActualmente proporciona 2 formas wandby TensorBoard, de acuerdo con su propia situaciónelige unopoder
varita mágica
Personalmente recomiendo un método, porque solo necesita iniciar sesión en la página web para ver la situación del entrenamiento en tiempo real, lo cual es muy conveniente y la visualización es mejor.
Finalmente, agregue el código de configuración al final del configarchivo recién creado .\configs\custom_dataset\yolov6_l_syncbn_fast_1xb8-100e_animal.py:
Después de ejecutar el comando de entrenamiento, Tensorboardel archivo se generará en la carpeta de visualización work_dirs\yolov6_l_syncbn_fast_1xb8-100e_animal\${TIMESTAMP}\vis_dataEjecute el siguiente comando para usar Tensorboardla visualización loss, la tasa de aprendizaje y coco/bbox_mAPotros datos de visualización en la página web:
entrenamiento ejecutivo
Abra .\tools\train.pyel archivo, modifique los parámetros, configcambie a --configy configure el valor predeterminado.
defparse_args():
parser = argparse.ArgumentParser(description='Train a detector')
parser.add_argument('--config',default='./configs/custom_dataset/yolov6_l_syncbn_fast_1xb8-100e_animal.py',help='train config file path')
parser.add_argument('--work-dir',help='the dir to save logs and models')
parser.add_argument('--amp',
action='store_true',
default=False,help='enable automatic-mixed-precision training')
parser.add_argument('--resume',
nargs='?',type=str,
const='auto',help='If specify checkpoint path, resume from it, while if not ''specify, try to auto resume from the latest checkpoint ''in the work directory.')
parser.add_argument('--cfg-options',
nargs='+',
action=DictAction,help='override some settings in the used config, the key-value pair ''in xxx=yyy format will be merged into config file. If the value to ''be overwritten is a list, it should be like key="[a,b]" or key=a,b ''It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ''Note that the quotation marks are necessary and that no white space ''is allowed.')
parser.add_argument('--launcher',
choices=['none','pytorch','slurm','mpi'],
default='none',help='job launcher')
parser.add_argument('--local_rank',type=int, default=0)
args = parser.parse_args()if'LOCAL_RANK'notin os.environ:
os.environ['LOCAL_RANK']=str(args.local_rank)return args
Después de correr, puedes ver la información específica del entrenamiento en wandbla página web o entensorboard
La siguiente es la precisión de 1 x 2080Ti, tamaño de lote = 8, entrenando 100 pesos de precisión de época work_dirs\best_coco_bbox_mAP_epoch_97:
Utilice el mejor modelo para la inferencia, abra .\demo\image_demo.pyel archivo, cambie --imglos parámetros, vale la pena señalar que los parámetros pueden ser rutas de carpetas, rutas de archivos individuales --configo . El parámetro es el archivo de configuración que creamos. Los parámetros son los pesos óptimos para el entrenamiento.--checkpointimgURL--config--checkpoint
defparse_args():
parser = ArgumentParser()
parser.add_argument('--img', default='./data/images/Image_20230621152815633.bmp',help='Image path, include image file, dir and URL.')
parser.add_argument('--config', default='./configs/custom_dataset/yolov6_l_syncbn_fast_1xb8-100e_animal.py',help='Config file')
parser.add_argument('--checkpoint', default='./work_dirs/best_coco_bbox_mAP_epoch_97.pth',help='Checkpoint file')
parser.add_argument('--out-dir', default='./output',help='Path to output file')
parser.add_argument('--device', default='cpu',help='Device used for inference')
parser.add_argument('--show', action='store_true',help='Show the detection results')
parser.add_argument('--deploy',
action='store_true',help='Switch model to deployment mode')
parser.add_argument('--tta',
action='store_true',help='Whether to use test time augmentation')
parser.add_argument('--score-thr',type=float, default=0.3,help='Bbox score threshold')
parser.add_argument('--class-name',
nargs='+',type=str,help='Only Save those classes if set')
parser.add_argument('--to-labelme',
action='store_true',help='Output labelme style label file')
args = parser.parse_args()return args