MORTISCOPE: YOLO11 Model Training and Evaluation

Author: Mortiscope

This Jupyter Notebook serves as the core development and training environment for the object detection component of the MORTISCOPE system. The primary objective is to train a YOLO11 model to accurately detect and classify the different life stages of Chrysomya megacephala. The successful training and evaluation of this model are fundamental to the application’s ability to process images and provide accurate entomological data for PMI estimation.

Workflow Summary

This notebook follows a pipeline designed not just for training, but also for deployment and preliminary analysis of forensic imagery:

  1. Environment & Storage Initialization: Mounts Google Drive for persistent artifact storage and installs specific dependencies, including sahi for advanced inference.
  2. Dynamic Dataset Aggregation: Downloads multiple versioned datasets (varying in resolution and environmental conditions) from Roboflow and programmatically builds a unified data.yaml configuration file to prevent path errors.
  3. Training Pipeline: Configures a YOLO11-Large model with custom augmentation strategies. It features a smart resume system that automatically detects interruptions and resumes training from the last saved checkpoint in Google Drive, alongside a custom callback to archive weights for every epoch.
  4. Comprehensive Evaluation: Generates training loss plots, a normalized confusion matrix for biological stage differentiation, and detailed inference speed benchmarks.
  5. Advanced Inference Setup: Integrates SAHI (Sliced Aided Hyper Inference) to handle high-resolution field imagery to allow the detection of small insect instars that standard resizing would miss.
  6. Deployment & Demonstration: Exports the final model to ONNX format for edge deployment and creates an interactive inference engine. This engine detects scene types (Macro vs. Field) to automatically switch between standard and sliced inference modes, applies outlier filtering, and generates publication-ready visualizations.

Tech Stack

Deep Learning and Inference Engines

  • Ultralytics YOLO11: The backbone object detection architecture. This notebook specifically uses the Large (l) variant to prioritize high accuracy for subtle morphological features of insect life stages.
  • SAHI (Sliced Aided Hyper Inference): An advanced library used to perform inference on high-resolution images by slicing them into smaller overlapping windows. This is critical for detecting small instars in wide-angle “field” shots.
  • PyTorch: The underlying tensor computation framework powering YOLO11.
  • ONNX (Open Neural Network Exchange): Used to export the trained PyTorch model into a standardized format to optimize it for deployment on various hardware platforms without Python dependencies.

Data Management and Processing

  • Roboflow: Used for versioning, hosting, preprocessing, augmenting and downloading the multi-part Chrysomya megacephala dataset.
  • Google Drive: Serves as the persistent storage layer to ensure trained weights (best.pt, last.pt) and historical logs are preserved across Google Colab sessions.
  • Pandas: Used to parse and manipulate the training logs (results.csv) for custom performance plotting.
  • PyYAML: Automates the creation of the dataset configuration file, dynamically linking downloaded image paths to the model.

Visualization and Analysis

  • OpenCV (cv2): Handles image I/O, color space conversion, and drawing bounding boxes for the inference demonstration.
  • Seaborn & Matplotlib: Used to generate high-quality statistical plots, including the smoothed loss curves and the heatmap-style confusion matrix.
  • NumPy: Performs essential array operations, particularly for calculating Intersection over Union (IoU) and filtering statistical outliers in prediction areas.

Section 1: Project Initialization and Dependencies

Purpose: This section establishes the file system structure required for the project and installs the specific external libraries needed for computer vision tasks. It ensures the notebook has access to persistent storage (Google Drive) and the necessary tools for dataset management and inference.

Key Activities:

  • Drive Mounting: Connects to Google Drive to create a persistent directory. This is crucial for saving trained weights and logs so they are not lost when the Colab session disconnects.
  • Library Installation: Installs roboflow (for downloading datasets), ultralytics (for the YOLO model), and sahi (for Sliced Aided Hyper Inference, used for detecting small objects).
  • Credential Management: Securely retrieves the Roboflow API key from Colab’s secrets manager to allow authorized access to the private datasets.
import os

from google.colab import drive

# Mounts Google Drive to allow the Colab notebook to access and save files directly.
drive.mount('/content/drive')

# Defines configuration variables for the main project and the specific model folder.
root_folder = "Mortiscope Models"
model_name = "YOLOv11"

# Constructs the full, platform-independent path to the model's project directory.
project_path = os.path.join('/content/drive/MyDrive', root_folder, model_name)
# Constructs the path for a dedicated subdirectory to store model weights.
weights_path = os.path.join(project_path, 'weights')

# Creates the project and weights directories.
os.makedirs(project_path, exist_ok=True)
os.makedirs(weights_path, exist_ok=True)

# Prints the fully constructed paths to the console for user confirmation.
print(f"Project Directory: {project_path}")
print(f"Weight Storage:   {weights_path}")
Mounted at /content/drive
Project Directory: /content/drive/MyDrive/Mortiscope Models/YOLOv11
Weight Storage:   /content/drive/MyDrive/Mortiscope Models/YOLOv11/weights
# Executes the shell command to install the specified libraries using pip.
!pip install roboflow ultralytics sahi shapely

# Prints a confirmation message to the console after the installation command completes.
print("Libraries installed successfully.")
Collecting roboflow
  Downloading roboflow-1.2.11-py3-none-any.whl.metadata (9.7 kB)
Collecting ultralytics
  Downloading ultralytics-8.3.237-py3-none-any.whl.metadata (37 kB)
Collecting sahi
  Downloading sahi-0.11.36-py3-none-any.whl.metadata (19 kB)
Requirement already satisfied: shapely in /usr/local/lib/python3.12/dist-packages (2.1.2)
Requirement already satisfied: certifi in /usr/local/lib/python3.12/dist-packages (from roboflow) (2025.11.12)
Collecting idna==3.7 (from roboflow)
  Downloading idna-3.7-py3-none-any.whl.metadata (9.9 kB)
Requirement already satisfied: cycler in /usr/local/lib/python3.12/dist-packages (from roboflow) (0.12.1)
Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.12/dist-packages (from roboflow) (1.4.9)
Requirement already satisfied: matplotlib in /usr/local/lib/python3.12/dist-packages (from roboflow) (3.10.0)
Requirement already satisfied: numpy>=1.18.5 in /usr/local/lib/python3.12/dist-packages (from roboflow) (2.0.2)
Collecting opencv-python-headless==4.10.0.84 (from roboflow)
  Downloading opencv_python_headless-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (20 kB)
Requirement already satisfied: Pillow>=7.1.2 in /usr/local/lib/python3.12/dist-packages (from roboflow) (11.3.0)
Collecting pi-heif<2 (from roboflow)
  Downloading pi_heif-1.1.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (6.5 kB)
Collecting pillow-avif-plugin<2 (from roboflow)
  Downloading pillow_avif_plugin-1.5.2-cp312-cp312-manylinux_2_28_x86_64.whl.metadata (2.1 kB)
Requirement already satisfied: python-dateutil in /usr/local/lib/python3.12/dist-packages (from roboflow) (2.9.0.post0)
Requirement already satisfied: python-dotenv in /usr/local/lib/python3.12/dist-packages (from roboflow) (1.2.1)
Requirement already satisfied: requests in /usr/local/lib/python3.12/dist-packages (from roboflow) (2.32.4)
Requirement already satisfied: six in /usr/local/lib/python3.12/dist-packages (from roboflow) (1.17.0)
Requirement already satisfied: urllib3>=1.26.6 in /usr/local/lib/python3.12/dist-packages (from roboflow) (2.5.0)
Requirement already satisfied: tqdm>=4.41.0 in /usr/local/lib/python3.12/dist-packages (from roboflow) (4.67.1)
Requirement already satisfied: PyYAML>=5.3.1 in /usr/local/lib/python3.12/dist-packages (from roboflow) (6.0.3)
Requirement already satisfied: requests-toolbelt in /usr/local/lib/python3.12/dist-packages (from roboflow) (1.0.0)
Collecting filetype (from roboflow)
  Downloading filetype-1.2.0-py2.py3-none-any.whl.metadata (6.5 kB)
Requirement already satisfied: opencv-python>=4.6.0 in /usr/local/lib/python3.12/dist-packages (from ultralytics) (4.12.0.88)
Requirement already satisfied: scipy>=1.4.1 in /usr/local/lib/python3.12/dist-packages (from ultralytics) (1.16.3)
Requirement already satisfied: torch>=1.8.0 in /usr/local/lib/python3.12/dist-packages (from ultralytics) (2.9.0+cu126)
Requirement already satisfied: torchvision>=0.9.0 in /usr/local/lib/python3.12/dist-packages (from ultralytics) (0.24.0+cu126)
Requirement already satisfied: psutil>=5.8.0 in /usr/local/lib/python3.12/dist-packages (from ultralytics) (5.9.5)
Requirement already satisfied: polars>=0.20.0 in /usr/local/lib/python3.12/dist-packages (from ultralytics) (1.31.0)
Collecting ultralytics-thop>=2.0.18 (from ultralytics)
  Downloading ultralytics_thop-2.0.18-py3-none-any.whl.metadata (14 kB)
Requirement already satisfied: click in /usr/local/lib/python3.12/dist-packages (from sahi) (8.3.1)
Collecting fire (from sahi)
  Downloading fire-0.7.1-py3-none-any.whl.metadata (5.8 kB)
Collecting opencv-python>=4.6.0 (from ultralytics)
  Downloading opencv_python-4.11.0.86-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (20 kB)
Collecting pybboxes==0.1.6 (from sahi)
  Downloading pybboxes-0.1.6-py3-none-any.whl.metadata (9.9 kB)
