YOLO Training Pipeline: Difference between revisions

From LogicalDOC Community Wiki
Jump to navigationJump to search
Giuseppe (talk | contribs)
Giuseppe (talk | contribs)
No edit summary
Line 52: Line 52:


== Populate the Training Directory ==
== Populate the Training Directory ==


=== Extract the Dataset ===
=== Extract the Dataset ===


After annotating the documents in Label Studio (see [[Label Studio Guide]]), extract the downloaded archive to a local directory.
After annotating the documents in Label Studio (see [[Label Studio Guide]]), export the dataset and extract the downloaded archive to a local directory.


The extracted archive contains:
The extracted archive contains:


* labels/         (YOLO annotation files)
* `labels/` – YOLO annotation files (`.txt`)
* classes.txt     (class definitions)
* `classes.txt` – class definitions
* notes.json       (Label Studio metadata)
* `notes.json` – Label Studio metadata
* images/         (may be empty depending on export settings)
* `images/` – image files (may be empty depending on the selected export format)


[[File:YOLO-archive-content.png|thumb|800px|center|Content of the dataset exported by Label Studio]]


[[File:yolo-downloaded-archive.png|thumb|800px|center|YOLO archive content]]
=== Prepare the Dataset Structure ===


 
The training pipeline expects the following dataset structure:
 
=== Dataset Structure ===
 
The training pipeline expects the following directory structure:


<pre>
<pre>
Line 82: Line 78:
│  ├── train/
│  ├── train/
│  └── val/
│  └── val/
├── classes.txt
├── synset.txt
└── notes.json
├── notes.json
└── data.yaml
</pre>
</pre>


Where:
The following steps describe how to transform the exported dataset into the expected structure.


* images/train contains the training images
=== Populate the Dataset ===
* images/val contains the validation images
* labels/train contains the training annotations
* labels/val contains the validation annotations
* data.yaml contains the dataset configuration


# Move all annotation files (`.txt`) from `labels/` to `labels/train/`.


'''IMPORTANT'''
# Copy the corresponding images into `images/train/`.


Move the <code>.txt</code> file from <code>labels</code> directory into <code>labels/train</code> directory.
# Rename `classes.txt` to `synset.txt`.
 
And create the other required folders.


# Create the empty directories:


<pre>
images/val/
labels/val/
</pre>


'''IMPORTANT'''
'''IMPORTANT'''


The conversion process generates only the annotation files and does not move the images.
Depending on the selected export format, Label Studio may export only the annotation (`.txt`) files. In this case, the corresponding images must be copied manually from the original image directory into `images/train/`.


Copy the corresponding images into the <code>images/train</code> directory.
'''IMPORTANT'''


Do not worry about populating the <code>images/val</code> or <code>labels/val</code> directories.
Verify that every image has a corresponding annotation file with the same filename.
 
Those will be automatically populated moving the 30% of files from <code>images/train</code> and <code>labels/train</code> via a script
 
Verify that every annotation file has a matching image.
Each image must have a corresponding annotation file with the same filename.


Example:
Example:
Line 123: Line 115:
</pre>
</pre>


 
If the automated training script (`train.sh`) is used, the `images/val/` and `labels/val/` directories should initially remain empty. During execution, the script automatically moves the configured percentage of images and annotation files from the training set into the validation set.
 
'''IMPORTANT'''
 
Rename <code>classes.txt</code> to <code>synset.txt</code>, as the training pipeline expects class definitions to be provided through a file named <code>synset.txt</code>.
 
In addition to that specific structure for the <code>dataset/</code> directory, other important files are required for the training (<code>data.yaml</code>, <code>train.py</code>).
 
<pre>
dataset/
├── images/
│  ├── train/
│  └── val/
├── labels/
│  ├── train/
│  └── val/
├── notes.json
├── data.yaml
├── synset.txt
└── train.py
</pre>


=== Create the data.yaml File ===
=== Create the data.yaml File ===


YOLO uses a configuration file named data.yaml to locate the dataset and identify the available classes.
YOLO uses a configuration file named `data.yaml` to locate the dataset and identify the available classes.


The file specifies:
The file specifies:
Line 160: Line 132:
<syntaxhighlight lang="yaml">
<syntaxhighlight lang="yaml">
path: dataset
path: dataset
train: images/train
train: images/train
val: images/val
val: images/val
Line 166: Line 139:


