Inicie la poda del modelo yolov5 desde cero

Iniciar la poda del modelo yolov5 desde cero ·

1. Introducción

[Durante todo el proceso, se encontraron más de 10 problemas en tren normal, repuestoTrain, poda y ajuste fino, incluidas soluciones para AttributeError, ModuleNotFoundError, RuntimeError, SyntaxError, TypeError, etc., consulte el contenido para obtener más detalles]

Para trasplantar el modelo existente a la plataforma ARM, al mismo tiempo que se garantiza la precisión del modelo, se reduce el consumo de energía informática y el tiempo de inferencia del modelo.

Hemos realizado experimentos antes para comparar YOLOv5, YOLOv7 y YOLOv8 , combinamos el tiempo de inferencia y la precisión de diferentes versiones de los modelos y verificamos mucha información, incluidas las descripciones de blogs de la mayoría de las personas, y combinadas con la experiencia de la mayoría de las personas, sentimos que yolov5 tiene una mejor capacidad de generalización.bien. Por lo tanto, al considerar entrenar nuestro propio modelo e implementarlo en plataformas X86 y ARM, entrenamos y podamos el modelo para yolov5 para facilitar la implementación liviana de modelos pequeños.

Por supuesto, también necesitamos realizar una cuantificación INT8 en el modelo final para reducir el tiempo de inferencia de la detección del objetivo.

2 Obtenga el código fuente de GitHub

Descargue el código fuente de la siguiente ruta:

https://github.com/midasklr/yolov5prune/tree/v6.0

Este artículo está recortando la versión 6.0 de GitHub anterior.

3 principios

[Basado en la introducción de la poda yolov5 en algunos blogs/artículos, resumamos brevemente los principios de la poda del modelo yolov5]

3.1 Principio

Documento principal: Aprendizaje de redes convolucionales eficientes mediante el adelgazamiento de redes

