Skip to main content

Hierarchical Multi-Label Classification Network in Pytorch

Project description

HMC Torch

Hierarchical Multi-Label Classification (HMC) network implemented in PyTorch.

Supports two classification strategies — global (single model for all labels) and local (one model per hierarchy level) — with optional hyperparameter optimization via Optuna.


Table of Contents


Overview

HMC problems involve predicting labels that are organized in a hierarchy (e.g., Gene Ontology). This project benchmarks two approaches:

Method Description
global C-HMCNN: single MLP constrained by a hierarchy matrix (R-matrix)
global_baseline Same model without hierarchical constraint enforcement
local One MLP per hierarchy level, trained jointly with early stopping
local_test Local model in inference-only mode

Project Structure

hmc-torch/
├── src/hmc/
│   ├── arguments.py                   # Args dataclass + argparse CLI (parse_args)
│   ├── main.py                        # Entry point — routes to global or local pipeline
│   ├── env.py                         # Environment variables
│   │
│   ├── datasets/
│   │   ├── dataset_torch.py           # PyTorch dataset wrapper
│   │   ├── gofun/
│   │   │   └── dataset_arff.py        # ARFF file loader (Gene Ontology / FUN)
│   │   └── manager/
│   │       └── dataset_manager.py     # initialize_dataset_experiments — main loader entry
│   │
│   ├── models/
│   │   ├── base.py                    # Base model class
│   │   ├── global_classifier/
│   │   │   └── constraint/
│   │   │       ├── model.py           # ConstrainedModel, ConstrainedLightningModel
│   │   │       └── utils.py           # get_constr_out — applies R-matrix constraint
│   │   └── local_classifier/
│   │       ├── baseline/
│   │       │   └── model.py           # HMCLocalModel — per-level MLP ensemble
│   │       └── networks.py            # Shared network building blocks
│   │
│   ├── pipeline/
│   │   ├── global_classifier/
│   │   │   ├── main.py                # train_global() — setup, data loading, fit
│   │   │   └── core/
│   │   │       └── train.py           # train_step, test_step, get_local_scores
│   │   └── local_classifier/
│   │       ├── main.py                # main_local(), train_local(), test_local()
│   │       ├── core/
│   │       │   ├── train.py           # train_step — progressive level training
│   │       │   ├── validate.py        # validate_step — per-level metrics + early stopping
│   │       │   └── test.py            # test_step — threshold search + final scores
│   │       └── hpo/
│   │           └── hpo_local.py       # optimize_hyperparameters — Optuna study per level
│   │
│   └── utils/
│       ├── dataset/
│       │   ├── labels.py              # Label conversion (local↔global), binarization
│       │   └── convert_hpo_json.py    # HPO result format conversion
│       ├── metrics/
│       │   └── calculate_metrics.py   # precision, recall, f1, avg precision
│       ├── path/
│       │   ├── files.py               # create_dir
│       │   └── output.py              # save_dict_to_json
│       ├── predict/
│       │   └── metrics.py
│       └── train/
│           ├── early_stopping.py      # check_early_stopping_normalized, check_loss
│           ├── job.py                 # create_job_id_name, timers, threshold search
│           └── losses.py              # compute_loss, focal loss, hierarchical loss
│
├── tests/
│   ├── conftest.py
│   └── train_global_test.py           # Integration test for global pipeline
│
├── config.yaml                        # HPO-tuned hyperparameters per dataset
├── run.sh                             # Main training script (reads config.yaml via yq)
├── run.ps1                            # Windows equivalent
├── Makefile                           # lint, test, build targets
├── pyproject.toml                     # Project metadata and dependencies (uv)
└── uv.lock                            # Locked dependency tree

Installation

The project uses uv for dependency management.

# Install uv (if not already installed)
pip install uv

# Install all dependencies including dev tools
uv sync --all-groups

Set the Python path before running:

export PYTHONPATH=src

Datasets

Datasets follow the naming convention {data}_{ontology}, e.g. seq_FUN, expr_GO.

Supported datasets:

Group Datasets
FUN / GO cellcycle, derisi, eisen, expr, gasch1, gasch2, seq, spo
Others diatoms, enron, imclef07a, imclef07d

Download from Kaggle:

pip install kaggle
kaggle datasets download brunosette/gene-ontology-original
mkdir -p data
unzip gene-ontology-original.zip -d data/