Collecting terminaltables (from sahi)
  Downloading terminaltables-3.1.10-py2.py3-none-any.whl.metadata (3.5 kB)
Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib->roboflow) (1.3.3)
Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib->roboflow) (4.61.0)
Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib->roboflow) (25.0)
Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib->roboflow) (3.2.5)
Requirement already satisfied: charset_normalizer<4,>=2 in /usr/local/lib/python3.12/dist-packages (from requests->roboflow) (3.4.4)
Requirement already satisfied: filelock in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (3.20.0)
Requirement already satisfied: typing-extensions>=4.10.0 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (4.15.0)
Requirement already satisfied: setuptools in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (75.2.0)
Requirement already satisfied: sympy>=1.13.3 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (1.14.0)
Requirement already satisfied: networkx>=2.5.1 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (3.6.1)
Requirement already satisfied: jinja2 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (3.1.6)
Requirement already satisfied: fsspec>=0.8.5 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (2025.3.0)
Requirement already satisfied: nvidia-cuda-nvrtc-cu12==12.6.77 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (12.6.77)
Requirement already satisfied: nvidia-cuda-runtime-cu12==12.6.77 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (12.6.77)
Requirement already satisfied: nvidia-cuda-cupti-cu12==12.6.80 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (12.6.80)
Requirement already satisfied: nvidia-cudnn-cu12==9.10.2.21 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (9.10.2.21)
Requirement already satisfied: nvidia-cublas-cu12==12.6.4.1 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (12.6.4.1)
Requirement already satisfied: nvidia-cufft-cu12==11.3.0.4 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (11.3.0.4)
Requirement already satisfied: nvidia-curand-cu12==10.3.7.77 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (10.3.7.77)
Requirement already satisfied: nvidia-cusolver-cu12==11.7.1.2 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (11.7.1.2)
Requirement already satisfied: nvidia-cusparse-cu12==12.5.4.2 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (12.5.4.2)
Requirement already satisfied: nvidia-cusparselt-cu12==0.7.1 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (0.7.1)
Requirement already satisfied: nvidia-nccl-cu12==2.27.5 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (2.27.5)
Requirement already satisfied: nvidia-nvshmem-cu12==3.3.20 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (3.3.20)
Requirement already satisfied: nvidia-nvtx-cu12==12.6.77 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (12.6.77)
Requirement already satisfied: nvidia-nvjitlink-cu12==12.6.85 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (12.6.85)
Requirement already satisfied: nvidia-cufile-cu12==1.11.1.6 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (1.11.1.6)
Requirement already satisfied: triton==3.5.0 in /usr/local/lib/python3.12/dist-packages (from torch>=1.8.0->ultralytics) (3.5.0)
Requirement already satisfied: termcolor in /usr/local/lib/python3.12/dist-packages (from fire->sahi) (3.2.0)
Requirement already satisfied: mpmath<1.4,>=1.1.0 in /usr/local/lib/python3.12/dist-packages (from sympy>=1.13.3->torch>=1.8.0->ultralytics) (1.3.0)
Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.12/dist-packages (from jinja2->torch>=1.8.0->ultralytics) (3.0.3)
Downloading roboflow-1.2.11-py3-none-any.whl (89 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 89.9/89.9 kB 8.5 MB/s eta 0:00:00
Downloading idna-3.7-py3-none-any.whl (66 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 66.8/66.8 kB 6.0 MB/s eta 0:00:00
Downloading opencv_python_headless-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (49.9 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 49.9/49.9 MB 47.3 MB/s eta 0:00:00
Downloading ultralytics-8.3.237-py3-none-any.whl (1.2 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.2/1.2 MB 71.0 MB/s eta 0:00:00
Downloading sahi-0.11.36-py3-none-any.whl (111 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 111.7/111.7 kB 11.7 MB/s eta 0:00:00
Downloading pybboxes-0.1.6-py3-none-any.whl (24 kB)
Downloading opencv_python-4.11.0.86-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (63.0 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 63.0/63.0 MB 39.3 MB/s eta 0:00:00
Downloading pi_heif-1.1.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (1.4 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.4/1.4 MB 81.9 MB/s eta 0:00:00
Downloading pillow_avif_plugin-1.5.2-cp312-cp312-manylinux_2_28_x86_64.whl (4.2 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.2/4.2 MB 91.0 MB/s eta 0:00:00
Downloading ultralytics_thop-2.0.18-py3-none-any.whl (28 kB)
Downloading filetype-1.2.0-py2.py3-none-any.whl (19 kB)
Downloading fire-0.7.1-py3-none-any.whl (115 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 115.9/115.9 kB 10.8 MB/s eta 0:00:00
Downloading terminaltables-3.1.10-py2.py3-none-any.whl (15 kB)
Installing collected packages: pillow-avif-plugin, filetype, terminaltables, pybboxes, pi-heif, opencv-python-headless, opencv-python, idna, fire, ultralytics-thop, sahi, roboflow, ultralytics
  Attempting uninstall: opencv-python-headless
    Found existing installation: opencv-python-headless 4.12.0.88
    Uninstalling opencv-python-headless-4.12.0.88:
      Successfully uninstalled opencv-python-headless-4.12.0.88
  Attempting uninstall: opencv-python
    Found existing installation: opencv-python 4.12.0.88
    Uninstalling opencv-python-4.12.0.88:
      Successfully uninstalled opencv-python-4.12.0.88
  Attempting uninstall: idna
    Found existing installation: idna 3.11
    Uninstalling idna-3.11:
      Successfully uninstalled idna-3.11
Successfully installed filetype-1.2.0 fire-0.7.1 idna-3.7 opencv-python-4.11.0.86 opencv-python-headless-4.10.0.84 pi-heif-1.1.1 pillow-avif-plugin-1.5.2 pybboxes-0.1.6 roboflow-1.2.11 sahi-0.11.36 terminaltables-3.1.10 ultralytics-8.3.237 ultralytics-thop-2.0.18

Libraries installed successfully.
from google.colab import userdata
from roboflow import Roboflow

try:
    # Attempts to retrieve the 'ROBOFLOW_API_KEY' from Google Colab's secret manager.
    rf_api_key = userdata.get('ROBOFLOW_API_KEY')
    print("API Key retrieved successfully.")
except Exception as e:
    # Handles potential errors, such as the secret not being defined in the Colab environment.
    print("Error: Could not retrieve key.")
    # Re-raises the exception to halt execution if the key is essential.
    raise e

# Initializes the Roboflow client with the successfully retrieved API key.
rf = Roboflow(api_key=rf_api_key)
API Key retrieved successfully.

Section 2: Dataset Acquisition and Configuration

Purpose: To aggregate data from multiple sources and format it for the YOLOv11 training pipeline. Since the dataset is versioned across different projects (representing different resolutions and environmental conditions), this section consolidates them into a single training configuration.

Key Activities:

  • Dataset Download: Uses the Roboflow API to download specific versions of the Chrysomya megacephala datasets.
  • Dynamic YAML Generation: Instead of manually creating a configuration file, the script iterates through the downloaded folders to verify valid paths. It then programmatically generates a data.yaml file to ensure that the model only attempts to train on data that actually exists locally, preventing “path not found” errors.
# Accesses the specific Roboflow workspace that contains all the project datasets.
workspace = rf.workspace("mortiscope-fvkhd")

# Downloads version 1 of several distinct projects from the workspace.
decomposition_1 = workspace.project("decomposition-high-resolution-300").version(1).download("yolov11")
decomposition_2 = workspace.project("decomposition-high-resolution-250").version(1).download("yolov11")
decomposition_3 = workspace.project("decomposition-high-resolution-200").version(1).download("yolov11")
decomposition_4 = workspace.project("decomposition-standard-resolution-300").version(1).download("yolov11")
decomposition_5 = workspace.project("decomposition-standard-resolution-250").version(1).download("yolov11")
complementary = workspace.project("complementary").version(1).download("yolov11")

# Prints a confirmation message to the console after all download operations have successfully completed.
print("\nAll datasets downloaded successfully.")
loading Roboflow workspace...
loading Roboflow project...
loading Roboflow project...
loading Roboflow project...
loading Roboflow project...
loading Roboflow project...
loading Roboflow project...

All datasets downloaded successfully.
import yaml

# A list containing all the dataset objects that were previously downloaded.
all_datasets = [
    decomposition_1,
    decomposition_2,
    decomposition_3,
    decomposition_4,
    decomposition_5,
    complementary
]

# Initializes lists to store the file paths to the training and validation image folders.
train_paths = []
val_paths = []

print("-"*70)
print("Building Dataset Configuration")

# Iterates through each dataset to locate and collect the paths to its image directories.
for ds in all_datasets:
    # Constructs the expected paths for the 'train' and 'valid' image subdirectories.
    t_path = os.path.join(ds.location, 'train', 'images')
    v_path = os.path.join(ds.location, 'valid', 'images')

    # Verifies that the training directory actually exists before adding it to the list.
    if os.path.exists(t_path):
        train_paths.append(t_path)
        print(f"Added train: {ds.location.split('/')[-1]}")
    else:
        print(f"Skipped train (Empty): {ds.location.split('/')[-1]}")

    # Verifies that the validation directory actually exists before adding it.
    if os.path.exists(v_path):
        val_paths.append(v_path)
        print(f"Added valid: {ds.location.split('/')[-1]}")
    else:
        print(f"Skipped valid (Not found): {ds.location.split('/')[-1]}")

# Defines the master configuration dictionary in the format required by Ultralytics YOLO.
data_config = {
    'names': {
        0: 'adult',
        1: 'instar_1',
        2: 'instar_2',
        3: 'instar_3',
        4: 'pupa'
    },
    'nc': 5, # Number of classes.
    'train': train_paths,
    'val': val_paths,
}

# Defines the output path for the YAML file in the current working directory.
yaml_path = os.path.join(os.getcwd(), 'data.yaml')

# Writes the configuration dictionary to the 'data.yaml' file.
with open(yaml_path, 'w') as outfile:
    yaml.dump(data_config, outfile, default_flow_style=False)

# Prints a confirmation summary, showing the location of the file and the total number of included data folders.
print("\n" + "-"*70)
print(f"Balanced configuration created at: {yaml_path}")
print(f"Total Train Folders: {len(train_paths)}")
print(f"Total Valid Folders: {len(val_paths)}")
print("-"*70)
----------------------------------------------------------------------
Building Dataset Configuration
Added train: Decomposition-(High-Resolution---300%)-1
Added valid: Decomposition-(High-Resolution---300%)-1
Added train: Decomposition-(High-Resolution---250%)-1
Added valid: Decomposition-(High-Resolution---250%)-1
Added train: Decomposition-(High-Resolution---200%)-1
Skipped valid (Not found): Decomposition-(High-Resolution---200%)-1
Added train: Decomposition-(Standard-Resolution---300%)-1
Added valid: Decomposition-(Standard-Resolution---300%)-1
Added train: Decomposition-(Standard-Resolution---250%)-1
Added valid: Decomposition-(Standard-Resolution---250%)-1
Added train: Complementary-1
Added valid: Complementary-1
----------------------------------------------------------------------
Balanced configuration created at: /content/data.yaml
Total Train Folders: 6
Total Valid Folders: 5
----------------------------------------------------------------------

Section 3: Model Initialization and Callback Definition

Purpose: To prepare the architecture and define custom behaviors during the training process. This section ensures that training progress is saved frequently and securely.

Key Activities:

  • Custom Callback (on_train_epoch_end): A custom function is defined to run after every training epoch. It copies the model weights (last.pt and best.pt) from the temporary Colab runtime to the persistent Google Drive folder. It also creates a historical archive of weights for every epoch, allowing for granular analysis of model convergence later.
  • Model Instantiation: Downloads the base weights for YOLOv11l (Large). The large variant is specifically selected for the training in this notebook.
import shutil

# Defines and creates a dedicated directory for storing a snapshot of the model weights at the end of each training epoch.
history_path = os.path.join(weights_path, 'epoch_history')
os.makedirs(history_path, exist_ok=True)


def on_train_epoch_end(trainer):
    """
    A callback function executed at the end of each training epoch.

    This function performs the following actions:
    1. Saves a copy of the latest model weights (`last.pt`) to a historical
       archive, named with the corresponding epoch number.
    2. Updates the primary `last.pt` file in the persistent Google Drive
       weights folder, allowing for training resumption.
    3. Updates the `best.pt` file in the persistent folder whenever the trainer
       identifies a new best-performing model.

    Args:
        trainer: The Ultralytics trainer object, which provides access to the
                 current training state, including epoch number and file paths.
    """
    # Gets the current epoch number.
    current_epoch = trainer.epoch + 1

    # Defines the source paths for the weights generated by the trainer in the temporary, session-specific output directory.
    local_last = os.path.join(trainer.save_dir, 'weights', 'last.pt')
    local_best = os.path.join(trainer.save_dir, 'weights', 'best.pt')

    # Checks for the existence of the latest epoch's weights before proceeding.
    if os.path.exists(local_last):
        # Creates a unique filename for the historical weight file.
        history_filename = f"{current_epoch:03d}_epoch.pt"
        history_dest = os.path.join(history_path, history_filename)

        # Copies the latest weights to the historical archive directory.
        shutil.copy(local_last, history_dest)
        print(f"   History Saved: {history_filename}")

        # Overwrites the main 'last.pt' file in the persistent Google Drive folder.
        resume_dest = os.path.join(weights_path, 'last.pt')
        shutil.copy(local_last, resume_dest)

    # Checks if the trainer has produced a new best-performing model weight file.
    if os.path.exists(local_best):
        # Overwrites the main 'best.pt' file in the persistent Google Drive folder.
        best_dest = os.path.join(weights_path, 'best.pt')
        shutil.copy(local_best, best_dest)

# Prints a confirmation message detailing the callback's configuration and the locations where files will be saved.
print("Callback Defined: ")
print(f"   1. History saved to: {history_path}")
print(f"   2. Resume file active at: {weights_path}/last.pt")
Callback Defined: 
   1. History saved to: /content/drive/MyDrive/Mortiscope Models/YOLOv11/weights/epoch_history
   2. Resume file active at: /content/drive/MyDrive/Mortiscope Models/YOLOv11/weights/last.pt
import torch
from ultralytics import YOLO

# Defines a list of URLs for various pre-trained YOLOv11 model sizes, ranging from nano (n) to extra-large (x).
urls = [
    "https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11n.pt",
    "https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11s.pt",
    "https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11m.pt",
    "https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11l.pt",
    "https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11x.pt"
]

# Selects a specific model variant to serve as the training base.
selected_url = urls[3]
model_filename = os.path.basename(selected_url)

# Prevents re-downloading the model file if it already exists locally.
if not os.path.exists(model_filename):
    print(f"Downloading {model_filename}...")
    # Uses torch.hub to download the file from the specified URL.
    torch.hub.download_url_to_file(selected_url, model_filename)
else:
    print(f"{model_filename} found locally.")

# Instantiates the YOLO model, loading the architecture and pre-trained weights from the downloaded '.pt' file.
model = YOLO(model_filename)

# Registers the custom `on_train_epoch_end` callback function.
model.add_callback("on_train_epoch_end", on_train_epoch_end)

# Prints a summary of the model's architecture, including the number of layers, parameters, and computational complexity (GFLOPs).
print("\nModel Architecture & Complexity Base:")
model.info(detailed=True)
Creating new Ultralytics Settings v0.0.6 file ✅ 
View Ultralytics Settings with 'yolo settings' or at '/root/.config/Ultralytics/settings.json'
Update Settings with 'yolo settings key=value', i.e. 'yolo settings runs_dir=path/to/dir'. For help see https://docs.ultralytics.com/quickstart/#ultralytics-settings.
Downloading yolo11l.pt...100%|██████████| 49.0M/49.0M [00:00<00:00, 274MB/s]

YOLO11 Architecture & Complexity Base:
layer                                    name                type  gradient  parameters               shape        mu     sigma
    0                     model.0.conv.weight              Conv2d     False        1728       [64, 3, 3, 3] -0.000674     0.103        float32
    1                       model.0.bn.weight         BatchNorm2d     False          64                [64]      4.32      1.26        float32
    1                         model.0.bn.bias         BatchNorm2d     False          64                [64]    0.0947      1.59        float32
    2                             model.0.act                SiLU     False           0                  []         -         -              -
    3                     model.1.conv.weight              Conv2d     False       73728     [128, 64, 3, 3] -0.000418    0.0166        float32
    4                       model.1.bn.weight         BatchNorm2d     False         128               [128]      2.56     0.691        float32
    4                         model.1.bn.bias         BatchNorm2d     False         128               [128]      0.61      1.21        float32
    5                 model.2.cv1.conv.weight              Conv2d     False       16384    [128, 128, 1, 1]  -0.00174    0.0235        float32
    6                   model.2.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.36     0.682        float32
    6                     model.2.cv1.bn.bias         BatchNorm2d     False         128               [128]     0.269         1        float32
    7                 model.2.cv2.conv.weight              Conv2d     False       65536    [256, 256, 1, 1]   -0.0011    0.0145        float32
    8                   model.2.cv2.bn.weight         BatchNorm2d     False         256               [256]     0.792       0.2        float32
    8                     model.2.cv2.bn.bias         BatchNorm2d     False         256               [256]    -0.963     0.576        float32
    9             model.2.m.0.cv1.conv.weight              Conv2d     False        2048      [32, 64, 1, 1]   -0.0012    0.0287        float32
   10               model.2.m.0.cv1.bn.weight         BatchNorm2d     False          32                [32]     0.623     0.404        float32
   10                 model.2.m.0.cv1.bn.bias         BatchNorm2d     False          32                [32]     0.375     0.941        float32
   11             model.2.m.0.cv2.conv.weight              Conv2d     False        2048      [32, 64, 1, 1]  -0.00137    0.0292        float32
   12               model.2.m.0.cv2.bn.weight         BatchNorm2d     False          32                [32]      1.21      0.46        float32
   12                 model.2.m.0.cv2.bn.bias         BatchNorm2d     False          32                [32]     0.404     0.994        float32
   13             model.2.m.0.cv3.conv.weight              Conv2d     False        4096      [64, 64, 1, 1] -0.000487    0.0293        float32
   14               model.2.m.0.cv3.bn.weight         BatchNorm2d     False          64                [64]      1.09     0.339        float32
   14                 model.2.m.0.cv3.bn.bias         BatchNorm2d     False          64                [64]      0.32     0.715        float32
   15         model.2.m.0.m.0.cv1.conv.weight              Conv2d     False        9216      [32, 32, 3, 3] -0.000862    0.0188        float32
   16           model.2.m.0.m.0.cv1.bn.weight         BatchNorm2d     False          32                [32]      1.24      0.38        float32
   16             model.2.m.0.m.0.cv1.bn.bias         BatchNorm2d     False          32                [32]      0.87     0.612        float32
   17         model.2.m.0.m.0.cv2.conv.weight              Conv2d     False        9216      [32, 32, 3, 3] -0.000405    0.0165        float32
   18           model.2.m.0.m.0.cv2.bn.weight         BatchNorm2d     False          32                [32]     0.796     0.238        float32
   18             model.2.m.0.m.0.cv2.bn.bias         BatchNorm2d     False          32                [32]     0.608      1.11        float32
   19         model.2.m.0.m.1.cv1.conv.weight              Conv2d     False        9216      [32, 32, 3, 3] -0.000839    0.0153        float32
   20           model.2.m.0.m.1.cv1.bn.weight         BatchNorm2d     False          32                [32]      1.12     0.337        float32
   20             model.2.m.0.m.1.cv1.bn.bias         BatchNorm2d     False          32                [32]    -0.012     0.689        float32
   21         model.2.m.0.m.1.cv2.conv.weight              Conv2d     False        9216      [32, 32, 3, 3] -0.000739    0.0144        float32
   22           model.2.m.0.m.1.cv2.bn.weight         BatchNorm2d     False          32                [32]     0.775     0.295        float32
   22             model.2.m.0.m.1.cv2.bn.bias         BatchNorm2d     False          32                [32]     0.582      1.01        float32
   23             model.2.m.1.cv1.conv.weight              Conv2d     False        2048      [32, 64, 1, 1]  -0.00132    0.0239        float32
   24               model.2.m.1.cv1.bn.weight         BatchNorm2d     False          32                [32]     0.359     0.118        float32
   24                 model.2.m.1.cv1.bn.bias         BatchNorm2d     False          32                [32]     0.159     0.497        float32
   25             model.2.m.1.cv2.conv.weight              Conv2d     False        2048      [32, 64, 1, 1]  -0.00127    0.0163        float32
   26               model.2.m.1.cv2.bn.weight         BatchNorm2d     False          32                [32]      1.01     0.237        float32
   26                 model.2.m.1.cv2.bn.bias         BatchNorm2d     False          32                [32]    -0.667     0.319        float32
   27             model.2.m.1.cv3.conv.weight              Conv2d     False        4096      [64, 64, 1, 1]  -0.00126    0.0216        float32
   28               model.2.m.1.cv3.bn.weight         BatchNorm2d     False          64                [64]      1.21     0.175        float32
   28                 model.2.m.1.cv3.bn.bias         BatchNorm2d     False          64                [64]     0.187     0.471        float32
   29         model.2.m.1.m.0.cv1.conv.weight              Conv2d     False        9216      [32, 32, 3, 3] -0.000605    0.0164        float32
   30           model.2.m.1.m.0.cv1.bn.weight         BatchNorm2d     False          32                [32]      0.81     0.178        float32
   30             model.2.m.1.m.0.cv1.bn.bias         BatchNorm2d     False          32                [32]    -0.501      0.53        float32
   31         model.2.m.1.m.0.cv2.conv.weight              Conv2d     False        9216      [32, 32, 3, 3]  -0.00114    0.0157        float32
   32           model.2.m.1.m.0.cv2.bn.weight         BatchNorm2d     False          32                [32]     0.598     0.216        float32
   32             model.2.m.1.m.0.cv2.bn.bias         BatchNorm2d     False          32                [32]      0.64     0.678        float32
   33         model.2.m.1.m.1.cv1.conv.weight              Conv2d     False        9216      [32, 32, 3, 3] -0.000885    0.0148        float32
   34           model.2.m.1.m.1.cv1.bn.weight         BatchNorm2d     False          32                [32]     0.637     0.137        float32
   34             model.2.m.1.m.1.cv1.bn.bias         BatchNorm2d     False          32                [32]    -0.562     0.752        float32
   35         model.2.m.1.m.1.cv2.conv.weight              Conv2d     False        9216      [32, 32, 3, 3] -0.000312    0.0152        float32
   36           model.2.m.1.m.1.cv2.bn.weight         BatchNorm2d     False          32                [32]     0.634     0.148        float32
   36             model.2.m.1.m.1.cv2.bn.bias         BatchNorm2d     False          32                [32]      1.01     0.532        float32
   37                     model.3.conv.weight              Conv2d     False      589824    [256, 256, 3, 3] -0.000187   0.00652        float32
   38                       model.3.bn.weight         BatchNorm2d     False         256               [256]     0.717     0.225        float32
   38                         model.3.bn.bias         BatchNorm2d     False         256               [256]    -0.292     0.834        float32
   39                 model.4.cv1.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000487    0.0136        float32
   40                   model.4.cv1.bn.weight         BatchNorm2d     False         256               [256]     0.704     0.197        float32
   40                     model.4.cv1.bn.bias         BatchNorm2d     False         256               [256]    0.0744     0.633        float32
   41                 model.4.cv2.conv.weight              Conv2d     False      262144    [512, 512, 1, 1] -0.000696   0.00904        float32
   42                   model.4.cv2.bn.weight         BatchNorm2d     False         512               [512]     0.909     0.207        float32
   42                     model.4.cv2.bn.bias         BatchNorm2d     False         512               [512]    -0.906     0.522        float32
   43             model.4.m.0.cv1.conv.weight              Conv2d     False        8192     [64, 128, 1, 1]  -0.00148    0.0156        float32
   44               model.4.m.0.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.528     0.134        float32
   44                 model.4.m.0.cv1.bn.bias         BatchNorm2d     False          64                [64]     0.269     0.431        float32
   45             model.4.m.0.cv2.conv.weight              Conv2d     False        8192     [64, 128, 1, 1] -0.000493     0.013        float32
   46               model.4.m.0.cv2.bn.weight         BatchNorm2d     False          64                [64]     0.957     0.144        float32
   46                 model.4.m.0.cv2.bn.bias         BatchNorm2d     False          64                [64]    -0.133     0.292        float32
   47             model.4.m.0.cv3.conv.weight              Conv2d     False       16384    [128, 128, 1, 1]  -0.00159    0.0154        float32
   48               model.4.m.0.cv3.bn.weight         BatchNorm2d     False         128               [128]     0.798     0.151        float32
   48                 model.4.m.0.cv3.bn.bias         BatchNorm2d     False         128               [128]     -0.36     0.479        float32
   49         model.4.m.0.m.0.cv1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000601    0.0095        float32
   50           model.4.m.0.m.0.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.788     0.106        float32
   50             model.4.m.0.m.0.cv1.bn.bias         BatchNorm2d     False          64                [64]    -0.787     0.412        float32
   51         model.4.m.0.m.0.cv2.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000432   0.00908        float32
   52           model.4.m.0.m.0.cv2.bn.weight         BatchNorm2d     False          64                [64]     0.648     0.162        float32
   52             model.4.m.0.m.0.cv2.bn.bias         BatchNorm2d     False          64                [64]     0.108      0.51        float32
   53         model.4.m.0.m.1.cv1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3]  -0.00054   0.00962        float32
   54           model.4.m.0.m.1.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.846      0.13        float32
   54             model.4.m.0.m.1.cv1.bn.bias         BatchNorm2d     False          64                [64]    -0.763     0.512        float32
   55         model.4.m.0.m.1.cv2.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000171   0.00905        float32
   56           model.4.m.0.m.1.cv2.bn.weight         BatchNorm2d     False          64                [64]     0.856     0.237        float32
   56             model.4.m.0.m.1.cv2.bn.bias         BatchNorm2d     False          64                [64]     0.334     0.608        float32
   57             model.4.m.1.cv1.conv.weight              Conv2d     False        8192     [64, 128, 1, 1]  -0.00135    0.0145        float32
   58               model.4.m.1.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.546     0.166        float32
   58                 model.4.m.1.cv1.bn.bias         BatchNorm2d     False          64                [64]   -0.0734     0.671        float32
   59             model.4.m.1.cv2.conv.weight              Conv2d     False        8192     [64, 128, 1, 1]  -0.00128    0.0099        float32
   60               model.4.m.1.cv2.bn.weight         BatchNorm2d     False          64                [64]      1.21     0.164        float32
   60                 model.4.m.1.cv2.bn.bias         BatchNorm2d     False          64                [64]    -0.292     0.183        float32
   61             model.4.m.1.cv3.conv.weight              Conv2d     False       16384    [128, 128, 1, 1]  -0.00139    0.0129        float32
   62               model.4.m.1.cv3.bn.weight         BatchNorm2d     False         128               [128]      1.01     0.188        float32
   62                 model.4.m.1.cv3.bn.bias         BatchNorm2d     False         128               [128]    -0.437     0.422        float32
   63         model.4.m.1.m.0.cv1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000729   0.00872        float32
   64           model.4.m.1.m.0.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.881     0.106        float32
   64             model.4.m.1.m.0.cv1.bn.bias         BatchNorm2d     False          64                [64]    -0.877     0.483        float32
   65         model.4.m.1.m.0.cv2.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000677   0.00858        float32
   66           model.4.m.1.m.0.cv2.bn.weight         BatchNorm2d     False          64                [64]      0.76     0.173        float32
   66             model.4.m.1.m.0.cv2.bn.bias         BatchNorm2d     False          64                [64]   -0.0818     0.421        float32
   67         model.4.m.1.m.1.cv1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000673   0.00901        float32
   68           model.4.m.1.m.1.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.888     0.155        float32
   68             model.4.m.1.m.1.cv1.bn.bias         BatchNorm2d     False          64                [64]    -0.762     0.524        float32
   69         model.4.m.1.m.1.cv2.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000376   0.00865        float32
   70           model.4.m.1.m.1.cv2.bn.weight         BatchNorm2d     False          64                [64]      1.13     0.168        float32
   70             model.4.m.1.m.1.cv2.bn.bias         BatchNorm2d     False          64                [64]     0.572     0.405        float32
   71                     model.5.conv.weight              Conv2d     False  2.3593e+06    [512, 512, 3, 3] -7.32e-05   0.00375        float32
   72                       model.5.bn.weight         BatchNorm2d     False         512               [512]     0.936     0.158        float32
   72                         model.5.bn.bias         BatchNorm2d     False         512               [512]    -0.615     0.369        float32
   73                 model.6.cv1.conv.weight              Conv2d     False      262144    [512, 512, 1, 1] -0.000749   0.00793        float32
   74                   model.6.cv1.bn.weight         BatchNorm2d     False         512               [512]      1.03     0.159        float32
   74                     model.6.cv1.bn.bias         BatchNorm2d     False         512               [512]    -0.576     0.348        float32
   75                 model.6.cv2.conv.weight              Conv2d     False      524288   [512, 1024, 1, 1] -0.000449   0.00674        float32
   76                   model.6.cv2.bn.weight         BatchNorm2d     False         512               [512]      1.07     0.127        float32
   76                     model.6.cv2.bn.bias         BatchNorm2d     False         512               [512]    -0.975     0.422        float32
   77             model.6.m.0.cv1.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000742   0.00964        float32
   78               model.6.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.735     0.111        float32
   78                 model.6.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]   -0.0168     0.485        float32
   79             model.6.m.0.cv2.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000465   0.00747        float32
   80               model.6.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]       1.1    0.0892        float32
   80                 model.6.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.273     0.123        float32
   81             model.6.m.0.cv3.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000952   0.00922        float32
   82               model.6.m.0.cv3.bn.weight         BatchNorm2d     False         256               [256]      1.01     0.114        float32
   82                 model.6.m.0.cv3.bn.bias         BatchNorm2d     False         256               [256]    -0.655     0.251        float32
   83         model.6.m.0.m.0.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000425   0.00524        float32
   84           model.6.m.0.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.07     0.107        float32
   84             model.6.m.0.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.883     0.232        float32
   85         model.6.m.0.m.0.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000272   0.00531        float32
   86           model.6.m.0.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]     0.921     0.162        float32
   86             model.6.m.0.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.309     0.302        float32
   87         model.6.m.0.m.1.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000344   0.00575        float32
   88           model.6.m.0.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.05    0.0976        float32
   88             model.6.m.0.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.866     0.279        float32
   89         model.6.m.0.m.1.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000178    0.0055        float32
   90           model.6.m.0.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.25     0.196        float32
   90             model.6.m.0.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]   -0.0849      0.34        float32
   91             model.6.m.1.cv1.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000968   0.00868        float32
   92               model.6.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.861     0.103        float32
   92                 model.6.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.491     0.385        float32
   93             model.6.m.1.cv2.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000615   0.00612        float32
   94               model.6.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.19    0.0568        float32
   94                 model.6.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.252    0.0662        float32
   95             model.6.m.1.cv3.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000831   0.00796        float32
   96               model.6.m.1.cv3.bn.weight         BatchNorm2d     False         256               [256]       1.1     0.104        float32
   96                 model.6.m.1.cv3.bn.bias         BatchNorm2d     False         256               [256]    -0.678     0.186        float32
   97         model.6.m.1.m.0.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000429   0.00478        float32
   98           model.6.m.1.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.07    0.0974        float32
   98             model.6.m.1.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.796      0.18        float32
   99         model.6.m.1.m.0.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000306   0.00471        float32
  100           model.6.m.1.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]     0.951     0.122        float32
  100             model.6.m.1.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.384     0.219        float32
  101         model.6.m.1.m.1.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000326   0.00469        float32
  102           model.6.m.1.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.09     0.102        float32
  102             model.6.m.1.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.729     0.202        float32
  103         model.6.m.1.m.1.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000254   0.00457        float32
  104           model.6.m.1.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.22     0.115        float32
  104             model.6.m.1.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.121     0.186        float32
  105                     model.7.conv.weight              Conv2d     False  2.3593e+06    [512, 512, 3, 3]  -0.00012   0.00303        float32
  106                       model.7.bn.weight         BatchNorm2d     False         512               [512]      1.01      0.18        float32
  106                         model.7.bn.bias         BatchNorm2d     False         512               [512]    -0.524     0.363        float32
  107                 model.8.cv1.conv.weight              Conv2d     False      262144    [512, 512, 1, 1] -0.000465   0.00595        float32
  108                   model.8.cv1.bn.weight         BatchNorm2d     False         512               [512]      1.17     0.136        float32
  108                     model.8.cv1.bn.bias         BatchNorm2d     False         512               [512]    -0.202     0.333        float32
  109                 model.8.cv2.conv.weight              Conv2d     False      524288   [512, 1024, 1, 1] -0.000281   0.00427        float32
  110                   model.8.cv2.bn.weight         BatchNorm2d     False         512               [512]      1.07     0.204        float32
  110                     model.8.cv2.bn.bias         BatchNorm2d     False         512               [512]     0.011     0.274        float32
  111             model.8.m.0.cv1.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000617   0.00639        float32
  112               model.8.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.928     0.175        float32
  112                 model.8.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.171     0.439        float32
  113             model.8.m.0.cv2.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000247   0.00357        float32
  114               model.8.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.02    0.0405        float32
  114                 model.8.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.115    0.0497        float32
  115             model.8.m.0.cv3.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000416   0.00527        float32
  116               model.8.m.0.cv3.bn.weight         BatchNorm2d     False         256               [256]      1.04     0.122        float32
  116                 model.8.m.0.cv3.bn.bias         BatchNorm2d     False         256               [256]    -0.244     0.134        float32
  117         model.8.m.0.m.0.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000295   0.00348        float32
  118           model.8.m.0.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.15     0.108        float32
  118             model.8.m.0.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.405     0.212        float32
  119         model.8.m.0.m.0.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000182   0.00362        float32
  120           model.8.m.0.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.14     0.165        float32
  120             model.8.m.0.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.271     0.244        float32
  121         model.8.m.0.m.1.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3]   -0.0003   0.00368        float32
  122           model.8.m.0.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.16     0.131        float32
  122             model.8.m.0.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.405     0.201        float32
  123         model.8.m.0.m.1.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000136   0.00345        float32
  124           model.8.m.0.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.29     0.148        float32
  124             model.8.m.0.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.052      0.17        float32
  125             model.8.m.1.cv1.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000345   0.00426        float32
  126               model.8.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.819     0.141        float32
  126                 model.8.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    0.0294     0.275        float32
  127             model.8.m.1.cv2.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000133   0.00216        float32
  128               model.8.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]     0.977     0.023        float32
  128                 model.8.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]   -0.0632    0.0322        float32
  129             model.8.m.1.cv3.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000292   0.00339        float32
  130               model.8.m.1.cv3.bn.weight         BatchNorm2d     False         256               [256]     0.989    0.0887        float32
  130                 model.8.m.1.cv3.bn.bias         BatchNorm2d     False         256               [256]     -0.11     0.151        float32
  131         model.8.m.1.m.0.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000215   0.00219        float32
  132           model.8.m.1.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.08    0.0977        float32
  132             model.8.m.1.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]   -0.0973     0.105        float32
  133         model.8.m.1.m.0.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000123   0.00235        float32
  134           model.8.m.1.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.08     0.162        float32
  134             model.8.m.1.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.113     0.189        float32
  135         model.8.m.1.m.1.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000205   0.00237        float32
  136           model.8.m.1.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.11     0.125        float32
  136             model.8.m.1.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]     -0.15     0.145        float32
  137         model.8.m.1.m.1.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000135   0.00233        float32
  138           model.8.m.1.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.33     0.224        float32
  138             model.8.m.1.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]   -0.0434     0.155        float32
  139                 model.9.cv1.conv.weight              Conv2d     False      131072    [256, 512, 1, 1] -0.000999   0.00731        float32
  140                   model.9.cv1.bn.weight         BatchNorm2d     False         256               [256]     0.819     0.158        float32
  140                     model.9.cv1.bn.bias         BatchNorm2d     False         256               [256]      1.01     0.347        float32
  141                 model.9.cv2.conv.weight              Conv2d     False      524288   [512, 1024, 1, 1] -2.89e-05     0.005        float32
  142                   model.9.cv2.bn.weight         BatchNorm2d     False         512               [512]      1.12     0.266        float32
  142                     model.9.cv2.bn.bias         BatchNorm2d     False         512               [512]    -0.351     0.451        float32
  143                               model.9.m           MaxPool2d     False           0                  []         -         -              -
  144                model.10.cv1.conv.weight              Conv2d     False      262144    [512, 512, 1, 1] -0.000378    0.0069        float32
  145                  model.10.cv1.bn.weight         BatchNorm2d     False         512               [512]      1.39     0.293        float32
  145                    model.10.cv1.bn.bias         BatchNorm2d     False         512               [512]    0.0487     0.394        float32
  146                model.10.cv2.conv.weight              Conv2d     False      262144    [512, 512, 1, 1] -0.000395   0.00703        float32
  147                  model.10.cv2.bn.weight         BatchNorm2d     False         512               [512]     0.983     0.199        float32
  147                    model.10.cv2.bn.bias         BatchNorm2d     False         512               [512]    -0.719     0.352        float32
  148       model.10.m.0.attn.qkv.conv.weight              Conv2d     False      131072    [512, 256, 1, 1] -4.04e-05   0.00799        float32
  149         model.10.m.0.attn.qkv.bn.weight         BatchNorm2d     False         512               [512]      1.21     0.276        float32
  149           model.10.m.0.attn.qkv.bn.bias         BatchNorm2d     False         512               [512]    0.0118     0.254        float32
  150               model.10.m.0.attn.qkv.act            Identity     False           0                  []         -         -              -
  151      model.10.m.0.attn.proj.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -2.34e-05   0.00766        float32
  152        model.10.m.0.attn.proj.bn.weight         BatchNorm2d     False         256               [256]     0.544      0.27        float32
  152          model.10.m.0.attn.proj.bn.bias         BatchNorm2d     False         256               [256]   5.8e-06  4.03e-05        float32
  153              model.10.m.0.attn.proj.act            Identity     False           0                  []         -         -              -
  154        model.10.m.0.attn.pe.conv.weight              Conv2d     False        2304      [256, 1, 3, 3]  -0.00828    0.0194        float32
  155          model.10.m.0.attn.pe.bn.weight         BatchNorm2d     False         256               [256]     0.799      0.22        float32
  155            model.10.m.0.attn.pe.bn.bias         BatchNorm2d     False         256               [256]  8.28e-07  2.72e-05        float32
  156                model.10.m.0.attn.pe.act            Identity     False           0                  []         -         -              -
  157          model.10.m.0.ffn.0.conv.weight              Conv2d     False      131072    [512, 256, 1, 1] -0.000459   0.00613        float32
  158            model.10.m.0.ffn.0.bn.weight         BatchNorm2d     False         512               [512]      1.18     0.149        float32
  158              model.10.m.0.ffn.0.bn.bias         BatchNorm2d     False         512               [512]    -0.404     0.145        float32
  159          model.10.m.0.ffn.1.conv.weight              Conv2d     False      131072    [256, 512, 1, 1]  0.000274   0.00531        float32
  160            model.10.m.0.ffn.1.bn.weight         BatchNorm2d     False         256               [256]     0.701     0.164        float32
  160              model.10.m.0.ffn.1.bn.bias         BatchNorm2d     False         256               [256]  3.93e-06  3.62e-05        float32
  161                  model.10.m.0.ffn.1.act            Identity     False           0                  []         -         -              -
  162       model.10.m.1.attn.qkv.conv.weight              Conv2d     False      131072    [512, 256, 1, 1] -2.56e-05   0.00876        float32
  163         model.10.m.1.attn.qkv.bn.weight         BatchNorm2d     False         512               [512]      1.15     0.262        float32
  163           model.10.m.1.attn.qkv.bn.bias         BatchNorm2d     False         512               [512] -0.000484     0.234        float32
  164               model.10.m.1.attn.qkv.act            Identity     False           0                  []         -         -              -
  165      model.10.m.1.attn.proj.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -1.34e-05   0.00814        float32
  166        model.10.m.1.attn.proj.bn.weight         BatchNorm2d     False         256               [256]     0.984     0.182        float32
  166          model.10.m.1.attn.proj.bn.bias         BatchNorm2d     False         256               [256]   8.4e-07  1.89e-05        float32
  167              model.10.m.1.attn.proj.act            Identity     False           0                  []         -         -              -
  168        model.10.m.1.attn.pe.conv.weight              Conv2d     False        2304      [256, 1, 3, 3]  -0.00679    0.0181        float32
  169          model.10.m.1.attn.pe.bn.weight         BatchNorm2d     False         256               [256]     0.755     0.194        float32
  169            model.10.m.1.attn.pe.bn.bias         BatchNorm2d     False         256               [256]  7.72e-07  1.82e-05        float32
  170                model.10.m.1.attn.pe.act            Identity     False           0                  []         -         -              -
  171          model.10.m.1.ffn.0.conv.weight              Conv2d     False      131072    [512, 256, 1, 1] -4.46e-05   0.00512        float32
  172            model.10.m.1.ffn.0.bn.weight         BatchNorm2d     False         512               [512]      1.13     0.138        float32
  172              model.10.m.1.ffn.0.bn.bias         BatchNorm2d     False         512               [512]     -0.26     0.162        float32
  173          model.10.m.1.ffn.1.conv.weight              Conv2d     False      131072    [256, 512, 1, 1] -1.37e-05   0.00411        float32
  174            model.10.m.1.ffn.1.bn.weight         BatchNorm2d     False         256               [256]     0.838      0.17        float32
  174              model.10.m.1.ffn.1.bn.bias         BatchNorm2d     False         256               [256]   1.3e-06  1.44e-05        float32
  175                  model.10.m.1.ffn.1.act            Identity     False           0                  []         -         -              -
  176                                model.11            Upsample     False           0                  []         -         -              -
  177                                model.12              Concat     False           0                  []         -         -              -
  178                model.13.cv1.conv.weight              Conv2d     False      524288   [512, 1024, 1, 1] -0.000475   0.00751        float32
  179                  model.13.cv1.bn.weight         BatchNorm2d     False         512               [512]      1.02     0.201        float32
  179                    model.13.cv1.bn.bias         BatchNorm2d     False         512               [512]    -0.695      0.57        float32
  180                model.13.cv2.conv.weight              Conv2d     False      524288   [512, 1024, 1, 1] -0.000525   0.00674        float32
  181                  model.13.cv2.bn.weight         BatchNorm2d     False         512               [512]     0.825     0.162        float32
  181                    model.13.cv2.bn.bias         BatchNorm2d     False         512               [512]    -0.777     0.438        float32
  182            model.13.m.0.cv1.conv.weight              Conv2d     False       32768    [128, 256, 1, 1]    -0.001     0.011        float32
  183              model.13.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.831     0.174        float32
  183                model.13.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.372     0.672        float32
  184            model.13.m.0.cv2.conv.weight              Conv2d     False       32768    [128, 256, 1, 1]  -0.00105   0.00978        float32
  185              model.13.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]       1.4     0.102        float32
  185                model.13.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.443     0.243        float32
  186            model.13.m.0.cv3.conv.weight              Conv2d     False       65536    [256, 256, 1, 1]  -0.00102    0.0097        float32
  187              model.13.m.0.cv3.bn.weight         BatchNorm2d     False         256               [256]     0.911     0.125        float32
  187                model.13.m.0.cv3.bn.bias         BatchNorm2d     False         256               [256]    -0.729     0.386        float32
  188        model.13.m.0.m.0.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000426   0.00551        float32
  189          model.13.m.0.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.06     0.129        float32
  189            model.13.m.0.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.816     0.314        float32
  190        model.13.m.0.m.0.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000335   0.00522        float32
  191          model.13.m.0.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]     0.885     0.175        float32
  191            model.13.m.0.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]     -0.18     0.325        float32
  192        model.13.m.0.m.1.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000384   0.00556        float32
  193          model.13.m.0.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.997     0.146        float32
  193            model.13.m.0.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.862     0.331        float32
  194        model.13.m.0.m.1.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000155   0.00511        float32
  195          model.13.m.0.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.07      0.13        float32
  195            model.13.m.0.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]   -0.0763     0.267        float32
  196            model.13.m.1.cv1.conv.weight              Conv2d     False       32768    [128, 256, 1, 1]  -0.00102   0.00894        float32
  197              model.13.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.704     0.118        float32
  197                model.13.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.383     0.489        float32
  198            model.13.m.1.cv2.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000716   0.00631        float32
  199              model.13.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.23    0.0727        float32
  199                model.13.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.229    0.0829        float32
  200            model.13.m.1.cv3.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000836   0.00753        float32
  201              model.13.m.1.cv3.bn.weight         BatchNorm2d     False         256               [256]      0.97      0.11        float32
  201                model.13.m.1.cv3.bn.bias         BatchNorm2d     False         256               [256]    -0.589      0.26        float32
  202        model.13.m.1.m.0.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3]  -0.00043   0.00528        float32
  203          model.13.m.1.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.07     0.114        float32
  203            model.13.m.1.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.775     0.337        float32
  204        model.13.m.1.m.0.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000242   0.00489        float32
  205          model.13.m.1.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.02     0.155        float32
  205            model.13.m.1.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.188     0.306        float32
  206        model.13.m.1.m.1.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000353   0.00468        float32
  207          model.13.m.1.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.04     0.126        float32
  207            model.13.m.1.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.609     0.272        float32
  208        model.13.m.1.m.1.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000111   0.00449        float32
  209          model.13.m.1.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]       1.2     0.192        float32
  209            model.13.m.1.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]    0.0451      0.23        float32
  210                                model.14            Upsample     False           0                  []         -         -              -
  211                                model.15              Concat     False           0                  []         -         -              -
  212                model.16.cv1.conv.weight              Conv2d     False      262144   [256, 1024, 1, 1]   -0.0003    0.0084        float32
  213                  model.16.cv1.bn.weight         BatchNorm2d     False         256               [256]     0.562     0.174        float32
  213                    model.16.cv1.bn.bias         BatchNorm2d     False         256               [256]    -0.142     0.825        float32
  214                model.16.cv2.conv.weight              Conv2d     False      131072    [256, 512, 1, 1] -0.000226   0.00821        float32
  215                  model.16.cv2.bn.weight         BatchNorm2d     False         256               [256]     0.612     0.231        float32
  215                    model.16.cv2.bn.bias         BatchNorm2d     False         256               [256]    -0.282     0.753        float32
  216            model.16.m.0.cv1.conv.weight              Conv2d     False        8192     [64, 128, 1, 1]  -0.00094    0.0185        float32
  217              model.16.m.0.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.387     0.124        float32
  217                model.16.m.0.cv1.bn.bias         BatchNorm2d     False          64                [64]     0.202     0.567        float32
  218            model.16.m.0.cv2.conv.weight              Conv2d     False        8192     [64, 128, 1, 1] -9.86e-05    0.0128        float32
  219              model.16.m.0.cv2.bn.weight         BatchNorm2d     False          64                [64]      1.09     0.108        float32
  219                model.16.m.0.cv2.bn.bias         BatchNorm2d     False          64                [64]     0.166      0.31        float32
  220            model.16.m.0.cv3.conv.weight              Conv2d     False       16384    [128, 128, 1, 1]  -0.00156    0.0137        float32
  221              model.16.m.0.cv3.bn.weight         BatchNorm2d     False         128               [128]     0.692     0.126        float32
  221                model.16.m.0.cv3.bn.bias         BatchNorm2d     False         128               [128]    -0.618     0.433        float32
  222        model.16.m.0.m.0.cv1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000701      0.01        float32
  223          model.16.m.0.m.0.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.855     0.118        float32
  223            model.16.m.0.m.0.cv1.bn.bias         BatchNorm2d     False          64                [64]    -0.704     0.523        float32
  224        model.16.m.0.m.0.cv2.conv.weight              Conv2d     False       36864      [64, 64, 3, 3]  -0.00072   0.00946        float32
  225          model.16.m.0.m.0.cv2.bn.weight         BatchNorm2d     False          64                [64]     0.655     0.141        float32
  225            model.16.m.0.m.0.cv2.bn.bias         BatchNorm2d     False          64                [64]    -0.364     0.454        float32
  226        model.16.m.0.m.1.cv1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000686   0.00992        float32
  227          model.16.m.0.m.1.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.731     0.126        float32
  227            model.16.m.0.m.1.cv1.bn.bias         BatchNorm2d     False          64                [64]    -0.632     0.643        float32
  228        model.16.m.0.m.1.cv2.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000275   0.00895        float32
  229          model.16.m.0.m.1.cv2.bn.weight         BatchNorm2d     False          64                [64]      1.02     0.163        float32
  229            model.16.m.0.m.1.cv2.bn.bias         BatchNorm2d     False          64                [64]     0.541       0.5        float32
  230            model.16.m.1.cv1.conv.weight              Conv2d     False        8192     [64, 128, 1, 1]  -0.00146     0.014        float32
  231              model.16.m.1.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.349     0.125        float32
  231                model.16.m.1.cv1.bn.bias         BatchNorm2d     False          64                [64]    -0.291     0.442        float32
  232            model.16.m.1.cv2.conv.weight              Conv2d     False        8192     [64, 128, 1, 1]   -0.0008   0.00795        float32
  233              model.16.m.1.cv2.bn.weight         BatchNorm2d     False          64                [64]      1.18     0.127        float32
  233                model.16.m.1.cv2.bn.bias         BatchNorm2d     False          64                [64]    -0.205     0.296        float32
  234            model.16.m.1.cv3.conv.weight              Conv2d     False       16384    [128, 128, 1, 1] -0.000853     0.011        float32
  235              model.16.m.1.cv3.bn.weight         BatchNorm2d     False         128               [128]     0.799     0.287        float32
  235                model.16.m.1.cv3.bn.bias         BatchNorm2d     False         128               [128]    -0.275     0.436        float32
  236        model.16.m.1.m.0.cv1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000478   0.00916        float32
  237          model.16.m.1.m.0.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.866     0.179        float32
  237            model.16.m.1.m.0.cv1.bn.bias         BatchNorm2d     False          64                [64]    -0.546     0.426        float32
  238        model.16.m.1.m.0.cv2.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000416   0.00876        float32
  239          model.16.m.1.m.0.cv2.bn.weight         BatchNorm2d     False          64                [64]     0.831     0.195        float32
  239            model.16.m.1.m.0.cv2.bn.bias         BatchNorm2d     False          64                [64]    0.0191     0.538        float32
  240        model.16.m.1.m.1.cv1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -0.000616   0.00847        float32
  241          model.16.m.1.m.1.cv1.bn.weight         BatchNorm2d     False          64                [64]     0.754     0.148        float32
  241            model.16.m.1.m.1.cv1.bn.bias         BatchNorm2d     False          64                [64]    -0.627     0.394        float32
  242        model.16.m.1.m.1.cv2.conv.weight              Conv2d     False       36864      [64, 64, 3, 3]  -1.1e-05   0.00797        float32
  243          model.16.m.1.m.1.cv2.bn.weight         BatchNorm2d     False          64                [64]      1.02     0.278        float32
  243            model.16.m.1.m.1.cv2.bn.bias         BatchNorm2d     False          64                [64]      0.42     0.639        float32
  244                    model.17.conv.weight              Conv2d     False      589824    [256, 256, 3, 3] -7.72e-05   0.00304        float32
  245                      model.17.bn.weight         BatchNorm2d     False         256               [256]     0.899     0.117        float32
  245                        model.17.bn.bias         BatchNorm2d     False         256               [256]     -0.52     0.219        float32
  246                                model.18              Concat     False           0                  []         -         -              -
  247                model.19.cv1.conv.weight              Conv2d     False      393216    [512, 768, 1, 1] -0.000218   0.00488        float32
  248                  model.19.cv1.bn.weight         BatchNorm2d     False         512               [512]      1.09      0.13        float32
  248                    model.19.cv1.bn.bias         BatchNorm2d     False         512               [512]    -0.442     0.268        float32
  249                model.19.cv2.conv.weight              Conv2d     False      524288   [512, 1024, 1, 1]  -0.00017   0.00351        float32
  250                  model.19.cv2.bn.weight         BatchNorm2d     False         512               [512]      1.05     0.218        float32
  250                    model.19.cv2.bn.bias         BatchNorm2d     False         512               [512]    -0.424     0.256        float32
  251            model.19.m.0.cv1.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000699   0.00795        float32
  252              model.19.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.629     0.109        float32
  252                model.19.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.118       0.4        float32
  253            model.19.m.0.cv2.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000241   0.00453        float32
  254              model.19.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.11    0.0828        float32
  254                model.19.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.128    0.0803        float32
  255            model.19.m.0.cv3.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000476   0.00589        float32
  256              model.19.m.0.cv3.bn.weight         BatchNorm2d     False         256               [256]     0.933     0.134        float32
  256                model.19.m.0.cv3.bn.bias         BatchNorm2d     False         256               [256]    -0.317     0.225        float32
  257        model.19.m.0.m.0.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000311    0.0046        float32
  258          model.19.m.0.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.998     0.136        float32
  258            model.19.m.0.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.719     0.312        float32
  259        model.19.m.0.m.0.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000211   0.00427        float32
  260          model.19.m.0.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]     0.934     0.118        float32
  260            model.19.m.0.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.467     0.273        float32
  261        model.19.m.0.m.1.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3]  -0.00022   0.00439        float32
  262          model.19.m.0.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.01     0.116        float32
  262            model.19.m.0.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.602     0.284        float32
  263        model.19.m.0.m.1.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000101   0.00408        float32
  264          model.19.m.0.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.31     0.163        float32
  264            model.19.m.0.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.157     0.187        float32
  265            model.19.m.1.cv1.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000617   0.00645        float32
  266              model.19.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.609     0.122        float32
  266                model.19.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.251     0.282        float32
  267            model.19.m.1.cv2.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000301   0.00297        float32
  268              model.19.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.03     0.049        float32
  268                model.19.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]   -0.0907    0.0567        float32
  269            model.19.m.1.cv3.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000389   0.00453        float32
  270              model.19.m.1.cv3.bn.weight         BatchNorm2d     False         256               [256]      1.22     0.236        float32
  270                model.19.m.1.cv3.bn.bias         BatchNorm2d     False         256               [256]    -0.243     0.205        float32
  271        model.19.m.1.m.0.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000345   0.00357        float32
  272          model.19.m.1.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.05      0.15        float32
  272            model.19.m.1.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.467     0.226        float32
  273        model.19.m.1.m.0.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000202   0.00354        float32
  274          model.19.m.1.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]     0.931     0.157        float32
  274            model.19.m.1.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.326      0.29        float32
  275        model.19.m.1.m.1.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000244   0.00369        float32
  276          model.19.m.1.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.961     0.175        float32
  276            model.19.m.1.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.671     0.256        float32
  277        model.19.m.1.m.1.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -7.82e-05    0.0034        float32
  278          model.19.m.1.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.34     0.232        float32
  278            model.19.m.1.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.169     0.206        float32
  279                    model.20.conv.weight              Conv2d     False  2.3593e+06    [512, 512, 3, 3] -4.48e-05   0.00121        float32
  280                      model.20.bn.weight         BatchNorm2d     False         512               [512]      1.02    0.0701        float32
  280                        model.20.bn.bias         BatchNorm2d     False         512               [512]    -0.158    0.0632        float32
  281                                model.21              Concat     False           0                  []         -         -              -
  282                model.22.cv1.conv.weight              Conv2d     False      524288   [512, 1024, 1, 1] -0.000105   0.00276        float32
  283                  model.22.cv1.bn.weight         BatchNorm2d     False         512               [512]      1.09    0.0981        float32
  283                    model.22.cv1.bn.bias         BatchNorm2d     False         512               [512]    -0.194     0.117        float32
  284                model.22.cv2.conv.weight              Conv2d     False      524288   [512, 1024, 1, 1]  -0.00011   0.00243        float32
  285                  model.22.cv2.bn.weight         BatchNorm2d     False         512               [512]      1.08     0.164        float32
  285                    model.22.cv2.bn.bias         BatchNorm2d     False         512               [512]    -0.171     0.112        float32
  286            model.22.m.0.cv1.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000249   0.00503        float32
  287              model.22.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.777    0.0806        float32
  287                model.22.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.164     0.164        float32
  288            model.22.m.0.cv2.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -2.98e-05   0.00269        float32
  289              model.22.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.01    0.0246        float32
  289                model.22.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]   -0.0467    0.0221        float32
  290            model.22.m.0.cv3.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000221   0.00376        float32
  291              model.22.m.0.cv3.bn.weight         BatchNorm2d     False         256               [256]     0.997     0.112        float32
  291                model.22.m.0.cv3.bn.bias         BatchNorm2d     False         256               [256]     -0.15     0.103        float32
  292        model.22.m.0.m.0.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000179    0.0029        float32
  293          model.22.m.0.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.07     0.111        float32
  293            model.22.m.0.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.313     0.171        float32
  294        model.22.m.0.m.0.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000155    0.0028        float32
  295          model.22.m.0.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.07    0.0899        float32
  295            model.22.m.0.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.203     0.135        float32
  296        model.22.m.0.m.1.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000176   0.00279        float32
  297          model.22.m.0.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.06    0.0871        float32
  297            model.22.m.0.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.258     0.134        float32
  298        model.22.m.0.m.1.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -7.05e-05   0.00264        float32
  299          model.22.m.0.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]       1.2    0.0885        float32
  299            model.22.m.0.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]   -0.0735    0.0947        float32
  300            model.22.m.1.cv1.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000388   0.00411        float32
  301              model.22.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]     0.835    0.0977        float32
  301                model.22.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.129    0.0981        float32
  302            model.22.m.1.cv2.conv.weight              Conv2d     False       32768    [128, 256, 1, 1] -0.000109   0.00141        float32
  303              model.22.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]     0.997   0.00692        float32
  303                model.22.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.019     0.015        float32
  304            model.22.m.1.cv3.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000266   0.00297        float32
  305              model.22.m.1.cv3.bn.weight         BatchNorm2d     False         256               [256]      1.09    0.0701        float32
  305                model.22.m.1.cv3.bn.bias         BatchNorm2d     False         256               [256]   -0.0632    0.0509        float32
  306        model.22.m.1.m.0.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000224    0.0023        float32
  307          model.22.m.1.m.0.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.07    0.0892        float32
  307            model.22.m.1.m.0.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.168    0.0735        float32
  308        model.22.m.1.m.0.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000144   0.00233        float32
  309          model.22.m.1.m.0.cv2.bn.weight         BatchNorm2d     False         128               [128]      1.06    0.0987        float32
  309            model.22.m.1.m.0.cv2.bn.bias         BatchNorm2d     False         128               [128]     -0.12    0.0981        float32
  310        model.22.m.1.m.1.cv1.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -0.000192   0.00233        float32
  311          model.22.m.1.m.1.cv1.bn.weight         BatchNorm2d     False         128               [128]      1.06    0.0873        float32
  311            model.22.m.1.m.1.cv1.bn.bias         BatchNorm2d     False         128               [128]    -0.225    0.0799        float32
  312        model.22.m.1.m.1.cv2.conv.weight              Conv2d     False      147456    [128, 128, 3, 3] -4.32e-05   0.00219        float32
  313          model.22.m.1.m.1.cv2.bn.weight         BatchNorm2d     False         128               [128]       1.2     0.122        float32
  313            model.22.m.1.m.1.cv2.bn.bias         BatchNorm2d     False         128               [128]    -0.055    0.0658        float32
  314            model.23.cv2.0.0.conv.weight              Conv2d     False      147456     [64, 256, 3, 3] -0.000139   0.00403        float32
  315              model.23.cv2.0.0.bn.weight         BatchNorm2d     False          64                [64]      0.96     0.395        float32
  315                model.23.cv2.0.0.bn.bias         BatchNorm2d     False          64                [64]     -0.31     0.641        float32
  316            model.23.cv2.0.1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3] -9.93e-05    0.0068        float32
  317              model.23.cv2.0.1.bn.weight         BatchNorm2d     False          64                [64]      2.56     0.838        float32
  317                model.23.cv2.0.1.bn.bias         BatchNorm2d     False          64                [64]     0.687     0.424        float32
  318                 model.23.cv2.0.2.weight              Conv2d     False        4096      [64, 64, 1, 1] -7.08e-07    0.0348        float32
  318                   model.23.cv2.0.2.bias              Conv2d     False          64                [64]     0.999     0.696        float32
  319            model.23.cv2.1.0.conv.weight              Conv2d     False      294912     [64, 512, 3, 3] -6.19e-05   0.00254        float32
  320              model.23.cv2.1.0.bn.weight         BatchNorm2d     False          64                [64]      1.17      0.35        float32
  320                model.23.cv2.1.0.bn.bias         BatchNorm2d     False          64                [64]  0.000821     0.589        float32
  321            model.23.cv2.1.1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3]  9.61e-05   0.00634        float32
  322              model.23.cv2.1.1.bn.weight         BatchNorm2d     False          64                [64]      2.85     0.676        float32
  322                model.23.cv2.1.1.bn.bias         BatchNorm2d     False          64                [64]     0.882     0.419        float32
  323                 model.23.cv2.1.2.weight              Conv2d     False        4096      [64, 64, 1, 1]  6.74e-07    0.0394        float32
  323                   model.23.cv2.1.2.bias              Conv2d     False          64                [64]     0.999     0.735        float32
  324            model.23.cv2.2.0.conv.weight              Conv2d     False      294912     [64, 512, 3, 3] -7.49e-05   0.00176        float32
  325              model.23.cv2.2.0.bn.weight         BatchNorm2d     False          64                [64]      1.26     0.182        float32
  325                model.23.cv2.2.0.bn.bias         BatchNorm2d     False          64                [64]    -0.188     0.277        float32
  326            model.23.cv2.2.1.conv.weight              Conv2d     False       36864      [64, 64, 3, 3]  0.000175   0.00444        float32
  327              model.23.cv2.2.1.bn.weight         BatchNorm2d     False          64                [64]      3.28     0.476        float32
  327                model.23.cv2.2.1.bn.bias         BatchNorm2d     False          64                [64]     0.775     0.341        float32
  328                 model.23.cv2.2.2.weight              Conv2d     False        4096      [64, 64, 1, 1]    -6e-07     0.033        float32
  328                   model.23.cv2.2.2.bias              Conv2d     False          64                [64]         1     0.355        float32
  329          model.23.cv3.0.0.0.conv.weight              Conv2d     False        2304      [256, 1, 3, 3]   0.00394    0.0142        float32
  330            model.23.cv3.0.0.0.bn.weight         BatchNorm2d     False         256               [256]     0.885     0.242        float32
  330              model.23.cv3.0.0.0.bn.bias         BatchNorm2d     False         256               [256]     0.353     0.433        float32
  331          model.23.cv3.0.0.1.conv.weight              Conv2d     False       65536    [256, 256, 1, 1]  -0.00011   0.00546        float32
  332            model.23.cv3.0.0.1.bn.weight         BatchNorm2d     False         256               [256]     0.978     0.129        float32
  332              model.23.cv3.0.0.1.bn.bias         BatchNorm2d     False         256               [256]    0.0241     0.275        float32
  333          model.23.cv3.0.1.0.conv.weight              Conv2d     False        2304      [256, 1, 3, 3]   0.00299    0.0188        float32
  334            model.23.cv3.0.1.0.bn.weight         BatchNorm2d     False         256               [256]     0.984     0.375        float32
  334              model.23.cv3.0.1.0.bn.bias         BatchNorm2d     False         256               [256]     0.166     0.303        float32
  335          model.23.cv3.0.1.1.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000437   0.00619        float32
  336            model.23.cv3.0.1.1.bn.weight         BatchNorm2d     False         256               [256]      1.91      0.32        float32
  336              model.23.cv3.0.1.1.bn.bias         BatchNorm2d     False         256               [256]     0.662     0.862        float32
  337                 model.23.cv3.0.2.weight              Conv2d     False       20480     [80, 256, 1, 1]  -0.00347    0.0202        float32
  337                   model.23.cv3.0.2.bias              Conv2d     False          80                [80]     -11.8      0.66        float32
  338          model.23.cv3.1.0.0.conv.weight              Conv2d     False        4608      [512, 1, 3, 3]   0.00194   0.00986        float32
  339            model.23.cv3.1.0.0.bn.weight         BatchNorm2d     False         512               [512]     0.991     0.212        float32
  339              model.23.cv3.1.0.0.bn.bias         BatchNorm2d     False         512               [512]    0.0489     0.155        float32
  340          model.23.cv3.1.0.1.conv.weight              Conv2d     False      131072    [256, 512, 1, 1] -0.000117   0.00362        float32
  341            model.23.cv3.1.0.1.bn.weight         BatchNorm2d     False         256               [256]      1.06      0.12        float32
  341              model.23.cv3.1.0.1.bn.bias         BatchNorm2d     False         256               [256]   0.00305     0.229        float32
  342          model.23.cv3.1.1.0.conv.weight              Conv2d     False        2304      [256, 1, 3, 3]   0.00124    0.0167        float32
  343            model.23.cv3.1.1.0.bn.weight         BatchNorm2d     False         256               [256]      1.05     0.375        float32
  343              model.23.cv3.1.1.0.bn.bias         BatchNorm2d     False         256               [256]    0.0996     0.262        float32
  344          model.23.cv3.1.1.1.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000601   0.00555        float32
  345            model.23.cv3.1.1.1.bn.weight         BatchNorm2d     False         256               [256]      2.04     0.256        float32
  345              model.23.cv3.1.1.1.bn.bias         BatchNorm2d     False         256               [256]     0.721     0.779        float32
  346                 model.23.cv3.1.2.weight              Conv2d     False       20480     [80, 256, 1, 1]   -0.0038    0.0198        float32
  346                   model.23.cv3.1.2.bias              Conv2d     False          80                [80]     -10.6     0.519        float32
  347          model.23.cv3.2.0.0.conv.weight              Conv2d     False        4608      [512, 1, 3, 3]   0.00162   0.00918        float32
  348            model.23.cv3.2.0.0.bn.weight         BatchNorm2d     False         512               [512]      1.01     0.115        float32
  348              model.23.cv3.2.0.0.bn.bias         BatchNorm2d     False         512               [512]   0.00181    0.0663        float32
  349          model.23.cv3.2.0.1.conv.weight              Conv2d     False      131072    [256, 512, 1, 1] -9.03e-05    0.0028        float32
  350            model.23.cv3.2.0.1.bn.weight         BatchNorm2d     False         256               [256]      1.05    0.0586        float32
  350              model.23.cv3.2.0.1.bn.bias         BatchNorm2d     False         256               [256]    0.0015      0.12        float32
  351          model.23.cv3.2.1.0.conv.weight              Conv2d     False        2304      [256, 1, 3, 3]   0.00293    0.0147        float32
  352            model.23.cv3.2.1.0.bn.weight         BatchNorm2d     False         256               [256]      1.09     0.181        float32
  352              model.23.cv3.2.1.0.bn.bias         BatchNorm2d     False         256               [256]    0.0367     0.128        float32
  353          model.23.cv3.2.1.1.conv.weight              Conv2d     False       65536    [256, 256, 1, 1] -0.000505   0.00432        float32
  354            model.23.cv3.2.1.1.bn.weight         BatchNorm2d     False         256               [256]      1.89     0.108        float32
  354              model.23.cv3.2.1.1.bn.bias         BatchNorm2d     False         256               [256]     0.886     0.616        float32
  355                 model.23.cv3.2.2.weight              Conv2d     False       20480     [80, 256, 1, 1]  -0.00504    0.0161        float32
  355                   model.23.cv3.2.2.bias              Conv2d     False          80                [80]     -9.51     0.354        float32
  356                model.23.dfl.conv.weight              Conv2d     False          16       [1, 16, 1, 1]       7.5      4.76        float32