ref: Filtros de poda para ConvNets eficientes (https://arxiv.org/abs/1608.08710)

referencia: https://blog.csdn.net/qq_42835363/article/details/129125376?spm=1001.2014.3001.5501

referencia: https://blog.csdn.net/IEEE_FELLOW/article/details/117236025

ref: Poda de modelo en Yolov5_5.0

La entrada pasa a través de la capa BN (Normalización por lotes) para obtener la distribución normalizada. Hay dos parámetros entrenables γ (gamma) y β (beta) en la capa BN.

Cuando gamma y betaγ tienden a 0, la entrada equivale a multiplicarse por 0. En este momento, la convolución en el canal generará 0, lo cual no tiene sentido. Por lo tanto, se puede considerar que la eliminación de dichos canales redundantes no tiene ningún impacto en el rendimiento del modelo.

Durante el entrenamiento normal de la red, la gamma generalmente se distribuye cerca de 1 debido a la inicialización. Para hacer que gamma tienda a 0, puede restringirla agregando regularización L1 para que los coeficientes sean escasos. En el artículo, el entrenamiento que agrega regularización gammaL1 se denomina entrenamiento disperso.

Después de un entrenamiento escaso, las capas escasamente pequeñas se cortan y las activaciones correspondientes también son muy pequeñas, por lo que el impacto en lo siguiente es muy pequeño. Al iterar repetidamente este proceso, se puede obtener un modelo pequeño. Los pasos se muestran en la Figura 1.

Insertar descripción de la imagen aquí

Figura 1

3.2 proceso de adelgazamiento de la red

① Primero inicialice la red, agregue la regularización L1 a los parámetros de la capa BN y entrene la red.

② Estadísticas de γ (gamma) en la red y establezca la tasa de poda para podar la red.

③ Ajuste la red podada para completar el trabajo de poda.

4 pasos de implementación específicos

4.1 Instalar entorno virtual

Descomprima el código fuente descargado, ingrese al directorio yolov5prune_6.0 y realice las siguientes operaciones en secuencia

# 1 创建虚拟环境
conda create -n yolov5prune
# 2 激活虚拟环境
conda activate yolov5prune
# 3 安装虚拟环境(根据yolov5prune_6.0根目录下的requirements.txt安装)
pip install -r requirements.txt

4.2 Parámetros de configuración

4.2.1 Parámetros del conjunto de datos

La estructura de su propio conjunto de datos es la siguiente

--datasTrain
------images
----------train     	# 存放训练数据集的图片(.jpg)
----------val
----------test
------labels
----------train			# 存放训练图片对应的标签文件(.txt)
----------val
----------tes

En el directorio /yolov5prune_6.0/data/, cree el archivo my_yolov5.yaml siguiendo la estructura en coco128.yaml. El contenido es el siguiente.

# Train/val/test sets as 
# 1) dir: path/to/imgs, 
# 2) file: path/to/imgs.txt, or 
# 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: /home/user/hlj/MyTrain/datasTrain3_More/  # dataset root dir
train: images/train/  # train images (relative to 'path') 128 images
val: images/val/      # val images (relative to 'path') 128 images
test:  images/test/   # test images (optional)


nc: 11  # number of classes
names: ['pedes', 'car', 'bus', 'truck', 'bike', 'elec', 'tricycle', 'coni', 'warm', 'tralight', 'specVehi']

4.2.2 Parámetros de la estructura del modelo

Modifique el tipo de detección de objetivos en yolov5prune_6.0/models/yolov5s.yaml para adaptarlo a la cantidad de tipos de detección de objetivos en su propio conjunto de datos. como sigue

nc: 11

4.2.3 Parámetros en train.py

Configure los parámetros en train.py, incluidos principalmente los siguientes:

'--weights', default='./yolov5s.pt'  # 由于我要从头训练,所以注释了此参数
'--cfg', default='./models/yolov5s.yaml'
'--data', default='./data/my_yolov5.yaml'
'--epochs', default=300 		# 由于从头训练,所以epochs值设的比较大
'--batch-size', default=-1
'--imgsz', default=640			# 考虑部署

4.3 Entrenamiento normal

4.3.1 Preparación

Como estoy haciendo SSH, primero cree/abra una sesión tmux

tmux new -s prunesession

Si [presione ctrl+b primero, luego presione d solo] para salir de la sesión, deberá usar el comando para ingresar a la sesión la próxima vez

tmux a -t prunesession

Para ingresar a la sesión, primero ingrese al directorio del proyecto y active el entorno virtual (si se ha activado, puede ignorarlo)

cd ../yolov5prune_6.0/
source activate yolov5prune

Eliminar la sesión después del entrenamiento.

tmux kill-session -t prunesession

4.3.2 Capacitación y resolución de problemas

Ejecute el siguiente comando para realizar el entrenamiento.

python3 train.py

【Pregunta 1】

Después de ejecutar el archivo train.py, se informó el siguiente error

ModuleNotFoundError: No module named 'utils.loggers.wandb'

Le indica que falta el paquete. Según las estrategias de otras personas, descargue el código correspondiente a la versión yolov5_6.0 de U God y luego copie toda la carpeta wandb en el directorio yolov5_6.0 \ utils \ loggers \ a yolov5prune_6. 0\utils\loggers directorio.

【Pregunta 2】

Después de volver a ingresar a python3 train.py, se informa el siguiente problema: se puede ver que al configurar los parámetros en train.py, el parámetro '--weights' no se puede comentar.

AttributeError: 'Namespace' object has no attribute 'weights'

Por lo tanto, el parámetro 'pesos' se establece de la siguiente manera, lo que significa que no se utilizarán los pesos previamente entrenados y el modelo se entrenará desde cero.

'--weights', default=''

【Pregunta 3】

No sé por qué, pero se ha informado de otro gran problema en Ubuntu: no existe tal problema cuando se ejecuta localmente.

raise AttributeError(__former_attrs__[attr])
AttributeError: module 'numpy' has no attribute 'int'.

Resulta que la nueva versión de numpy no tiene np.int, lo que se puede solucionar modificando el código fuente.

Modifique todo...astype(np.int) en datasets.py en el directorio yolov5prune_6.0/utils/ a...astype(int), como se muestra a continuación:

441  bi = np.floor(np.arange(n) / batch_size).astype(int)  # batch index
483  self.batch_shapes = np.ceil(np.array(shapes) * img_size / stride + pad).astype(int) * stride
854  b = xywh2xyxy(b.reshape(-1, 4)).ravel().astype(int)

Modifique todo...astype(np.int) en general.py en el directorio yolov5prune_6.0/utils/ a...astype(int), como se muestra a continuación:

510  classes = labels[:, 0].astype(int)  # labels = [class xywh]
525  class_counts = np.array([np.bincount(x[:, 0].astype(int), minlength=nc) for x in labels])

【Pregunta 4】

File "/home/user/hlj/MyTrain/yolov5prune_6.0/utils/loss.py", line 217, in build_targets
indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1))) 
RuntimeError: result type Float can't be cast to the desired output type long int

Referencia de referencia: https://blog.csdn.net/Thebest_jack/article/details/125649451 Realice las siguientes operaciones:

Modifique el código fuente de loss.py en el directorio yolov5prune_6.0/utils/,