names:
names:
  0: invoice_number
0: invoice_number
  1: date
1: date
  2: seller_name
2: seller_name
  3: total
3: total </syntaxhighlight>
</syntaxhighlight>


The class definitions must match those used during annotation.
The class definitions must match those defined during annotation.


=== Create the Python Training Script ===
=== Create the Python Training Script ===


The training script shoul include the Ultralytics YOLO framework.
Create a Python script (`train.py`) that uses the Ultralytics YOLO framework to train the model.


A pretrained YOLO model such as:
Training always starts from a pretrained YOLO model, such as:


* yolo11n.pt
* `yolo11n.pt`
* yolo11s.pt
* `yolo11s.pt`
* yolo11m.pt
* `yolo11m.pt`
* yolo11l.pt
* `yolo11l.pt`


is required as the starting point for training.
The pretrained model does not need to be downloaded manually. Ultralytics automatically downloads it when the training script is executed.


The model does not need to be downloaded manually. Ultralytics automatically downloads it when the training script is executed.
A minimal training script is shown below:


 
<syntaxhighlight lang="python">
A minimal training script can be as simple as:
 
<syntaxhighlight lang="Python">
from ultralytics import YOLO
from ultralytics import YOLO


Line 198: Line 167:


model.train(
model.train(
    data="data.yaml",
data="data.yaml",
    epochs=100
epochs=100
)
) </syntaxhighlight>
</syntaxhighlight>


A more advanced script may explicitly configure additional training parameters such as the optimizer, learning rate, batch size, image size, and device selection.


A more specific training script can look like this:
The parameters most commonly customized are:


<syntaxhighlight lang="Python">
* `epochs` – number of training epochs
from ultralytics import YOLO
* `batch` – number of images processed per batch
* `imgsz` – input image size
* `device` – CPU or GPU used for training
* `project` – output directory
* `name` – training run name


def main():
For a complete list of supported parameters, refer to the official Ultralytics documentation:
    model = YOLO("yolo11m.pt")
 
    model.train(
        data="data.yaml",
        epochs=150,
        batch=15,
        workers=12,
        lr0=0.002,
        momentum=0.9,
        weight_decay=0.0005,
        warmup_epochs=3,
        warmup_momentum=0.8,
        warmup_bias_lr=0.1,
        optimizer="AdamW",
        patience=30,
        imgsz=846,
        name="target",
        device=0,
        amp=True,
        save=True,
        save_period=10,
        cache="disk"
    )
 
if __name__ == "__main__":
    main()
</syntaxhighlight>
 
The parameters most commonly customized are:


* '''epochs''' - number of training epochs
https://docs.ultralytics.com/modes/train/#train-settings
* '''batch''' - number of images processed per batch
* '''imgsz''' - input image size
* '''device''' - CPU or GPU device used for training
* '''project''' and '''name''' - output directory configuration


for a comprehensive list of parameters: https://docs.ultralytics.com/modes/train?utm_source=chatgpt.com#musgd-optimizer


== Start the Training ==
== Start the Training ==

Revision as of 08:58, 25 June 2026

YOLO Training Pipeline

This guide describes how to prepare a dataset and train a custom YOLO model using annotations created with Label Studio.

Prerequisites

Before starting, ensure that:

  • Label Studio has been installed and configured
  • A dataset has been annotated and exported
  • Python 3.10 or later is available
  • Ultralytics YOLO is installed


Expected Training Directory Structure

Before starting the training process, the training directory should be organized as follows:

training/
├── dataset/
│   ├── images/
│   │   ├── train/
│   │   └── val/
│   └── labels/
│       ├── train/
│       └── val/
├── data.yaml
├── synset.txt
├── notes.json
├── train.py
├── train.sh
└── convert_pt_to_onnx.py

Where:

  • dataset/images/train contains the images used for training.
  • dataset/images/val contains the images used for validation.
  • dataset/labels/train contains the annotation files corresponding to the training images.
  • dataset/labels/val contains the annotation files corresponding to the validation images.
  • data.yaml defines the dataset configuration used by Ultralytics YOLO.
  • synset.txt contains the list of class names used during annotation.
  • notes.json is generated by Label Studio and contains additional project metadata.
  • train.py defines the YOLO training configuration and launches the training process.
  • train.sh (optional) automates dataset preparation, training, and model conversion.
  • convert_pt_to_onnx.py converts the trained PyTorch model (`best.pt`) into the ONNX format required by LogicalDOC.