YOLO11l summary: 357 layers, 25,372,160 parameters, 0 gradients, 87.6 GFLOPs (357, 25372160, 0, 87.6134912)

Section 4: Training Configuration and Execution

Purpose: This is the computational core of the notebook. It defines the hyperparameters that control how the model learns and executes the training loop.

Key Activities:

  • Hyperparameter Definition: Sets critical parameters such as epochs (100), batch_size (16), and img_size (640).
  • Augmentation Strategy: Configures geometric and color-space augmentations (Mosaic, HSV shifts, Scale) to artificially increase dataset diversity and prevent overfitting.
  • Smart Resume Logic: The script checks if a training run was interrupted. If valid weights exist in Google Drive, it automatically resumes training from the last checkpoint; otherwise, it starts a new session.
  • Training Loop: Calls model.train() to begin the backpropagation process, optimizing the weights to detect the five life stages.
# A unique identifier for this specific training run, used for naming output folders.
experiment_name = 'run_v1'
# The total number of times the model will iterate over the entire training dataset.
epochs = 100
# The number of images processed in a single forward/backward pass of the model.
batch_size = 16
# The resolution (in pixels) to which all input images will be resized before training.
img_size = 640
# The number of consecutive epochs with no improvement in validation metrics before training is stopped early.
patience = 15