#(1) 183行左右
for i in range(self.nl):
    anchors, shape = self.anchors[i], p[i].shape   # anchors = self.anchors[i]
    gain[2:6] = torch.tensor(p[i].shape)[[3, 2, 3, 2]]  # xyxy gain
#(2)218行后
# indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1)))  
上一行代码改为如下
indices.append((b, a, gj.clamp_(0, shape[2] - 1), gi.clamp_(0, shape[3] - 1)))  # image, anchor, grid indices            

【Pregunta 5】

Durante la época, se reportan las siguientes preguntas:

File "..../yolov5prune_6.0/utils/plots.py", line 116, in text
w, h = self.font.getsize(text)  # text width, height
AttributeError: 'FreeTypeFont' object has no attribute 'getsize'

Esto se debe a que se instaló una nueva versión de Pillow, pip install tf-models-official eliminó la función getsize
y la degradación a Pillow 9.5 resolvió el problema. Puede probar los siguientes métodos para resolver el problema, consulte la [Pregunta 8]:

pip install Pillow==9.5

【Pregunta 6】

Después de que finaliza la época 0 y finaliza val, se informa el siguiente problema

File ".....\yolov5prune_6.0\utils\callbacks.py", line 77, in run
    logger['callback'](*args, **kwargs)
TypeError: on_fit_epoch_end() missing 1 required positional argument: 'fi'

Busque el código fuente oficial y copie el archivo completo de los registradores en yolov5_6.0/utils/. Debería estar bien. Puede deberse a versiones inconsistentes.

【Pregunta 7】

yolov5prune_6.0/utils/general.py line471
return re.sub(pattern="[|@#!?·$€%&()=??^*;:,¨′><+]", repl="_", string=s)
SyntaxError:(unicoda error)'utf-8' code can't decode byte 0xal in position 6: invalid start byte。 

Debería ser un problema que el código 'utf-8' no sea compatible. Agregué el siguiente formato de codificación, pero al final no se resolvió. Miré la función de la función correspondiente y descubrí que era solo para limpiar la cadena (reemplazando caracteres especiales con guiones bajos), así que cambié directamente esa línea de código, que no tuvo ningún impacto en todo el programa.

# -*- coding: utf-8 -*-

【Resumir】

Aunque continuaron varios problemas y no me importó la [Pregunta 5], al final, python3 train.py finalmente se ejecutó normalmente.

4.4 Formación escasa

4.4.1 Configuración de parámetros

Establecer los parámetros de train_sparity.py

'--st', action='store_true',default=True,
'--sr', type=float, default=0.0001,
'--weights', type=str, default=ROOT / '',
'--cfg', type=str, default='./models/yolov5s.yaml',
'--data', type=str, default='./data/my_yolov5.yaml',
'--epochs', type=int, default=300
'--batch-size', type=int, default=-1,   # 注意【问题8】的发生
'--imgsz', '--img', '--img-size', type=int, default=640,
'--adam', action='store_true', default=True, 

4.4.2 Formación escasa y problemas

Ejecute el siguiente comando para realizar un entrenamiento escaso

python train_sparity.py

Insertar descripción de la imagen aquí

【Pregunta 8】

loggers.on_params_update({"batch_size": batch_size})
AttributeError: 'Loggers' object has no attribute 'on_params_update'

Parece ser causado por autobatch, así que primero cambié los parámetros '–batch-size', type=int, default=-1 al valor fijo default=2. Después de eso, epoch0 puede ser normal. Pero todavía queda el problema del [Problema 5], aunque no afecta el entrenamiento, creo que debería solucionarse, después de todo, es un problema de AttributeError. La solución es la siguiente:

# pillow版本太新的原因,新版的getsize属性被删除掉了。
pip3 uninstall pillow
pip3 nstall pillow==9.5

【Pregunta 9】

Después de que finalizó el valor de Epoch0, se informó el siguiente problema

File "/home/user/hlj/MyTrain/yolov5prune_6.0/utils/callbacks.py", line 77, in run
logger['callback'](*args, **kwargs)
TypeError: Loggers.on_fit_epoch_end() takes 5 positional arguments but 6 were given

Este problema se debe a que para resolver el [Problema 6], reemplacé el archivo utils/loggers/init.py en el proyecto con el archivo oficial. Encontré def on_fit_epoch_end(self, vals, bn_weights, epoch, best_fitness en el archivo init.py, fi) Para reducir bn_weights, vuelva a copiar el archivo en el proyecto de poda en este proyecto.

4.5 Poda

4.5.1 Configuración de parámetros

