7. Entrenament de models
1. Entrenament del model

2. Fonamentació
YOLO (You Only Look Once) és una família de models de deep learning enfocats en la detecció d'objectes en imatges o vídeos. Es caracteritza per la seva velocitat i precisió en temps real, ja que el model processa tota la imatge d'una sola vegada per predir les regions on es troben els objectes i la seva classe.
2.1. Com s'entrena un model YOLO
- Recopilació de dades: Es reuneixen imatges etiquetades amb les coordenades dels objectes i les seves categories. Les coordenades es representen com a caixes delimitadores (bounding boxes) que envolten els objectes d'interès.
- Preparació de dades: S'estructuren les etiquetes en un format compatible (per exemple, COCO o YOLO).
- Configuració de l'entrenament: Es tria l'arquitectura YOLO (p. ex. YOLOv5, YOLOv7, YOLOv8, etc.), la mida del lot (batch size) i els hiperparàmetres (èpoques, taxa d'aprenentatge, etc.).
- Procés d'entrenament: Amb cada lot d'imatges, la xarxa ajusta els pesos per minimitzar la diferència entre les prediccions i les etiquetes reals.
- Validació i ajust: S'avalua el rendiment en un conjunt de validació per ajustar hiperparàmetres i evitar sobreajustament.
2.2. COCO
El modelat COCO (sigles de Common Objects in Context) es refereix a un format estàndard utilitzat per estructurar les anotacions en datasets de visió per computador.
Originalment creat per Microsoft per al seu famós dataset, s'ha convertit en un estàndard de la indústria per entrenar models d'Intel·ligència Artificial en tasques com la detecció d'objectes, la segmentació d'instàncies i la detecció de punts clau (keypoints).
A diferència d'altres formats que creen un fitxer de text per cada imatge (com el format YOLO), el format COCO utilitza un únic fitxer JSON gegant que conté tota la informació de tot el dataset (entrenament, validació o test). Aquest fitxer JSON inclou informació sobre les imatges, les categories d'objectes, les anotacions (caixes delimitadores, segmentacions, etc.) i altres metadades.
3. Dataset (Estructura i etiquetes)
L'estructura del dataset es divideix en diverses carpetes i fitxers de configuració:
Com podem observar:
dataset/: Carpeta principal del dataset.data.yaml: Fitxer de configuració que defineix les rutes d'accés a les imatges i les etiquetes, així com les classes d'objectes.images/: Carpeta que conté les imatges d'entrenament i validació.labels/: Carpeta que conté les etiquetes corresponents a les imatges, amb el mateix nom però amb extensió.txt.
Important
- Per a cada
fotoX.jpgaimages/train, hi ha un corresponentfotoX.txtalabels/trainque descriu totes les caixes dels objectes d'aquesta imatge (una línia per objecte). - La separacion primer en imatges i despres en etiquetes dependrà de les preferències de cada persona, però el més important és que les rutes d'accés a les imatges i etiquetes estiguin ben definides al
data.yamlper a que el model pugui accedir-hi correctament durant l'entrenament.
3.1. Les etiquetes
Com ja hem vist tenim per un costat les imatges i per a cada imatge tenim un fitxer de text amb el mateix nom però amb extensió .txt que conté les etiquetes. Aquestes etiquetes es representen com a línies de text, on cada línia correspon a un objecte detectat a la imatge i segueix el format següent:
| Text Only | |
|---|---|
on:
- class_id: Identificador de la classe (objecte) en format enter (0, 1, 2...). Si només tens una classe (p. ex. "matricula"), serà sempre 0. Si per exemple tens matrícules, far esquerre i far dret, matrícula seria el 0, far esquerre seria l'1 i far dret el 2.
- x_center: Coordenada X del centre de la caixa, normalitzada (dividida entre l'amplada de la imatge).
- y_center: Coordenada Y del centre de la caixa, normalitzada (dividida entre l'altura de la imatge).
- width: Amplada de la caixa, també normalitzada (dividida entre l'amplada de la imatge).
- height: Altura de la caixa, normalitzada (dividida entre l'altura de la imatge).
Tots els valors estan normalitzats en el rang 0-1 respecte a les dimensions de la imatge.
Exemple d'una BB
Imagina que tens una imatge de 1280 px d'amplada per 720 px d'altura, i la caixa delimitadora que t'interessa va des de (x1=600, y1=200) fins a (x2=750, y2=300).
Valores reales (a la imatge):
- Ample de la caixa = x2 - x1 = 150 px
- Alt de la caixa = y2 - y1 = 100 px
- Centre X = (x1 + x2)/2 = (600 + 750)/2 = 675 px
- Centre Y = (y1 + y2)/2 = (200 + 300)/2 = 250 px
Valors normalizados (al dataset): - Ample normalitzat = 150 / 1280 ≈ 0.1172 - Alt normalitzat = 100 / 720 ≈ 0.1389 - Centre X normalitzat = 675 / 1280 ≈ 0.5273 - Centre Y normalitzat = 250 / 720 ≈ 0.3472
Si class_id=0, la línea en tu archivo .txt quedaría:
| Text Only | |
|---|---|
Pensa que, quan YOLO s'entrena (o infereix), cercarà aquests fitxers .txt per saber on es troben els objectes (en el teu cas, les matrícules) i amb quina classe associar-los. Això és fonamental perquè el model aprengui de forma supervisada.
Després, en inferència o predicció, el model generarà les seves pròpies coordenades de sortida, també normalment en un sistema similar, però te les proporcionarà en escala absoluta o normalitzada segons la llibreria que estiguis utilitzant.
3.2. L'arxiu de configuració data.yaml
En el cas de YOLO (especialment en variants com YOLOv5 o YOLOv8), l'arxiu .yaml que es troba a la carpeta principal (o a l'arrel del dataset) serveix per descriure la configuració del conjunt de dades.
En general, aquest arxiu .yaml conté informació com:
-
Rutes dels dades:
- La ruta o path on es localitzen les imatges d'entrenament (train).
- La ruta on es localitzen les imatges de validació (val).
- (Opcionalment) la ruta a les imatges de prova (test).
-
Quantitat i nom de les classes:
- Un llistat amb els noms de cada classe (per exemple,
['gos', 'gat', 'persona']). - El nombre total de classes al dataset.
- Un llistat amb els noms de cada classe (per exemple,
-
Paràmetres addicionals (opcional):
- Rutes d'anotacions, si es gestionen en carpetes diferents.
- Configuracions específiques per a l'entrenament (encara que aquest tipus d'informació a vegades va en un altre arxiu diferent).
- Identificadors o camps extras que et permeten integrar el dataset en un flux de treball més complex.
Exemple d'un data.yaml:
| YAML | |
|---|---|
3.3. Augmentació del dataset
Com sabem, un dels principals problemes a l'hora d'entrenar un model de detecció d'objectes és la manca de dades. Per això, una tècnica molt utilitzada és l'augmentació de dades, que consisteix en aplicar transformacions a les imatges existents per crear noves imatges sintètiques que ajudin a millorar la generalització del model.
3.3.1. Augmentación online (on-the-fly)
Aquest tipus d'augmentació es fa durant l'entrenament. La majoria d'implementacions recents de YOLO (p. ex., YOLOv5, YOLOv7, YOLOv8) ja inclouen una sèrie de transformacions aplicades automàticament. Aquesta augmentació es fa al moment d'entrenar, i cada vegada que es carrega un lot (batch) d'imatges, s'apliquen transformacions aleatòries a les imatges i les etiquetes corresponents. Nosaltres al disc tindrem sols el conjunt original d'imatges, però el model veurà versions augmentades d'aquestes imatges durant l'entrenament.
En molts repositoris es crea un fitxer de hiperparàmetres, sovint anomenat hyp.yaml o similar. Dins d'aquest fitxer, pots ajustar distintos paràmetres d'augmentació com:
- hsv_h, hsv_s, hsv_v: Augments de to, saturació i valor en espai de color HSV.
- degrees: Rotació.
- translate: Translació (moviment de la imatge).
- scale: Escalat.
- shear: Efecte de cisalladura (shear).
- flipud: Gir vertical.
- fliplr: Gir horitzontal.
Per exemple, en YOLOv5 (dins del seu repositori oficial) existeix un fitxer hyp.yaml amb paràmetres predefinits. Pots editar-lo per ajustar la intensitat de cada transformació.
3.3.2. Exemple (simplificat) hyp.yaml
| YAML | |
|---|---|
En entrenar el teu model YOLO aplicarà automàticament aquestes transformacions al carregar cada lot (batch) d'imatges.
La crida d'entrenament podria ser similar a aquesta, passant-ho com a paràmetres dins d'un programa Python. Ho veurem més endavant a la secció de codi, però aquí tens un exemple de com es podria configurar l'entrenament amb augmentació:
3.3.3. Augmentació offline o directa
En aquest cas, les transformacions s'apliquen abans de l'entrenament, i es guarden com a noves imatges i etiquetes al disc. Això pot ser útil si vols tenir un control total sobre les imatges augmentades o si vols reutilitzar-les en diferents experiments sense haver de generar-les cada vegada.
Fer augmentació offline implica crear un nou conjunt d'imatges augmentades i les seves corresponents etiquetes. Per exemple, si tens 100 imatges originals i apliques 5 transformacions diferents a cada imatge, podries acabar amb 500 imatges augmentades (a més de les 100 originals).
Farem servir la llibreria albumentations per a fer augmentació offline. Aquesta llibreria és molt potent i flexible, i permet aplicar una gran varietat de transformacions tant geomètriques com de color.
Pots trobar exemples molt interessants a https://docs.ultralytics.com/integrations/albumentations/
El programa que et passes aumentar_dataset_yolo.py és un script que utilitza albumentations per augmentar un dataset de YOLO. Aquest script llegeix les imatges i les etiquetes del dataset original, aplica transformacions d'augmentació a les imatges i actualitza les etiquetes corresponents per reflectir els canvis.
4. Creació del dataset (Lego-StarWars)
Doncs be, ha arribat el pas més complex, que és la creació del dataset. Per a això, necessitem recollir imatges que continguin els objectes que volem detectar (en el nostre cas, figures de Lego de StarWars) i etiquetar-les amb les caixes delimitadores corresponents.
Per a crar-ho anem a fer servir una eina molt còmoda i popular, que és label-studio. Aquesta eina ens permet carregar les imatges, dibuixar les caixes delimitadores al voltant dels objectes d'interès i guardar les etiquetes en el format que necessitem per a entrenar el nostre model YOLO.
L'eina està integrada en una web app, que podem instal·lar en local:
| Bash | |
|---|---|
pera arrancar-la, només cal executar:
| Bash | |
|---|---|
i accedir a http://localhost:8080 des del navegador. Un cop dins, podem crear un nou projecte, carregar les imatges i començar a etiquetar.
Si no volem instal·lar res al nostre entor, podem fer ús de docker per a executar label-studio en un contenidor. Per a això, podem utilitzar la següent comanda:
| Bash | |
|---|---|
Això posa a escoltar el servidor al port 8080 i monta la carpeta dataset del nostre home (on executem docker) del disc dins del contenidor, de manera que les imatges que carreguem a label-studio es guardaran directament a la carpeta dataset del nostre projecte i no les perdrem quan tanquem el contenidor.
Accedirem al servidor de label-studio a http://localhost:8080. Ens hem de registrar, però es un login local, que no es connecta a cap servidor exter.

Un cop dins, crearem un nou projecte.

A la següent pestanya carregarem les imatges que volem etiquetar. Podem carregar-les des del disc local o, si estem executant label-studio amb docker, podem carregar-les directament a la carpeta dataset del nostre projecte i després seleccionar-les des de l'eina. Tambe ens permet carregar-les des d'una URL al nuvol, com S3 o Google Drive.


La última part de l'assistent és definir per a que és el dataset que estem creant. En el nostre cas, seleccionarem Object Detection with Bounding Boxes.

Eliminem els labels que venen per defecte i creem un nou label amb el nom de la classe que volem detectar. Els escriurem un en cada línea. Farem clic en add.
Fent clic a les etiquetes podem canviar el color.
Finalment, fem clic a save per a crear el projecte i començar a etiquetar les imatges.


Ara ja podem començar a etiquetar les imatges. Per a això, farem doble clic a una imatge i dibuixarem una caixa delimitadora al voltant de cada objecte que volem detectar:
- Seleccionem la etiqueta
- Dibuixem el BB de la classe que volem detectar
- Fem clic a
submitper a guardar l'etiqueta
Repetirem el procés per a cada imatge.

Un cop hem etiquetat tot hem de procedir a generar el dataset en el format que necessitem per a entrenar el nostre model YOLO. Per a això, farem clic a Export i seleccionarem el format YOLO with images. Això generarà un fitxer .zip que conté les imatges i les etiquetes en el format correcte i el arxiu YAML de configuració.

Ja tenim les nostres dades etiquetades i preparades per a entrenar el nostre model YOLO!
5. Entrenament
Ara ha arribat el moment de entrenar el model. Aquest pas és molt senzill si hem definit el arxiu yaml d'abans, el qual completarem. Anem a veure un exemple al qual descriurem alguna de les parts:
model_type: Aquest paràmetre especifica el tipus de model de YOLO que s'utilitzarà. Els models de YOLO es presenten en diverses variants amb diferents mides i capacitats:yolo_vX_[mida]-opt:vxés la versió: 8, 9, 11, etc.midaés una lletra que defineix la mida del model preentrenat. Com més gran sigui, millor serà el resultat, però també augmentarà el cost d'entrenament per la quantitat d'hiperparàmetres. Valors possibles (la inicial): nano, small, medium, large i xtraLarge.optés per escollir el tipus de detecció que es farà amb el model.

batch_size: És el nombre d'imatges que es processen en cada pas d'entrenament abans d'actualitzar els pesos del model. Un valor de 16 significa que el model processarà 16 imatges alhora. Unbatch_sizemés gran pot accelerar l'entrenament, però també requereix més memòria GPU, mentre que un valor petit farà que el model sigui més estable però més lent.img_size: La mida de la imatge a la qual es redimensionaran totes les imatges d'entrada abans de ser alimentades al model. En aquest cas. Una resolució més gran permet que el model capti més detalls, però també requereix més memòria i pot ser més lent.epochs: És el nombre total de vegades que el model passarà per tot el conjunt de dades durant l'entrenament. Si el model no millora després de diverses èpoques, pots aturar l'entrenament per evitar el sobreajust.learning_rate: La taxa d'aprenentatge és la mida del pas que l'optimitzador fa per ajustar els pesos del model en cada iteració. Un valor de 0.001 significa que l'optimitzador ajustarà els pesos amb un pas petit en cada iteració. Un valor més alt pot fer que el model aprengui més ràpid, però pot ser menys estable. Un valor més baix pot fer que el model aprengui de manera més estable, però més lentament.momentum: És un paràmetre que ajuda a accelerar l'entrenament, especialment en les primeres etapes. Un valor de 0.937 és força comú i millora la convergència de l'optimitzador, ajudant que el model no quedi atrapat en mínims locals.weight_decay: És una tècnica de regularització utilitzada per prevenir el sobreajust, penalitzant els pesos grans durant l'entrenament. Un valor de 0.0005 és força baix i és una regularització moderada. Un valor més alt deweight_decaypot reduir el risc de sobreajust, però també pot evitar que el model aprengui massa dels dades.pretrained_weights: Especifica si s'utilitzarà un model preentrenat. Utilitzar pesos preentrenats accelera el procés d'entrenament i millora la precisió del model, especialment si el conjunt de dades és petit. Els models preentrenats s'entrenen amb grans datasets com COCO, cosa que ajuda que el model tingui una bona base per aprendre a detectar objectes.train: Especifica la ruta al directori que conté les imatges d'entrenament. Les imatges d'entrenament s'utilitzen per entrenar el model a reconèixer objectes.val: Especifica la ruta al directori que conté les imatges de validació. Les imatges de validació s'utilitzen per avaluar el model durant l'entrenament, assegurant-se que no estigui sobreajustant les dades d'entrenament.nc: Aquest paràmetre especifica el nombre de classes en el conjunt de dades. En aquest cas, 7 classes. És important que el nombre de classes coincideixi amb el nombre de classes definides als fitxers d'etiquetes.names: Aquest és un diccionari que mapeja un índex de classe (començant des de 0) al seu nom corresponent. Pot ser una llista numerada com l'exemple o algunes versions permeten un array:names: ["Chewbacca", "Leia", "Luke", "ObiWan", "Solo", "StormTrooper", "Vader"]
Al següent exemple podem veure com queda un programa per entrenar el model
Entrenament del model
| Python | |
|---|---|
Com podem veure:
- Es fa servir el model
yolov8s. La primera execució es descarrega desde ultralycs i es guarda en la carpeta model - Posteriorment comença l'entrenament i va mostrant per pantalla les iteracions i les èpoques
Ademès
Altres arguments interesants son:
save_period=nper a guardar el estat dels hiperparàmetres cadanèpoques iresume=Trueper a reprendre l'entrenament. L'entrenament pot parar-se en força bruta (CTRL+C, CTRL+Z).
També comentar que els models parcials i finals es guarden dins d'una carpeta que es crea anomenada runs i on es creen train_n on n indica el número d'execucions o llançaments que fem del model.
Dins d'aquest run trobarem al final un model anomenat best.pt amb la millor versió dels hiperparàmetres
Per guardar el millor model, per example de l'execució numero 5 (train5):
Aquest model és el que farem servir a continuació per a les prediccions
Tota la informació la pots trobar a https://docs.ultralytics.com/modes/train/
6. Predicció del model
Finalment ha arribat el moment de probar el model, a veure si funciona de manera adequada.
Els passos a seguir son:
- Carregar el model entrenat
- Indicar quina imatge volem processar
- Fer la predicció
- Analitzar els resultats
- Mostrar els resultats
Mirem-ho pas a pas:
Com podem veure la carrega del model i la predicció no te complicació. Fixar-se que podem fer la predicció per a una o diverses imatges, i el resultat dependrà d'això. La variable result contindrà un llistat amb variables de tipus Results, una per imatge que fem predicció. Tens la informació completa a la seua web en aquest link
Aquesta variable depenent del model que hem entrenat tindrà uns resultats o altres. En el cas que ens segueix, que és la detecció d'objectes, ens interessen els elements:
names: diccionari amb les classes de objectes que detecta el nostre model. Coincideix amb les classes que hem entrenat.boxes: un objecte que conté els elements detectats, que son de tipusBoxeslen(Results): ens dona quants elements s'han detectat.
Per a cada element de tipus boxes trobarem, per avaluar el resultat:
cls: la id de la classe del objecte detectatconf: la confiança en tant per 1 del objecte detectatxyxy: les coordenades dels extrems de la BB, en valors realsxyxyn: igual que l'anterior però normalitzat segons el tamany de la imatge d'entradaxywh: la coordenada del centre de la caixa, ample i llargxywhn: el mateix, però normalitzat al tamany de la imatge d'entrada
::: note
| Text Only | |
|---|---|
1 | |
Pintem la informació sobre la imatge