# The initial step size for the optimizer's weight updates.
learning_rate = 0.005
# The optimization algorithm to be used. 'auto' allows Ultralytics to select a suitable default.
optimizer_type = 'auto'

# Probability of applying the mosaic augmentation, which combines four images into one.
mosaic_probability = 1.0
# The degree of random hue shift applied in HSV color-space augmentation.
hsv_hue_fraction = 0.015
# The degree of random saturation shift applied in HSV color-space augmentation.
hsv_saturation_fraction = 0.7
# The degree of random brightness shift applied in HSV color-space augmentation.
hsv_brightness_fraction = 0.0
# The range (in degrees) of random rotation applied to images.
rotation_degrees = 0.0
# The probability of vertically flipping an image.
flip_vertical_probability = 0.0
# The probability of horizontally flipping an image.
flip_horizontal_probability = 0.0
# The gain for applying random scaling (zoom in/out) to images.
scale_gain = 0.5

# A boolean flag to force the training to start from scratch, ignoring any existing checkpoints.
force_restart = False
# The default path to the 'last.pt' checkpoint file for automatic training resumption.
auto_resume_path = os.path.join(weights_path, 'last.pt')
# An optional path to a specific weight file to resume from, overriding the auto-resume logic if set.
specific_weight_path = ""

# Prints a formatted summary of the key training and augmentation configurations for user verification.
print("-" * 40)
print("Training Configuration")
print(f"{'Experiment Name':<25} : {experiment_name}")
print(f"{'Epochs':<25} : {epochs}")
print(f"{'Batch Size':<25} : {batch_size}")
print(f"{'Image Size':<25} : {img_size}")
print(f"{'Learning Rate':<25} : {learning_rate}")
print("-" * 40)
print("Augmentation Strategy")
print(f"{'Mosaic Probability':<25} : {mosaic_probability}")
print(f"{'Hue Fraction':<25} : {hsv_hue_fraction}")
print(f"{'Saturation Fraction':<25} : {hsv_saturation_fraction}")
print(f"{'Brightness Fraction':<25} : {hsv_brightness_fraction}")
print(f"{'Rotation Degrees':<25} : {rotation_degrees}")
print(f"{'Vertical Flip Prob':<25} : {flip_vertical_probability}")
print(f"{'Horizontal Flip Prob':<25} : {flip_horizontal_probability}")
print("-" * 40)
print(f"{'Auto Resume Path':<25} : {auto_resume_path}")
----------------------------------------
Training Configuration
Experiment Name           : run_v1
Epochs                    : 100
Batch Size                : 16
Image Size                : 640
Learning Rate             : 0.005
----------------------------------------
Augmentation Strategy
Mosaic Probability        : 1.0
Hue Fraction              : 0.015
Saturation Fraction       : 0.7
Brightness Fraction       : 0.0
Rotation Degrees          : 0.0
Vertical Flip Prob        : 0.0
Horizontal Flip Prob      : 0.0
----------------------------------------
Auto Resume Path          : /content/drive/MyDrive/Mortiscope Models/YOLOv11/weights/last.pt
import time