The following sections describe how to create this directory structure starting from the dataset exported by Label Studio.

Populate the Training Directory

Extract the Dataset

After annotating the documents in Label Studio (see Label Studio Guide), export the dataset and extract the downloaded archive to a local directory.

The extracted archive contains:

  • `labels/` – YOLO annotation files (`.txt`)
  • `classes.txt` – class definitions
  • `notes.json` – Label Studio metadata
  • `images/` – image files (may be empty depending on the selected export format)
File:YOLO-archive-content.png
Content of the dataset exported by Label Studio

Prepare the Dataset Structure

The training pipeline expects the following dataset structure:

dataset/
├── images/
│   ├── train/
│   └── val/
├── labels/
│   ├── train/
│   └── val/
├── synset.txt
├── notes.json
└── data.yaml

The following steps describe how to transform the exported dataset into the expected structure.

Populate the Dataset

  1. Move all annotation files (`.txt`) from `labels/` to `labels/train/`.
  1. Copy the corresponding images into `images/train/`.
  1. Rename `classes.txt` to `synset.txt`.
  1. Create the empty directories:
images/val/
labels/val/

IMPORTANT

Depending on the selected export format, Label Studio may export only the annotation (`.txt`) files. In this case, the corresponding images must be copied manually from the original image directory into `images/train/`.

IMPORTANT

Verify that every image has a corresponding annotation file with the same filename.

Example:

images/train/invoice001.jpg
labels/train/invoice001.txt

If the automated training script (`train.sh`) is used, the `images/val/` and `labels/val/` directories should initially remain empty. During execution, the script automatically moves the configured percentage of images and annotation files from the training set into the validation set.

Create the data.yaml File

YOLO uses a configuration file named `data.yaml` to locate the dataset and identify the available classes.

The file specifies:

  • Training image directory
  • Validation image directory
  • Number of classes
  • Class names

Example:

path: dataset

train: images/train
val: images/val

nc: 4

names:
0: invoice_number
1: date
2: seller_name
3: total

The class definitions must match those defined during annotation.

Create the Python Training Script

Create a Python script (`train.py`) that uses the Ultralytics YOLO framework to train the model.

Training always starts from a pretrained YOLO model, such as:

  • `yolo11n.pt`
  • `yolo11s.pt`
  • `yolo11m.pt`
  • `yolo11l.pt`

The pretrained model does not need to be downloaded manually. Ultralytics automatically downloads it when the training script is executed.

A minimal training script is shown below:

from ultralytics import YOLO

model = YOLO("yolo11n.pt")

model.train(
data="data.yaml",
epochs=100
)

A more advanced script may explicitly configure additional training parameters such as the optimizer, learning rate, batch size, image size, and device selection.

The parameters most commonly customized are:

  • `epochs` – number of training epochs
  • `batch` – number of images processed per batch
  • `imgsz` – input image size
  • `device` – CPU or GPU used for training
  • `project` – output directory
  • `name` – training run name

For a complete list of supported parameters, refer to the official Ultralytics documentation:

https://docs.ultralytics.com/modes/train/#train-settings


Start the Training

During training, Ultralytics YOLO:

  • Loads the dataset
  • Trains the model
  • Evaluates the model on the validation set
  • Saves the best-performing weights


To start the training and automatically distribute the images and annotation files between the train/ and val/ directories, you can use the provided train.sh script.

Alternatively, you can manually organize the dataset by moving the desired number of images and their corresponding annotation files into the val/ directories, and then execute the train.py script directly.

To use the automated workflow, the train.sh script must be placed in the training directory. The script also invokes convert_pt_to_onnx.py to convert the trained PyTorch model (.pt) into the ONNX format required by LogicalDOC. Therefore, the `convert_pt_to_onnx.py` script must also be present in the same directory.

An example implementation of convert_pt_to_onnx.py is available in the YOLO to ONNX Conversion page.

dataset/
├── images/
│   ├── train/
│   └── val/
├── labels/
│   ├── train/
│   └── val/
├── notes.json
├── data.yaml
├── synset.txt
├── train.py
├── train.sh
└── convert-pt-to-onnx.py