Or via curl:

curl -L -u $KAGGLE_USERNAME:$KAGGLE_KEY \
  -o gene-ontology-original.zip \
  https://www.kaggle.com/api/v1/datasets/download/brunosette/gene-ontology-original
mkdir -p data && unzip gene-ontology-original.zip -d data/

Running

Using run.sh

The script reads per-dataset hyperparameters from config.yaml automatically.

chmod +x run.sh

# Train local classifier on a single dataset (CPU)
./run.sh --dataset_name seq_FUN --method local --device cpu

# Train on all datasets
./run.sh --dataset_name all --method local --device cuda

# Train global classifier
./run.sh --dataset_name seq_FUN --method global --device cuda

Common options:

Option Default Description
--dataset_name seq_FUN Dataset name or all
--method local local, local_test, global, global_baseline
--device cpu cpu or cuda
--epochs 4000 Training epochs
--hpo false Enable Optuna HPO (true/false)
--n_trials 30 HPO trials per level
--output_path ./results Where to save models and scores
--epochs_to_evaluate 20 Validation frequency
--warmup false Progressive level activation

Direct Python invocation

python -m hmc.main \
  --dataset_path ./data \
  --output_path ./results \
  --dataset_name seq_FUN \
  --method local \
  --device cpu \
  --epochs 2000 \
  --lr_values 0.001 0.0001 0.0005 0.001 0.0002 0.00005 \
  --dropout_values 0.3 0.4 0.5 0.3 0.4 0.5 \
  --hidden_dims "[[512],[256],[128],[256],[128],[64]]" \
  --num_layers_values 1 1 1 1 1 2 \
  --weight_decay_values 1e-4 1e-4 1e-4 1e-4 1e-4 1e-4

Using make

make run    # runs run.sh with default settings (seq_FUN, local, cuda)
make test   # runs pytest with coverage
make lint   # autopep8 + black + ruff + isort + pylint

Configuration

config.yaml stores HPO-tuned hyperparameters for each dataset. run.sh reads these values using yq and passes them to the CLI.

To add a new dataset, append a new entry to config.yaml:

datasets_params:
  my_dataset_FUN:
    hidden_dims: [[256], [128], [64]]
    lr_values: [0.001, 0.0005, 0.0002]
    dropout_values: [0.3, 0.4, 0.5]
    num_layers_values: [1, 1, 1]
    weight_decay_values: [1e-4, 1e-4, 1e-4]

Testing

pytest --verbose --cov=. tests/

The integration test in tests/train_global_test.py runs the full global pipeline on seq_FUN with mocked sys.argv and validates output metrics.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hmc_torch-0.0.8.tar.gz (57.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hmc_torch-0.0.8-py3-none-any.whl (67.7 kB view details)

Uploaded Python 3

File details

Details for the file hmc_torch-0.0.8.tar.gz.

File metadata

  • Download URL: hmc_torch-0.0.8.tar.gz
  • Upload date:
  • Size: 57.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hmc_torch-0.0.8.tar.gz
Algorithm Hash digest
SHA256 056ad147198cfe7f271d4c106875fa36f6b0346db1b0fd9a4a14faf246ed5a8e
MD5 44d669e1d7d7b486d7e95b17ecb6989a
BLAKE2b-256 63183488fef47ab4926b2a4c81bbf1cbb273448d9899fec279f66dcaca64c820

See more details on using hashes here.

Provenance

The following attestation bundles were made for hmc_torch-0.0.8.tar.gz:

Publisher: python-publish.yml on Sette/hmc-torch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hmc_torch-0.0.8-py3-none-any.whl.

File metadata

  • Download URL: hmc_torch-0.0.8-py3-none-any.whl
  • Upload date:
  • Size: 67.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hmc_torch-0.0.8-py3-none-any.whl
Algorithm Hash digest
SHA256 99dddaf8f79e84b8fb938a77ac926189dbc8d4865d1380876f2bda653b76a72f
MD5 5b0cafca93d2b1b1177bc42c781220e8
BLAKE2b-256 45b9fcb0978a939eb7b352fc58987e82cae9c1539872d513ccc6fd42d98e309f

See more details on using hashes here.

Provenance

The following attestation bundles were made for hmc_torch-0.0.8-py3-none-any.whl:

Publisher: python-publish.yml on Sette/hmc-torch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page