# Checkpoint Resumption Logic

# Initializes the default training mode to start a new session.
resume_mode = False
# Sets the default weights to the pre-trained model file.
weights_to_load = model_filename

# Checks for a specific, manually provided weight file to resume from.
if specific_weight_path and os.path.exists(specific_weight_path):
    print(f"Manual override detected.\nResuming from specific weight: {specific_weight_path}")
    resume_mode = True
    weights_to_load = specific_weight_path
# If no manual override is given, checks for the default auto-resume checkpoint file.
elif os.path.exists(auto_resume_path):
    # Handles the case where a checkpoint exists but a fresh start is explicitly required.
    if force_restart:
        print(f"Previous run found at {auto_resume_path}, but 'force_restart' is True.")
        print("Starting new training...")
        resume_mode = False
    # If a checkpoint exists and a fresh start is not forced, sets up auto-resumption.
    else:
        print(f"Previous run detected.\nAuto-resuming from: {auto_resume_path}")
        resume_mode = True
        weights_to_load = auto_resume_path
# If no checkpoints are found, configures the script to start a new training session.
else:
    print("No previous run found. Starting new training...")


# Training Execution
print("\nInitializing training loop...")
# Records the timestamp at the beginning of the training process to measure total duration.
start_time = time.time()

# Executes the appropriate training command based on whether a session is being resumed.
if resume_mode:
    # When resuming, the `resume` argument is used, which automatically loads the model's state, optimizer state, and last epoch from the checkpoint.
    results = model.train(
        resume=weights_to_load,
        project=project_path,
        name=experiment_name
    )