​Establezca los parámetros de proporción de recorte, puede probar de pequeño a grande. Tenga en cuenta que el archivo de modelo de cfg debe corresponder a los pesos; de lo contrario, habrá un problema de falta de coincidencia de los valores clave durante el proceso de ejecución de poda. El modelo correspondiente pruned_model.pt se guardará después de que se complete el recorte.

En el archivo prune.py, modifique los siguientes parámetros

'--data', type=str, default=ROOT / 'data/my_yolov5.yaml',
'--weights', nargs='+', type=str, default=ROOT / 'runs/train/spaweight/last.pt'
'--cfg', type=str, default='./models/yolov5s.yaml',
'--percent', type=float, default=0.1,
'--batch-size', type=int, default=16, 
'--imgsz', '--img', '--img-size', type=int, default=640,

correr

python prune.py

【Pregunta 10】

SyntaxError: Non-UTF-8 code starting with '\xe5' in file /home/user/hlj/MyTrain/yolov5prune_6.0/prune.py on line 400, but no encoding declared; see https://peps.python.org/pep-0263/ for details

Solución: busque la línea correspondiente y descubra que es un problema con el formato del código del contenido del comentario, elimínelo o cambie el chino al inglés.

【Pregunta 11】

return func(*args, **kwargs)
TypeError: run() got an unexpected keyword argument 'cfg'

La solución es agregar parámetros en la función run() del código fuente de prune.py de la siguiente manera:

cfg = './model/yolov5s.yaml'

4.5.2 Poda

Pode el modelo best.pt después de un entrenamiento escaso.

Si se han configurado los parámetros, ejecute python prune.py directamente

python prune.py

De lo contrario, el peso transferido es el peso obtenido mediante un entrenamiento escaso.

python prune.py --weights runs/train/exp_sparity/weights/best.pt --percent 0.5 --cfg models/yolov5s.yaml

Una vez completado el corte, el modelo correspondiente pruned_model.pt se guardará en el directorio raíz.

4.6 ajustar la red podada

4.6.1 Configuración de parámetros

Cambie los parámetros relevantes de finetune_pruned.py de la siguiente manera

'--weights', type=str, default=ROOT / 'pruned_model.pt',
'--cfg', type=str, default='./models/yolov5s.yaml',
'--data', type=str, default=ROOT / 'data/my_yolov5.yaml', 
'--epochs', type=int, default=100
'--batch-size', type=int, default=16, 
'--imgsz', '--img', '--img-size', type=int, default=640,
'--adam', action='store_true', default=True, 
'--workers', type=int, default=8, 
'--project', default=ROOT / 'runs/finetune',

4.6.2 ajustar

Si los parámetros en finetune_pruned.py no se han modificado, ejecute lo siguiente.

python finetune_pruned.py --weights pruned_model.pt --adam --epochs 100

Dado que los parámetros en finetune_pruned.py se modifican directamente, ejecútelos directamente

python finetune_pruned.py

Al ejecutar, se informa [Problema 9] Fine_tune puede iniciarse normalmente de acuerdo con las soluciones relevantes.

4.7 Entrenamiento cíclico disperso->Poda->ajuste de red

Esta vez solo hice una ronda de dispersión->poda->ajuste fino. Ni el entrenamiento normal ni el entrenamiento escaso utilizan modelos previamente entrenados. La comparación incluye resultados de ajuste después de recortar en diferentes escalas del modelo (10%, 20%, 30%).

Tabla 2 Comparación de la poda del modelo de detección de objetivos

Tren Esparidad Antes de podar afinar afinar afinar
Podar0.1 Podar0.2 Podar0.3
modeloTamaño(M) 13,8 millones 13,8 millones 13.8 12,3 millones 10,5 millones 8,68 millones
PAG 0,915 0.923 0.919 0.916 0,899 0,892
R 0.832 0.808 0.816 0,829 0,84 0,842
[email protected] 0,885 0,879 0.881 0,887 0,887 0,888
[email protected]:.95 0,642 0,628 0.633 0,639 0,64 0,642

(1) Se puede ver que es factible podar el 30% del modelo yolov5s garantizando el mAP básico.

(2) Teniendo en cuenta la pertinencia del modelo, generalmente nos resulta difícil entrenar un modelo con alta precisión y una gran capacidad de generalización, por lo que a menudo necesitamos podar y ajustar los datos y el modelo del proyecto.

(3) Pruebe el efecto del modelo ajustado en la detección de transmisiones de video en tiempo real. Dado que la escala de entrenamiento del modelo es 640, la tasa de recuperación de objetivos distantes es baja y existe un fenómeno de detección perdida cuando el tráfico en la intersección es denso.

Supongo que te gusta

Origin blog.csdn.net/qq_42835363/article/details/132500571
Recomendado
Clasificación