Pytorch multilabel classification example¶
In this page, we will show you how to run a multilabel classification experiment exploiting Pytorch and Pytorch Lightning to finetune or train from scratch a model on a custom dataset.
This example will demonstrate how to create a custom experiment starting from default settings.
Training¶
Dataset¶
Let's start with the dataset that we are going to use. Since we are using the multilabel classification datamodule we must follow a precise structure for the dataset.
dataset/
├── images
│   ├── abc.xyz
│   └── ...
├── samples.txt # optional
├── test.txt # optional
├── train.txt # optional
└── val.txt # optional
Either samples.txt or both train.txt and test.txt must be provided. If samples.txt is provided, it will be used to split the dataset into train/val/test based on the datamodule parameters. Otherwise, train.txt and val.txt will be used to split the dataset into train/val and test.txt will be used to create the test set.
The content of the files is the same for both samples.txt and train.txt/val.txt/test.txt:
images/abc.xyz,class_1,class_2
images/abc_2.xyz,class_3
So the first column is the path to the image, while the other columns are the labels associated with that image. The labels must be separated by a comma.
The standard datamodule configuration for classification is found under configs/datamodule/base/multilabel_classification.yaml.
_target_: quadra.datamodules.MultilabelClassificationDataModule
data_path: ???
images_and_labels_file: null
train_split_file: null
test_split_file: null
val_split_file: null
dataset:
  _target_: hydra.utils.get_method
  path: quadra.datasets.classification.MultilabelClassificationDataset
num_classes: null
num_workers: 8
batch_size: 64
test_batch_size: 64
seed: ${core.seed}
val_size: 0.2
test_size: 0.2
train_transform: ${transforms.train_transform}
test_transform: ${transforms.test_transform}
val_transform: ${transforms.val_transform}
class_to_idx: null
The most important parameters are:
- data_path: the path to the dataset folder
- images_and_labels_file: the path to the samples.txt file
- train_split_file: the path to the train.txt file
- test_split_file: the path to the test.txt file
- val_split_file: the path to the val.txt file
Experiment¶
Suppose that we want to run the experiment on the given dataset, we can define a config starting from the base config (found under configs/experiment/base/classification/multilabel_classification.yaml).
# @package _global_
defaults:
  - override /backbone: resnet18
  - override /datamodule: base/multilabel_classification
  - override /loss: asl
  - override /model: multilabel_classification
  - override /optimizer: adam
  - override /task: classification
  - override /scheduler: rop
  - override /transforms: default_resize
datamodule:
  num_workers: 8
  batch_size: 32
  test_batch_size: 32
print_config: true
core:
  tag: "run"
  test_after_training: true
  upload_artifacts: true
  name: multilabel-classification
logger:
  mlflow:
    experiment_name: ${core.name}
    run_name: ${core.name}
backbone:
  model:
    pretrained: True
    freeze: False
trainer:
  devices: [0]
  max_epochs: 300
  check_val_every_n_epoch: 1
The base experiment will train a resnet18 (by default pretrained on Imagenet) for 300 epochs using Adam as optimizer and reducing the learning rate on plateaus. In we give a look inside the model configuration we will find that on top of the backbone there is a simple Linear layer mapping the output of the backbone to the number of classes.
We can define a custom experiment starting from the base one, and override the parameters that we want to change. Suppose we create a yaml configuration under configs/experiment/custom_experiment/torch_multilabel_classification.yaml with the following content:
# @package _global_
defaults:
  - base/classification/multilabel_classification
  - override /backbone: vit16_tiny
  - _self_
datamodule:
  num_workers: 12
  batch_size: 32
  data_path: path/to/experiment/dataset
  images_and_labels_file: ${datamodule.data_path}/samples.txt # We make use of hydra variable interpolation
  class_to_idx:
    class_1: 0
    class_2: 1
    class_3: 2
model:
  classifier:
    out_features: 3 # This is very important as it defines the number of classes
task:
  run_test: True # Perform test evaluation at the end of training
  report: False 
  output:
    example: False 
logger:
  mlflow:
    experiment_name: name_of_the_experiment
    run_name: ${core.name}
Warning
At the current time the report generation is not supported for multilabel classification.
Run¶
Assuming that you have created a virtual environment and installed the quadra library, you can run the experiment by running the following command:
quadra experiment=custom_experiment/torch_multilabel_classification
This should produce the following output files:
checkpoints  config_resolved.yaml  config_tree.txt  data  deployment_model  main.log
Where checkpoints contains the pytorch lightning checkpoints of the model, data contains the joblib dump of the datamodule with its parameters and dataset split, deployment_model contains the model in exported format (default is torchscript).