else:
    # For a new run, all hyperparameters and augmentation settings are passed explicitly.
    results = model.train(
        # Core Parameters
        data=yaml_path,
        epochs=epochs,
        imgsz=img_size,
        batch=batch_size,
        device=0,
        patience=patience,
        # Project and Checkpointing
        save=True,
        save_period=1,
        project=project_path,
        name=experiment_name,
        exist_ok=True,
        plots=True,
        # Optimizer Settings
        lr0=learning_rate,
        optimizer=optimizer_type,
        # Augmentation Parameters
        mosaic=mosaic_probability,
        hsv_h=hsv_hue_fraction,
        hsv_s=hsv_saturation_fraction,
        hsv_v=hsv_brightness_fraction,
        degrees=rotation_degrees,
        flipud=flip_vertical_probability,
        fliplr=flip_horizontal_probability,
        scale=scale_gain
    )

# Records the timestamp at the end of the training process.
end_time = time.time()

# Calculates the total training duration and formats it into hours, minutes, and seconds.
duration_seconds = end_time - start_time
hours = int(duration_seconds // 3600)
minutes = int((duration_seconds % 3600) // 60)
seconds = int(duration_seconds % 60)

# Prints a final summary of the completed training session and its duration.
print("\n" + "-"*30)
print("Training complete.")
print(f"Total Time: {hours}h {minutes}m {seconds}s")
print("-"*30)
No previous run found. Starting new training...

Initializing training loop...

Ultralytics 8.3.237 🚀 Python-3.12.12 torch-2.9.0+cu126 CUDA:0 (NVIDIA L4, 22693MiB)
engine/trainer: agnostic_nms=False, amp=True, augment=False, auto_augment=randaugment, batch=16, bgr=0.0, box=7.5, cache=False, cfg=None, classes=None, close_mosaic=10, cls=0.5, compile=False, conf=None, copy_paste=0.0, copy_paste_mode=flip, cos_lr=False, cutmix=0.0, data=/content/data.yaml, degrees=0.0, deterministic=True, device=0, dfl=1.5, dnn=False, dropout=0.0, dynamic=False, embed=None, epochs=100, erasing=0.4, exist_ok=True, fliplr=0.0, flipud=0.0, format=torchscript, fraction=1.0, freeze=None, half=False, hsv_h=0.015, hsv_s=0.7, hsv_v=0.0, imgsz=640, int8=False, iou=0.7, keras=False, kobj=1.0, line_width=None, lr0=0.005, lrf=0.01, mask_ratio=4, max_det=300, mixup=0.0, mode=train, model=yolo11l.pt, momentum=0.937, mosaic=1.0, multi_scale=False, name=run_v1, nbs=64, nms=False, opset=None, optimize=False, optimizer=auto, overlap_mask=True, patience=15, perspective=0.0, plots=True, pose=12.0, pretrained=True, profile=False, project=/content/drive/MyDrive/Mortiscope Models/YOLOv11, rect=False, resume=False, retina_masks=False, save=True, save_conf=False, save_crop=False, save_dir=/content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1, save_frames=False, save_json=False, save_period=1, save_txt=False, scale=0.5, seed=0, shear=0.0, show=False, show_boxes=True, show_conf=True, show_labels=True, simplify=True, single_cls=False, source=None, split=val, stream_buffer=False, task=detect, time=None, tracker=botsort.yaml, translate=0.1, val=True, verbose=True, vid_stride=1, visualize=False, warmup_bias_lr=0.1, warmup_epochs=3.0, warmup_momentum=0.8, weight_decay=0.0005, workers=8, workspace=None
Downloading https://ultralytics.com/assets/Arial.ttf to '/root/.config/Ultralytics/Arial.ttf': 100% ━━━━━━━━━━━━ 755.1KB 140.6MB/s 0.0s

Overriding model.yaml nc=80 with nc=5

                   from  n    params  module                                       arguments                     
  0                  -1  1      1856  ultralytics.nn.modules.conv.Conv             [3, 64, 3, 2]                 
  1                  -1  1     73984  ultralytics.nn.modules.conv.Conv             [64, 128, 3, 2]               
  2                  -1  2    173824  ultralytics.nn.modules.block.C3k2            [128, 256, 2, True, 0.25]     
  3                  -1  1    590336  ultralytics.nn.modules.conv.Conv             [256, 256, 3, 2]              
  4                  -1  2    691712  ultralytics.nn.modules.block.C3k2            [256, 512, 2, True, 0.25]     
  5                  -1  1   2360320  ultralytics.nn.modules.conv.Conv             [512, 512, 3, 2]              
  6                  -1  2   2234368  ultralytics.nn.modules.block.C3k2            [512, 512, 2, True]           
  7                  -1  1   2360320  ultralytics.nn.modules.conv.Conv             [512, 512, 3, 2]              
  8                  -1  2   2234368  ultralytics.nn.modules.block.C3k2            [512, 512, 2, True]           
  9                  -1  1    656896  ultralytics.nn.modules.block.SPPF            [512, 512, 5]                 
 10                  -1  2   1455616  ultralytics.nn.modules.block.C2PSA           [512, 512, 2]                 
 11                  -1  1         0  torch.nn.modules.upsampling.Upsample         [None, 2, 'nearest']          
 12             [-1, 6]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 13                  -1  2   2496512  ultralytics.nn.modules.block.C3k2            [1024, 512, 2, True]          
 14                  -1  1         0  torch.nn.modules.upsampling.Upsample         [None, 2, 'nearest']          
 15             [-1, 4]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 16                  -1  2    756736  ultralytics.nn.modules.block.C3k2            [1024, 256, 2, True]          
 17                  -1  1    590336  ultralytics.nn.modules.conv.Conv             [256, 256, 3, 2]              
 18            [-1, 13]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 19                  -1  2   2365440  ultralytics.nn.modules.block.C3k2            [768, 512, 2, True]           
 20                  -1  1   2360320  ultralytics.nn.modules.conv.Conv             [512, 512, 3, 2]              
 21            [-1, 10]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 22                  -1  2   2496512  ultralytics.nn.modules.block.C3k2            [1024, 512, 2, True]          
 23        [16, 19, 22]  1   1414879  ultralytics.nn.modules.head.Detect           [5, [256, 512, 512]]          

YOLO11l summary: 357 layers, 25,314,335 parameters, 25,314,319 gradients, 87.3 GFLOPs
Transferred 1009/1015 items from pretrained weights
Freezing layer 'model.23.dfl.conv.weight'

AMP: running Automatic Mixed Precision (AMP) checks...
Downloading https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11n.pt to 'yolo11n.pt': 100% ━━━━━━━━━━━━ 5.4MB 279.5MB/s 0.0s
AMP: checks passed ✅
train: Fast image access ✅ (ping: 0.0±0.0 ms, read: 1406.1±752.1 MB/s, size: 59.0 KB)
train: Scanning /content/Complementary-1/train/labels... 14102 images, 347 backgrounds, 0 corrupt: 100% ━━━━━━━━━━━━ 14102/14102 1.5Kit/s 9.1s
train: New cache created: /content/Complementary-1/train/labels.cache
albumentations: Blur(p=0.01, blur_limit=(3, 7)), MedianBlur(p=0.01, blur_limit=(3, 7)), ToGray(p=0.01, method='weighted_average', num_output_channels=3), CLAHE(p=0.01, clip_limit=(1.0, 4.0), tile_grid_size=(8, 8))
val: Fast image access ✅ (ping: 0.0±0.0 ms, read: 630.0±305.5 MB/s, size: 44.3 KB)
val: Scanning /content/Complementary-1/valid/labels... 896 images, 36 backgrounds, 0 corrupt: 100% ━━━━━━━━━━━━ 896/896 1.2Kit/s 0.8s
val: New cache created: /content/Complementary-1/valid/labels.cache
Plotting labels to /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/labels.jpg... 
optimizer: 'optimizer=auto' found, ignoring 'lr0=0.005' and 'momentum=0.937' and determining best 'optimizer', 'lr0' and 'momentum' automatically... 
optimizer: SGD(lr=0.01, momentum=0.9) with parameter groups 167 weight(decay=0.0), 174 weight(decay=0.0005), 173 bias(decay=0.0)

Image sizes 640 train, 640 val
Using 8 dataloader workers
Logging results to /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1
Starting training for 100 epochs...

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
      1/100      10.8G      1.638      2.046      1.373         26        640: 100% ━━━━━━━━━━━━ 882/882 2.1it/s 7:01
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.0it/s 13.7s
                   all        896       2844      0.679      0.546      0.617      0.404

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
      2/100      10.4G      1.588       1.47      1.315         38        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:31
   History Saved: 002_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.5s
                   all        896       2844      0.819      0.452       0.56      0.341

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
      3/100      11.3G      1.691      1.636        1.4         14        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:27
   History Saved: 003_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.5s
                   all        896       2844      0.634      0.448      0.513      0.295

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
      4/100      10.5G      1.729      1.687      1.448         27        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 004_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.4s
                   all        896       2844      0.573      0.472      0.529      0.247

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
      5/100        11G      1.671      1.534      1.433         27        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 005_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.5s
                   all        896       2844      0.636      0.538      0.575      0.367

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
      6/100      11.1G      1.615      1.439      1.415         17        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 006_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.722      0.514      0.613       0.39

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
      7/100      11.6G      1.589      1.384      1.403         32        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 007_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.4s
                   all        896       2844      0.708      0.564      0.642      0.416

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
      8/100      11.7G      1.561      1.346      1.393         39        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 008_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.4s
                   all        896       2844      0.772      0.543      0.648      0.418

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
      9/100      10.5G      1.543      1.296      1.376         27        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 009_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.4s
                   all        896       2844      0.694      0.597       0.67      0.437

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     10/100      11.2G      1.513      1.245      1.367         45        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 010_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.698      0.589      0.653      0.433

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     11/100      11.5G      1.497      1.234       1.35         44        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 011_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.4s
                   all        896       2844      0.748      0.604      0.686       0.45

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     12/100      11.4G      1.491      1.206       1.35         16        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 012_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.739      0.589      0.686      0.453

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     13/100      10.9G       1.48      1.186      1.345          8        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 013_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844       0.72      0.596      0.677      0.456

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     14/100        11G      1.461      1.148       1.33         42        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 014_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.729      0.595      0.686       0.46

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     15/100      11.6G      1.441      1.122      1.319         44        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 015_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.702      0.604      0.681      0.453

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     16/100      10.9G      1.444      1.112      1.314         12        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 016_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.704      0.623      0.688      0.466

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     17/100      10.9G      1.428      1.097      1.308         21        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 017_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.814      0.524      0.665      0.454

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     18/100        11G      1.415       1.08      1.302         36        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 018_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.722      0.628      0.696      0.471

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     19/100      11.1G      1.413      1.067      1.303          8        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 019_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.722      0.621      0.681      0.469

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     20/100      10.6G      1.399      1.043      1.287         13        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 020_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.732      0.609      0.695      0.473

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     21/100      10.9G      1.391      1.026      1.289         17        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 021_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.708      0.638      0.682      0.471

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     22/100        11G      1.377      1.015      1.279         27        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 022_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.726      0.629      0.692      0.476

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     23/100        11G      1.369      1.006      1.275         14        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 023_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.735      0.628        0.7      0.481

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     24/100      10.4G       1.36     0.9824      1.274         19        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 024_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.692      0.639      0.703      0.484

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     25/100      10.8G      1.355     0.9721      1.268         10        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 025_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.737      0.624      0.702      0.485

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     26/100      10.9G      1.349     0.9624       1.27         17        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 026_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.709       0.61      0.692      0.479

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     27/100      10.4G      1.345     0.9616      1.266         28        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 027_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.728      0.644      0.709      0.496

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     28/100      11.1G      1.324     0.9335      1.254         13        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 028_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.691      0.669      0.712      0.492

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     29/100      10.4G      1.328     0.9364      1.257         14        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 029_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.731      0.649      0.714      0.494

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     30/100      10.4G      1.317     0.9247       1.25         11        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 030_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.743      0.646       0.71      0.491

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     31/100      10.4G      1.311     0.9075      1.252         14        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 031_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.741      0.631      0.708      0.492

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     32/100      11.1G      1.298     0.9002      1.243         29        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 032_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.727      0.634      0.709      0.492

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     33/100      10.9G      1.305     0.8992       1.24         16        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 033_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.727      0.656      0.713      0.496

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     34/100        11G       1.29     0.8879      1.229          9        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 034_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.737      0.642      0.716      0.498

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     35/100      10.5G      1.289     0.8699       1.23         16        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 035_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.738      0.649      0.722      0.503

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     36/100        11G      1.274     0.8649      1.223         34        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 036_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.753      0.635      0.714      0.495

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     37/100        11G      1.271      0.857      1.218         13        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 037_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.746      0.642      0.716        0.5

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     38/100      11.7G      1.263     0.8443      1.217         18        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 038_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.752      0.636      0.718        0.5

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     39/100      10.9G       1.25     0.8302      1.209          8        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 039_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.742      0.629      0.713      0.499

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     40/100        11G      1.247     0.8224      1.205         29        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 040_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844       0.74      0.637      0.713      0.497

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     41/100        11G      1.244     0.8125      1.207         20        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 041_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.741      0.642      0.715      0.501

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     42/100      11.1G      1.238      0.801      1.206         38        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 042_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.758       0.64      0.719      0.506

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     43/100      10.5G       1.23     0.8017      1.199         29        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 043_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.735      0.655      0.721      0.506

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     44/100      11.6G      1.219     0.7871      1.194         33        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 044_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.724      0.648      0.714      0.503

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     45/100      10.9G      1.223     0.7846      1.195         24        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 045_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.716      0.659      0.713      0.504

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     46/100        11G      1.211      0.767      1.188         11        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 046_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.737      0.643      0.714      0.502

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     47/100        11G      1.196     0.7609      1.175         11        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 047_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.721       0.65      0.714      0.503

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     48/100      11.6G      1.192     0.7408      1.179         15        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 048_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.723      0.649      0.712      0.504

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     49/100      10.5G      1.189     0.7479      1.177         10        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 049_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.716      0.649      0.711      0.502

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     50/100        11G      1.183      0.736      1.173         95        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 050_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844      0.713      0.647      0.707      0.499

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     51/100        11G      1.177     0.7291      1.169         33        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 051_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.3s
                   all        896       2844       0.71      0.652      0.707      0.497

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     52/100      11.7G      1.173     0.7256      1.165         17        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 052_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844       0.73      0.636      0.704      0.495

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     53/100        12G      1.166     0.7093      1.157         50        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 053_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.765      0.614      0.703      0.495

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     54/100      10.9G      1.159     0.7035      1.155         18        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 054_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.748      0.627      0.703      0.496

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     55/100      10.9G      1.155     0.6977      1.154         12        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 055_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.744      0.634      0.703      0.493

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     56/100      11.7G      1.146     0.6888      1.154         47        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:24
   History Saved: 056_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.755      0.627      0.702      0.493

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     57/100      10.5G      1.139     0.6815      1.152         63        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 057_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.731      0.638      0.701      0.492

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
     58/100      10.5G      1.128     0.6707      1.145         10        640: 100% ━━━━━━━━━━━━ 882/882 2.3it/s 6:25
   History Saved: 058_epoch.pt
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.7it/s 10.2s
                   all        896       2844      0.715      0.651      0.699      0.493

EarlyStopping: Training stopped early as no improvement observed in last 15 epochs. Best results observed at epoch 43, best model saved as best.pt.

To update EarlyStopping(patience=15) pass a new patience value, i.e. `patience=300` or use `patience=0` to disable EarlyStopping.

58 epochs completed in 6.458 hours.
Optimizer stripped from /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/last.pt, 51.2MB
Optimizer stripped from /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/best.pt, 51.2MB

Validating /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/best.pt...
Ultralytics 8.3.237 🚀 Python-3.12.12 torch-2.9.0+cu126 CUDA:0 (NVIDIA L4, 22693MiB)
YOLO11l summary (fused): 190 layers, 25,283,167 parameters, 0 gradients, 86.6 GFLOPs

                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 28/28 2.6it/s 10.6s
                   all        896       2844      0.735      0.655      0.721      0.507
                 adult        176        593      0.757      0.514      0.593      0.333
              instar_1        222       1164      0.743      0.451      0.641      0.354
              instar_2        168        521      0.451      0.584      0.564      0.363
              instar_3        240        334       0.73      0.793      0.846      0.666
                  pupa        205        232      0.997      0.931      0.959      0.816

Speed: 0.2ms preprocess, 7.8ms inference, 0.0ms loss, 1.7ms postprocess per image
Results saved to /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1

------------------------------
Training complete.
Total Time: 6h 28m 11s
------------------------------

Section 5: Visual Performance Evaluation

Purpose: To assess the model’s accuracy and reliability using visual metrics. Raw numbers are often insufficient; visualization helps identify specific classes or scenarios where the model struggles.

Key Activities:

  • Training Metrics Plotting: Parses the results.csv log file to generate line charts for Box Loss, Classification Loss, Precision, Recall, and mAP (Mean Average Precision). This helps verify that the model is converging and not overfitting.
  • Confusion Matrix Generation: Runs a validation pass on the best-performing model to generate a normalized Confusion Matrix. This heatmap visualizes how often the model confuses one life stage with another, providing insight into biological similarities affecting the AI.
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

# Constructs the full path to the results log file.
results_csv_path = os.path.join(project_path, experiment_name, 'results.csv')

# The number of data points to average over when applying a rolling mean.
smoothing_window_size = 5

# Sets a professional and consistent visual theme for all generated plots.
sns.set_theme(style="whitegrid", context="notebook", font_scale=1.1)
# Increases the resolution of the output figures for better clarity.
plt.rcParams['figure.dpi'] = 120

# Defines a perceptually uniform colormap to derive a consistent color palette.
color_map = plt.get_cmap('plasma')

# Assigns specific colors from the colormap to different metrics for consistency.
color_train = color_map(0.0)       # Color for training metrics.
color_val   = color_map(0.6)       # Color for validation metrics.
color_prec  = color_map(0.25)      # Color for the precision curve.
color_rec   = color_map(0.75)      # Color for the recall curve.
color_map_metric = color_map(0.5)  # Color for the mAP metric.
color_lr    = color_map(0.05)      # Color for the learning rate schedule.


def plot_training_results(csv_file_path):
    """
    Reads a results.csv file and generates a 2x3 grid of training performance plots.

    Args:
        csv_file_path (str): The full path to the results.csv file.
    """
    # Verifies the existence of the results file before attempting to read it.
    if not os.path.exists(csv_file_path):
        print(f"Error: Could not find results at {csv_file_path}")
        return

    # Reads the CSV data into a pandas DataFrame.
    df = pd.read_csv(csv_file_path)
    # Cleans up column names by removing leading/trailing whitespace.
    df.columns = df.columns.str.strip()

    # Creates a Matplotlib figure and an array of 2x3 subplots (axes).
    figure, axis_array = plt.subplots(2, 3, figsize=(18, 10))

    # Defines the mapping of DataFrame columns to their respective plot titles for the three primary loss functions.
    loss_map = [
        ('train/box_loss', 'val/box_loss', 'Box Loss'),
        ('train/cls_loss', 'val/cls_loss', 'Classification Loss'),
        ('train/dfl_loss', 'val/dfl_loss', 'Distribution Focal Loss')
    ]

    # Iterates through the loss map to generate the top row of plots.
    for i, (train_col, val_col, title) in enumerate(loss_map):
        axis = axis_array[0, i]

        # Plots the raw, noisy data with low opacity to serve as a background reference.
        sns.lineplot(data=df, x=df.index, y=train_col, ax=axis, color=color_train, alpha=0.15)
        sns.lineplot(data=df, x=df.index, y=val_col, ax=axis, color=color_val, alpha=0.15)

        # Overlays the smoothed data using a rolling mean for clearer trend visualization.
        sns.lineplot(x=df.index, y=df[train_col].rolling(smoothing_window_size).mean(),
                     ax=axis, color=color_train, linewidth=2.5, label='Train')
        sns.lineplot(x=df.index, y=df[val_col].rolling(smoothing_window_size).mean(),
                     ax=axis, color=color_val, linewidth=2.5, label='Validation')

        # Configures the title, labels, and legend for each loss plot.
        axis.set_title(title, color='#333333')
        axis.set_xlabel('Epochs')
        axis.set_ylabel('Loss Value')
        axis.legend()

    # Precision and Recall Plot
    axis_precision_recall = axis_array[1, 0]
    sns.lineplot(x=df.index, y=df['metrics/precision(B)'].rolling(smoothing_window_size).mean(),
                 ax=axis_precision_recall, color=color_prec, label='Precision')
    sns.lineplot(x=df.index, y=df['metrics/recall(B)'].rolling(smoothing_window_size).mean(),
                 ax=axis_precision_recall, color=color_rec, label='Recall')

    axis_precision_recall.set_title('Precision & Recall')
    axis_precision_recall.set_xlabel('Epochs')
    axis_precision_recall.set_ylabel('Score')
    axis_precision_recall.set_ylim(0, 1)

    # Mean Average Precision (mAP) Plot
    axis_map = axis_array[1, 1]
    sns.lineplot(x=df.index, y=df['metrics/mAP50(B)'].rolling(smoothing_window_size).mean(),
                 ax=axis_map, color=color_map_metric, linewidth=2.5, label='mAP @ 0.50')

    axis_map.set_title('Mean Average Precision (IoU=0.50)')
    axis_map.set_xlabel('Epochs')
    axis_map.set_ylabel('Score')
    axis_map.set_ylim(0, 1)
    # Fills the area under the mAP curve to visually emphasize the performance metric.
    axis_map.fill_between(df.index, df['metrics/mAP50(B)'].rolling(smoothing_window_size).mean(),
                          color=color_map_metric, alpha=0.1)

    # Learning Rate Schedule Plot
    axis_learning_rate = axis_array[1, 2]
    sns.lineplot(x=df.index, y=df['lr/pg0'], ax=axis_learning_rate, color=color_lr, linestyle='--')

    axis_learning_rate.set_title('Learning Rate Schedule')
    axis_learning_rate.set_xlabel('Epochs')
    axis_learning_rate.set_ylabel('Learning Rate')

    # Adjusts the spacing between subplots to prevent labels from overlapping.
    plt.tight_layout(
        pad=3.0,
        w_pad=4.0,
        h_pad=5.0
    )
    # Renders and displays the final, complete figure.
    plt.show()

# Executes the plotting function with the path to the results file.
plot_training_results(results_csv_path)

import numpy as np

# Defines the path to the best-performing model weights saved during training.
best_weight_path = os.path.join(project_path, experiment_name, 'weights', 'best.pt')
# Defines the output path for the final, publication-quality confusion matrix image.
output_image_path = os.path.join(project_path, experiment_name, 'confusion_matrix.png')

# Ensures that the script only runs if the best weight file exists.
if os.path.exists(best_weight_path):
    print(f"Loading weights from: {best_weight_path}")
    # Instantiates a new YOLO model object using the best saved weights.
    validation_model = YOLO(best_weight_path)

    # Runs a validation pass on the model.
    validation_metrics = validation_model.val(
        data=yaml_path,
        split='val',
        plots=True,
        device=0,
        batch=16,
        conf=0.001
    )

    # Extracts the raw confusion matrix (a NumPy array) from the results.
    raw_matrix = validation_metrics.confusion_matrix.matrix
    num_classes = 5
    # Slices the matrix to ensure it only contains the defined classes,
    # excluding any background or miscellaneous classes.
    matrix_data = raw_matrix[:num_classes, :num_classes]

    # Retrieves the class names from the validation results and formats them.
    raw_names = list(validation_metrics.names.values())[:num_classes]
    class_names = [name.replace('_', ' ').title() for name in raw_names]

    # Normalizes the confusion matrix by rows to calculate recall scores.
    row_sums = matrix_data.sum(axis=1, keepdims=True)
    # Replaces zero sums with a small number to avoid division-by-zero errors for classes that may not have appeared in the validation set.
    row_sums[row_sums == 0] = 1e-9
    matrix_normalized = matrix_data / row_sums

    # Initializes a high-resolution figure for the plot.
    plt.figure(figsize=(16, 12), dpi=300)
    sns.set_theme(style="white", font_scale=1.1)

    # Creates the heatmap using Seaborn, configuring annotations, colormap, and labels.
    axis = sns.heatmap(
        matrix_normalized,
        annot=True,                 # Displays the numerical value in each cell.
        annot_kws={"size": 14},     # Sets the font size for annotations.
        fmt='.2f',                  # Formats annotations to two decimal places.
        cmap='Blues',               # Sets the color scheme.
        xticklabels=class_names,
        yticklabels=class_names,
        vmin=0.0, vmax=1.0,         # Fixes the color bar range from 0 to 1.
        square=True,                # Enforces square cells for better proportionality.
        linewidths=2.5,
        linecolor='white',
        cbar_kws={
            'shrink': 0.6,          # Adjusts the size of the color bar.
            'pad': 0.04
        }
    )

    # Configures the color bar label to clarify that the values represent recall.
    cbar = axis.collections[0].colorbar
    cbar.set_label('Recall (Sensitivity)', labelpad=30, fontsize=14)

    # Sets the main title and axis labels with appropriate padding.
    plt.title('Confusion Matrix', fontsize=20, pad=30)
    plt.xlabel('Predicted Class', fontsize=16, labelpad=25)
    plt.ylabel('Actual Class', fontsize=16, labelpad=25)

    # Adjusts tick label appearance for clarity.
    plt.xticks(rotation=0, fontsize=13)
    plt.yticks(rotation=0, fontsize=13)

    # Adjusts subplot parameters to give a tight layout.
    plt.tight_layout(pad=5.0)

    # Saves the final figure to the specified output path.
    plt.savefig(output_image_path, dpi=300, bbox_inches='tight')
    print(f"Confusion Matrix saved to: {output_image_path}")

    # Displays the plot in the notebook output.
    plt.show()

else:
    # Prints an error message if the required 'best.pt' file is not found.
    print(f"Error: Best weights not found at {best_weight_path}")
Loading weights from: /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/best.pt

Ultralytics 8.3.237 🚀 Python-3.12.12 torch-2.9.0+cu126 CUDA:0 (NVIDIA L4, 22693MiB)
YOLO11l summary (fused): 190 layers, 25,283,167 parameters, 0 gradients, 86.6 GFLOPs
val: Fast image access ✅ (ping: 0.0±0.0 ms, read: 1413.2±529.0 MB/s, size: 34.8 KB)
val: Scanning /content/Complementary-1/valid/labels.cache... 896 images, 36 backgrounds, 0 corrupt: 100% ━━━━━━━━━━━━ 896/896 1.5Mit/s 0.0s

                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 56/56 3.5it/s 16.2s
                   all        896       2844      0.735      0.654       0.72      0.506
                 adult        176        593      0.755      0.513      0.591      0.333
              instar_1        222       1164      0.742      0.449       0.64      0.355
              instar_2        168        521      0.452      0.583      0.565      0.363
              instar_3        240        334       0.73      0.792      0.846      0.666
                  pupa        205        232      0.997      0.931      0.959      0.814

Speed: 0.9ms preprocess, 14.0ms inference, 0.0ms loss, 0.8ms postprocess per image
Results saved to /content/runs/detect/val
Confusion Matrix saved to: /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/confusion_matrix_paper.png

Section 6: Benchmarking and SAHI Integration

Purpose: To evaluate the model’s operational efficiency (speed) and prepare it for advanced inference scenarios involving high-resolution imagery.

Key Activities:

  • Speed Benchmarking: Runs a validation pass specifically to measure pre-processing, inference, and post-processing times. This calculates the estimated FPS (Frames Per Second) to determine if the model is suitable for real-time applications.
  • SAHI Wrapper Initialization: Initializes the Sliced Aided Hyper Inference wrapper. Standard YOLO resizing can make small insects vanish in 4K images. SAHI solves this by slicing the image into smaller overlapping windows, performing inference on each, and stitching the results back together.
# Defines the path to the best-performing model weights from the training run.
best_weight_path = os.path.join(project_path, experiment_name, 'weights', 'best.pt')

# Ensures the script proceeds only if the required model weight file is found.
if os.path.exists(best_weight_path):
    print(f"Loading best model for benchmarking: {best_weight_path}")
    # Loads the best model weights into a YOLO object for evaluation.
    benchmark_model = YOLO(best_weight_path)

    # Runs a validation pass on the specified dataset split.
    metrics = benchmark_model.val(data=yaml_path, split='val', plots=False, device=0)

    # Extracts the speed dictionary, which contains timing information for different stages of the inference pipeline.
    speed_metrics = metrics.speed

    # Displays a formatted summary of the average inference speed metrics.
    print("\n" + "-"*45)
    print("Inference Speed Benchmark (Average per Image)")
    print("-"*45)
    print(f"{'Pre-process':<25} : {speed_metrics['preprocess']:.2f} ms")
    print(f"{'Inference (Model)':<25} : {speed_metrics['inference']:.2f} ms")
    print(f"{'Post-process (NMS)':<25} : {speed_metrics['postprocess']:.2f} ms")
    print("-" * 45)

    # Calculates the total latency by summing the timings of all pipeline stages.
    total_latency = sum(speed_metrics.values())
    print(f"{'Total Latency':<25} : {total_latency:.2f} ms")

    # Estimates the throughput in Frames Per Second (FPS) based on the total latency.
    fps = 1000 / total_latency
    print(f"{'Estimated FPS':<25} : {fps:.2f} fps")
    print("-"*45)

else:
    # Prints an error message if the model weights file could not be located.
    print("Error: Best weights file not found.")
    print("Please make sure that the training completed successfully.")
Loading best model for benchmarking: /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/best.pt

Ultralytics 8.3.237 🚀 Python-3.12.12 torch-2.9.0+cu126 CUDA:0 (NVIDIA L4, 22693MiB)
YOLO11l summary (fused): 190 layers, 25,283,167 parameters, 0 gradients, 86.6 GFLOPs
val: Fast image access ✅ (ping: 0.0±0.0 ms, read: 1570.6±495.6 MB/s, size: 42.6 KB)
val: Scanning /content/Complementary-1/valid/labels.cache... 896 images, 36 backgrounds, 0 corrupt: 100% ━━━━━━━━━━━━ 896/896 1.6Mit/s 0.0s

                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 56/56 3.8it/s 14.7s
                   all        896       2844      0.735      0.654       0.72      0.506
                 adult        176        593      0.755      0.513      0.591      0.333
              instar_1        222       1164      0.742      0.449       0.64      0.355
              instar_2        168        521      0.452      0.583      0.565      0.363
              instar_3        240        334       0.73      0.792      0.846      0.666
                  pupa        205        232      0.997      0.931      0.959      0.814

Speed: 0.7ms preprocess, 13.6ms inference, 0.0ms loss, 0.7ms postprocess per image

---------------------------------------------
Inference Speed Benchmark (Average per Image)
---------------------------------------------
Pre-process               : 0.65 ms
Inference (Model)         : 13.60 ms
Post-process (NMS)        : 0.71 ms
---------------------------------------------
Total Latency             : 14.97 ms
Estimated FPS             : 66.82 fps
---------------------------------------------
from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction

# Defines the path to the best-performing model weights from the training run, which will be loaded into the SAHI wrapper.
best_weight_path = os.path.join(project_path, experiment_name, 'weights', 'best.pt')

# The height of each individual slice in pixels.
slice_height = 640
# The width of each individual slice in pixels.
slice_width = 640
# The percentage of overlap between adjacent slices vertically.
overlap_height_ratio = 0.2
# The percentage of overlap between adjacent slices horizontally.
overlap_width_ratio = 0.2

print(f"Initializing SAHI wrapper for: {best_weight_path}")

# Verifies that the model weight file exists before attempting to load it.
if os.path.exists(best_weight_path):
    # Initializes the SAHI AutoDetectionModel.
    detection_model = AutoDetectionModel.from_pretrained(
        model_type='yolov11',         # Specifies the model architecture.
        model_path=best_weight_path,  # Provides the path to the custom-trained weights.
        confidence_threshold=0.25,    # Sets the minimum confidence for a detection to be considered valid.
        device="cuda:0"               # Assigns the model to a specific GPU device for inference.
    )

    # Prints a confirmation message summarizing the SAHI configuration.
    print("\n" + "-"*45)
    print("SAHI Model Ready")
    print("-" * 45)
    print(f"{'Slice Dimensions':<20} : {slice_height}x{slice_width}")
    print(f"{'Overlap Ratio':<20} : {overlap_height_ratio * 100}%")
    print(f"{'Confidence Thresh':<20} : 0.25")
    print("-" * 45)

else:
    # Handles the case where the required weight file is not found.
    print(f"Error: Weights not found at {best_weight_path}")
    print("Cannot initialize SAHI.")
Initializing SAHI wrapper for: /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/best.pt

---------------------------------------------
SAHI Model Ready
---------------------------------------------
Slice Dimensions     : 640x640
Overlap Ratio        : 20.0%
Confidence Thresh    : 0.25
---------------------------------------------

Section 7: Deployment Export and Interactive Demonstration

Purpose: To finalize the model for production deployment and provide a tangible demonstration of its capabilities on user-provided data.

Key Activities:

  • ONNX Export: Converts the PyTorch model (.pt) to the ONNX (Open Neural Network Exchange) format. This format is hardware-agnostic and optimized for deployment on edge devices or web servers.
  • Interactive Inference Pipeline: A comprehensive script that:
    1. Accepts a user-uploaded image.
    2. Detects the scene type (Macro vs. Field) to choose between Standard or Sliced inference.
    3. Filters outliers based on box area to reduce false positives.
    4. Draws bounding boxes and creates a summary legend of the detected entomological evidence.
# Defines the source path for the best PyTorch model weights and the desired target path and filename for the exported ONNX model.
source_weights = os.path.join(project_path, experiment_name, 'weights', 'best.pt')
target_filename = "yolo11_mortiscope.onnx"
target_path = os.path.join(project_path, experiment_name, 'weights', target_filename)

print(f"Loading weights from: {source_weights}")

# Verifies the existence of the source weight file before initiating the export process.
if os.path.exists(source_weights):
    # Loads the trained PyTorch model from the specified '.pt' file.
    model = YOLO(source_weights)

    # Executes the model export process with specific configurations.
    exported_path = model.export(
        format='onnx',      # Specifies the target export format as ONNX.
        dynamic=False,      # Exports the model with fixed input/output dimensions for performance.
        simplify=True,      # Applies the ONNX-Simplifier to optimize the model graph.
        opset=12            # Sets the ONNX operator set version for broad compatibility.
    )

    # After export, the file is renamed and moved to the final target location.
    if isinstance(exported_path, str):
        # The `export` method saves the file with a default name.
        shutil.move(exported_path, target_path)
        print("\n" + "-"*100)
        print(f"File Saved: {target_path}")
        print("-"*100)
    else:
        # Handles cases where the export process does not return a valid file path.
        print("Export returned unexpected format.")

else:
    # Provides an error message if the source PyTorch model weights are not found.
    print(f"Error: Could not find weights at {source_weights}")
Loading weights from: /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/best.pt

Ultralytics 8.3.237 🚀 Python-3.12.12 torch-2.9.0+cu126 CPU (Intel Xeon CPU @ 2.20GHz)
YOLO11l summary (fused): 190 layers, 25,283,167 parameters, 0 gradients, 86.6 GFLOPs

PyTorch: starting from '/content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/best.pt' with input shape (1, 3, 640, 640) BCHW and output shape(s) (1, 9, 8400) (48.8 MB)
ONNX: starting export with onnx 1.19.1 opset 12...
ONNX: slimming with onnxslim 0.1.80...
ONNX: export success ✅ 3.3s, saved as '/content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/best.onnx' (96.8 MB)
Export complete (4.3s)

Results saved to /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights
Predict:         yolo predict task=detect model=/content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/best.onnx imgsz=640  
Validate:        yolo val task=detect model=/content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/best.onnx imgsz=640 data=/content/data.yaml  
Visualize:       https://netron.app

----------------------------------------------------------------------------------------------------
File Saved: /content/drive/MyDrive/Mortiscope Models/YOLOv11/run_v1/weights/yolov11_mortiscope.onnx
----------------------------------------------------------------------------------------------------
from collections import Counter, defaultdict

import cv2
import matplotlib.patches as mpatches
from google.colab import files
from sahi.prediction import ObjectPrediction

# Global Configuration

# The minimum confidence score required for a detection to be considered valid.
confidence_threshold = 0.25
# The target width in pixels for the final output visualization.
target_width = 3840
# The target height in pixels for the final output visualization.
target_height = 2160
# The resolution (Dots Per Inch) for the generated Matplotlib figure.
dpi = 100

# A standardized color palette for different insect life stages.
color_map = {
    "instar_1": "#eab308",
    "instar_2": "#84cc16",
    "instar_3": "#22c55e",
    "pupa":     "#f97316",
    "adult":    "#f43f5e"
}

# Defines the canonical order for presenting life stages in summaries and legends.
lifecycle_order = ["instar_1", "instar_2", "instar_3", "pupa", "adult"]


def hex_to_bgr(hex_color):
    """
    Converts a hexadecimal color string to a BGR tuple for use with OpenCV.

    Args:
        hex_color (str): The color in hexadecimal format (e.g., '#eab308').

    Returns:
        tuple: The color in BGR format (e.g., (8, 179, 234)).
    """
    hex_color = hex_color.lstrip('#')
    rgb = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
    # OpenCV uses BGR order, so the RGB tuple is reversed.
    return (rgb[2], rgb[1], rgb[0])


def format_class_name(name):
    """
    Formats an internal class name into a human-readable, title-cased string.

    Args:
        name (str): The internal class name (e.g., 'instar_1').

    Returns:
        str: The formatted name (e.g., 'Instar 1').
    """
    return name.replace("_", " ").title()


def calculate_iou(box1, box2):
    """
    Calculates the Intersection over Union (IoU) of two bounding boxes.

    Args:
        box1 (sahi.prediction.BBox): The first bounding box.
        box2 (sahi.prediction.BBox): The second bounding box.

    Returns:
        float: The IoU score, a value between 0.0 and 1.0.
    """
    # Extracts coordinates for easier calculation.
    b1 = [box1.minx, box1.miny, box1.maxx, box1.maxy]
    b2 = [box2.minx, box2.miny, box2.maxx, box2.maxy]

    # Determines the coordinates of the intersection rectangle.
    x1 = max(b1[0], b2[0])
    y1 = max(b1[1], b2[1])
    x2 = min(b1[2], b2[2])
    y2 = min(b1[3], b2[3])

    # Computes the area of intersection.
    intersection = max(0, x2 - x1) * max(0, y2 - y1)
    # Computes the area of both bounding boxes.
    area1 = (b1[2] - b1[0]) * (b1[3] - b1[1])
    area2 = (b2[2] - b2[0]) * (b2[3] - b2[1])
    # Computes the area of the union.
    union = area1 + area2 - intersection

    if union == 0:
        return 0
    return intersection / union


def apply_class_agnostic_nms(predictions, iou_threshold=0.6):
    """
    Applies a custom class-agnostic Non-Maximum Suppression (NMS) to a list
    of object predictions to filter out highly overlapping boxes.

    Args:
        predictions (list[ObjectPrediction]): A list of SAHI ObjectPrediction objects.
        iou_threshold (float): The IoU threshold above which boxes are suppressed.

    Returns:
        list[ObjectPrediction]: A filtered list of object predictions.
    """
    # Sorts predictions by confidence score in descending order.
    sorted_preds = sorted(predictions, key=lambda x: x.score.value, reverse=True)
    kept_preds = []

    for current in sorted_preds:
        should_keep = True
        for kept in kept_preds:
            iou = calculate_iou(current.bbox, kept.bbox)
            if iou > iou_threshold:
                # Suppresses the current box if it has a high IoU with an already kept box.
                should_keep = False
                break
        if should_keep:
            kept_preds.append(current)

    return kept_preds


def detect_scene_type(sahi_model, image_path):
    """
    Analyzes an image to determine if it is a 'macro' (close-up) or 'field'
    (wide-angle) scene.

    This heuristic is based on the average relative area of objects detected
    in an initial, low-resolution pass. Large average areas suggest a macro shot.

    Args:
        sahi_model (sahi.AutoDetectionModel): The initialized SAHI model.
        image_path (str): The path to the image file.

    Returns:
        str: The detected scene type, either 'macro' or 'field'.
    """
    native_model = sahi_model.model
    results = native_model.predict(image_path, imgsz=640, conf=0.25, verbose=False)
    boxes = results[0].boxes

    if len(boxes) == 0:
        return "field"

    # Calculates the normalized area (width * height) of each detected box.
    areas = boxes.xywhn[:, 2] * boxes.xywhn[:, 3]
    avg_area = torch.mean(areas).item()

    # Classifies the scene based on a predefined area threshold.
    if avg_area > 0.015:
        return "macro"
    else:
        return "field"


def run_image_analysis():
    """
    Orchestrates the main image analysis workflow.

    This function handles the user file upload, selects an inference strategy
    based on the scene type, processes the detections, applies filtering, and
    generates a final visual report with annotations and a summary legend.
    """
    print("Click button to upload image:")
    uploaded_files = files.upload()

    if not uploaded_files:
        print("No file uploaded.")
        return

    for filename in uploaded_files.keys():
        print(f"\nProcessing {filename}")

        # Determines the appropriate inference strategy for the uploaded image.
        scene_type = detect_scene_type(detection_model, filename)

        image_cv = cv2.imread(filename)
        img_h, img_w, _ = image_cv.shape
        img_area = img_w * img_h

        object_prediction_list = []

        # Scene-Adaptive Inference
        if scene_type == "macro":
            # For close-up images, use the standard, non-sliced prediction method.
            native_model = detection_model.model

            results = native_model.predict(
                filename,
                conf=0.45,
                imgsz=640,
                augment=False,
                agnostic_nms=True, # Uses YOLO's built-in NMS.
                verbose=False
            )

            # Manually converts the native YOLO results into the SAHI ObjectPrediction format.
            for r in results:
                for box in r.boxes:
                    x1, y1, x2, y2 = box.xyxy[0].tolist()
                    score = box.conf[0].item()
                    cls_id = int(box.cls[0].item())
                    cls_name = native_model.names[cls_id]

                    obj = ObjectPrediction(
                        bbox=[x1, y1, x2, y2],
                        category_id=cls_id,
                        category_name=cls_name,
                        score=score
                    )
                    object_prediction_list.append(obj)

            use_outlier_filter = False

        else:
            # For wide-angle images, use SAHI's sliced prediction method.
            if img_w < 2500 or img_h < 2500:
                current_slice_size = 160
                current_overlap = 0.35
            else:
                current_slice_size = 320
                current_overlap = 0.25

            result = get_sliced_prediction(
                filename,
                detection_model,
                slice_height=current_slice_size,
                slice_width=current_slice_size,
                overlap_height_ratio=current_overlap,
                overlap_width_ratio=current_overlap,
                postprocess_type="NMS",
                postprocess_match_metric="IOS",
                postprocess_match_threshold=0.5,
                postprocess_class_agnostic=True,
                verbose=1
            )
            object_prediction_list = result.object_prediction_list
            use_outlier_filter = True

        # Applies a final class-agnostic NMS pass to refine the results.
        object_prediction_list = apply_class_agnostic_nms(object_prediction_list, iou_threshold=0.6)

        class_counts = Counter()
        class_confidences = defaultdict(list)

        # Calculates the median area of all detections to use for outlier filtering.
        all_areas = []
        for pred in object_prediction_list:
            if pred.score.value >= confidence_threshold:
                bbox = pred.bbox
                area = (bbox.maxx - bbox.minx) * (bbox.maxy - bbox.miny)
                all_areas.append(area)

        median_area = np.median(all_areas) if all_areas else 0

        # Iterates through predictions to filter outliers and draw annotations.
        for prediction in object_prediction_list:
            if prediction.score.value < confidence_threshold:
                continue

            bbox = prediction.bbox
            box_area = (bbox.maxx - bbox.minx) * (bbox.maxy - bbox.miny)

            # Applies an outlier filter to remove unusually large detections, which are often false positives in field images.
            if use_outlier_filter and median_area > 0:
                coverage_ratio = box_area / img_area
                # Skip if box covers >5% of image.
                if coverage_ratio > 0.05:
                    continue
                # Skip if box is >15x median area.
                if box_area > (median_area * 15):
                    continue

            # Aggregates statistics for the final summary.
            class_name = prediction.category.name
            score = prediction.score.value
            class_counts[class_name] += 1
            class_confidences[class_name].append(score)

            # Draws the bounding box rectangle onto the image.
            color_hex = color_map.get(class_name, "#ffffff")
            color_bgr = hex_to_bgr(color_hex)
            x_min, y_min = int(bbox.minx), int(bbox.miny)
            x_max, y_max = int(bbox.maxx), int(bbox.maxy)
            cv2.rectangle(image_cv, (x_min, y_min), (x_max, y_max), color_bgr, 2)

        # Visualization and Reporting

        # Converts the OpenCV (BGR) image to RGB for Matplotlib display.
        img_rgb = cv2.cvtColor(image_cv, cv2.COLOR_BGR2RGB)
        fig_w_in, fig_h_in = target_width / dpi, target_height / dpi

        # Creates a two-panel figure: one for the image, one for the legend.
        fig, (ax_image, ax_legend) = plt.subplots(
            1, 2,
            figsize=(fig_w_in, fig_h_in),
            dpi=dpi,
            gridspec_kw={'width_ratios': [3, 1], 'wspace': 0.05}
        )

        ax_image.imshow(img_rgb)
        ax_image.axis('off')
        ax_legend.axis('off')

        # Constructs the legend handles from the aggregated detection data.
        legend_handles = []
        for class_key in lifecycle_order:
            if class_key in class_counts:
                count = class_counts[class_key]
                scores = class_confidences[class_key]
                avg_score = sum(scores) / len(scores) if scores else 0

                label_text = f"{format_class_name(class_key)}: {count}{avg_score * 100:.2f}%"
                patch = mpatches.Patch(color=color_map.get(class_key, "#000"), label=label_text)
                legend_handles.append(patch)

        # Renders the legend on the right-hand panel.
        if legend_handles:
            ax_legend.legend(
                handles=legend_handles,
                loc='center',
                title="Detection Summary",
                fontsize=24,
                title_fontsize=30,
                frameon=False,
                labelspacing=0.8
            )

        plt.tight_layout()
        plt.show()

        # Prints a final textual summary to the console.
        print("\n" + "-" * 70)
        print(f"Image report: {filename}")
        print("-" * 70)
        for class_key in lifecycle_order:
             if class_key in class_counts:
                scores = class_confidences[class_key]
                avg = sum(scores)/len(scores)
                print(f"{format_class_name(class_key):<15} | Count: {class_counts[class_key]:<5} | Avg Conf: {avg*100:.2f}%")
        print("-" * 70)

# Executes the main analysis function.
run_image_analysis()


----------------------------------------------------------------------
Image report: nvcamtest_9251_s00_00019.jpg
----------------------------------------------------------------------
Instar 2        | Count: 17    | Avg Conf: 53.61%
Instar 3        | Count: 4     | Avg Conf: 71.70%
----------------------------------------------------------------------