This is a train.sh file you can use:

#!/bin/bash

IMAGES_TRAINING_DIR=dataset/images/train
IMAGES_VALIDATION_DIR=dataset/images/val
LABELS_TRAINING_DIR=dataset/labels/train
LABELS_VALIDATION_DIR=dataset/labels/val
VALIDATION_RATE=0.0

TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
LOG=logs/training-$TIMESTAMP.log

# Remove .npy files perhaps left by last elaboration
rm -rf dataset/images/train/*.npy
rm -rf dataset/images/val/*.npy



echo "$TIMESTAMP: Looking for unlabeled images in: $IMAGES_TRAINING_DIR" >> $LOG
for file in $IMAGES_TRAINING_DIR/*.*; do
  BASE_FILENAME="$(basename "$file")"
  BASE_FILENAME="${BASE_FILENAME%.*}"        # strip the extension

  if [ ! -f "$LABELS_TRAINING_DIR/$BASE_FILENAME.txt" ]; then
    TIMESTAMP=$(date +"%Y%m%d_%H%M%S.%3N")
    echo "$TIMESTAMP: Image $file non annotated, delete it" >> $LOG
    rm -rf $file
  fi
done

TIMESTAMP=$(date +"%Y%m%d_%H%M%S.%3N")
echo "$TIMESTAMP: Looking for unlabeled images in: $IMAGES_VALIDATION_DIR" >> $LOG
for file in $IMAGES_VALIDATION_DIR/*.*; do
  BASE_FILENAME="$(basename "$file")"
  BASE_FILENAME="${BASE_FILENAME%.*}"        # strip the extension

  if [ ! -f "$LABELS_VALIDATION_DIR/$BASE_FILENAME.txt" ]; then
    TIMESTAMP=$(date +"%Y%m%d_%H%M%S.%3N")
    echo "$TIMESTAMP: Image $file non annotated, delete it" >> $LOG
    rm -rf $file
  fi
done

echo "$TIMESTAMP: Take $VALIDATION_RATE percent of training images and move them to validation" >> $LOG
total=$(ls -1 $IMAGES_TRAINING_DIR | wc -l)
take=$(echo "$total * $VALIDATION_RATE" | bc | cut -d. -f1)
for file in $(ls -1 $IMAGES_TRAINING_DIR | shuf | head -n "$take"); do
  BASE_FILENAME="$(basename "$file")"
  BASE_FILENAME="${BASE_FILENAME%.*}"        # strip the extension

  TIMESTAMP=$(date +"%Y%m%d_%H%M%S.%3N")
  echo "$TIMESTAMP: Relocating file: $file" >> $LOG
  mv $IMAGES_TRAINING_DIR/$file  $IMAGES_VALIDATION_DIR
  mv $LABELS_TRAINING_DIR/$BASE_FILENAME.txt $LABELS_VALIDATION_DIR
done

TIMESTAMP=$(date +"%Y%m%d_%H%M%S.%3N")
echo "$TIMESTAMP: Launching the training" >> $LOG
python train.py >> $LOG  2>&1
TIMESTAMP=$(date +"%Y%m%d_%H%M%S.%3N")
echo "$TIMESTAMP: Training completed" >> $LOG


TIMESTAMP=$(date +"%Y%m%d_%H%M%S.%3N")
echo "$TIMESTAMP: Launching the conversion" >> $LOG
python convert_pt_to_onnx.py >> $LOG 2>&1
TIMESTAMP=$(date +"%Y%m%d_%H%M%S.%3N")
echo "$TIMESTAMP: Conversion completed" >> $LOG

Training Output

At the end of the training process, Ultralytics creates a runs/ directory containing the training artifacts.

Typical outputs include:

  • Training logs
  • Validation metrics
  • Loss curves
  • Confusion matrix
  • Model weights

But most importantly, the framework typically saves two checkpoint files:

best.pt
last.pt

They serve different purposes.


best.pt is the model you will usually want to use.

During training, after each epoch, the model is evaluated on the validation dataset. Ultralytics monitors a performance metric (by default, a fitness score derived from metrics such as mAP).

Whenever the model achieves a better validation score than any previous epoch, it overwrites best.pt.

Instead, last.pt always contains the model after the final training epoch, regardless of whether it achieved the best validation results.