.. |pyc_logo| image:: https://raw.githubusercontent.com/pyc-team/pytorch_concepts/refs/heads/master/doc/_static/img/logos/pyc.svg :width: 20px :align: middle .. |pytorch_logo| image:: https://raw.githubusercontent.com/pyc-team/pytorch_concepts/refs/heads/master/doc/_static/img/logos/pytorch.svg :width: 20px :align: middle .. |hydra_logo| image:: https://raw.githubusercontent.com/pyc-team/pytorch_concepts/refs/heads/master/doc/_static/img/logos/hydra-head.svg :width: 20px :align: middle .. |pl_logo| image:: https://raw.githubusercontent.com/pyc-team/pytorch_concepts/refs/heads/master/doc/_static/img/logos/lightning.svg :width: 20px :align: middle .. |wandb_logo| image:: https://raw.githubusercontent.com/pyc-team/pytorch_concepts/refs/heads/master/doc/_static/img/logos/wandb.svg :width: 20px :align: middle .. |conceptarium_logo| image:: https://raw.githubusercontent.com/pyc-team/pytorch_concepts/refs/heads/master/doc/_static/img/logos/conceptarium.svg :width: 20px :align: middle Conceptarium ============ |conceptarium_logo| **Conceptarium** is a no-code framework for running large-scale experiments on concept-based models. Built on top of |pyc_logo| PyC, |hydra_logo| Hydra, and |pl_logo| PyTorch Lightning, it enables configuration-driven experimentation without writing Python code. Design Principles ----------------- Configuration-Driven Experimentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Conceptarium uses YAML configuration files to define all experiment parameters. No Python coding required: - **Models**: Select and configure any |pyc_logo| PyC model (CBM, CEM, CGM, BlackBox) - **Datasets**: Use built-in datasets (CUB-200, CelebA) or add custom ones - **Training**: Configure optimizer, scheduler, and Lightning Trainer settings - **Tracking**: Automatic logging to |wandb_logo| W&B for visualization and comparison Large-Scale Sweeps ^^^^^^^^^^^^^^^^^^ Run multiple experiments with single commands using |hydra_logo| Hydra's multi-run capabilities: .. code-block:: bash # Test 3 datasets × 2 models × 5 seeds = 30 experiments python run_experiment.py dataset=celeba,cub,mnist model=cbm,cem seed=1,2,3,4,5 Or by creating custom sweep configuration files: .. code-block:: yaml # conceptarium/conf/my_sweep.yaml defaults: - _commons # Inherit standard encoder/optimizer settings - _self_ # This file's parameters override hydra: job: name: experiment_name sweeper: # standard grid search params: seed: 1 dataset: celeba, cub, mnist, ... model: blackbox, cbm, cem, ... All runs are automatically organized, logged, and tracked. Hierarchical Composition ^^^^^^^^^^^^^^^^^^^^^^^^ Configurations inherit and override using ``defaults`` for maintainability: .. code-block:: yaml # conceptarium/conf/my_sweep.yaml defaults: - _commons # Inherit standard encoder/optimizer settings - _self_ # This file's parameters override # Only specify what's different model: optim_kwargs: lr: 0.05 # Override learning rate This keeps configurations concise and reduces duplication. Detailed Guides ^^^^^^^^^^^^^^^ .. dropdown:: Installation and Basic Usage :icon: rocket **Installation** Clone the repository and set up the environment: .. code-block:: bash git clone https://github.com/pyc-team/pytorch_concepts.git cd pytorch_concepts/conceptarium conda env create -f environment.yml conda activate conceptarium **Basic Usage** Run a single experiment with default configuration: .. code-block:: bash python run_experiment.py Run a sweep over multiple configurations: .. code-block:: bash python run_experiment.py --config-name sweep Override parameters from command line: .. code-block:: bash # Change dataset python run_experiment.py dataset=cub # Change model python run_experiment.py model=cbm_joint # Change multiple parameters python run_experiment.py dataset=celeba model=cbm_joint trainer.max_epochs=100 # Run sweep over multiple values python run_experiment.py dataset=celeba,cub model=cbm_joint,blackbox seed=1,2,3,4,5 .. dropdown:: Understanding Configurations :icon: file-code **Configuration Structure** All configurations are stored in ``conceptarium/conf/``: .. code-block:: text conf/ ├── _default.yaml # Base configuration ├── sweep.yaml # Example sweep configuration ├── dataset/ # Dataset configurations │ ├── _commons.yaml # Shared dataset parameters │ ├── celeba.yaml # CelebA dataset │ ├── cub.yaml # CUB-200 dataset │ └── ... # More datasets ├── loss/ # Loss function configs │ ├── standard.yaml # Type-aware losses │ └── weighted.yaml # Weighted losses ├── metrics/ # Metric configs │ └── standard.yaml # Type-aware metrics └── model/ # Model configurations ├── _commons.yaml # Shared model parameters ├── blackbox.yaml # Black-box baseline ├── cbm.yaml # Alias for cbm_joint └── cbm_joint.yaml # CBM (joint training) **Configuration Hierarchy** Configurations use |hydra_logo| Hydra's composition system with ``defaults`` to inherit and override: .. code-block:: yaml # conf/model/cbm_joint.yaml defaults: - _commons # Inherit common model parameters - _self_ # Current file takes precedence # Model-specific configuration _target_: torch_concepts.nn.ConceptBottleneckModel_Joint task_names: ${dataset.default_task_names} inference: _target_: torch_concepts.nn.DeterministicInference _partial_: true **Priority**: Parameters defined later override earlier ones. ``_self_`` controls where current file's parameters fit in the hierarchy. **Base Configuration** The ``_default.yaml`` file contains base settings for all experiments: .. code-block:: yaml defaults: - dataset: cub - model: cbm_joint - _self_ seed: 42 trainer: max_epochs: 500 patience: 30 monitor: "val_loss" mode: "min" wandb: project: conceptarium entity: your-team log_model: false **Key sections**: - ``defaults``: Which dataset and model configurations to use - ``seed``: Random seed for reproducibility - ``trainer``: PyTorch Lightning Trainer settings - ``wandb``: Weights & Biases logging configuration .. dropdown:: Working with Datasets :icon: database **Dataset Configuration Files** Each dataset has a YAML file in ``conf/dataset/`` that specifies: 1. The datamodule class (``_target_``) 2. Dataset-specific parameters 3. Backbone architecture (if needed) 4. Preprocessing settings **Example - CUB-200 Dataset** .. code-block:: yaml # conf/dataset/cub.yaml defaults: - _commons - _self_ _target_: torch_concepts.data.datamodules.CUBDataModule name: cub # Backbone for feature extraction backbone: _target_: torchvision.models.resnet18 pretrained: true precompute_embs: true # Precompute features to speed up training # Task variables to predict default_task_names: [bird_species] # Concept descriptions (optional, for interpretability) label_descriptions: - has_wing_color::blue: Wing color is blue - has_upperparts_color::blue: Upperparts color is blue - has_breast_pattern::solid: Breast pattern is solid - has_back_color::brown: Back color is brown **Example - CelebA Dataset** .. code-block:: yaml # conf/dataset/celeba.yaml defaults: - _commons - _self_ _target_: torch_concepts.data.datamodules.CelebADataModule name: celeba backbone: _target_: torchvision.models.resnet18 pretrained: true precompute_embs: true # Predict attractiveness from facial attributes default_task_names: [Attractive] label_descriptions: - Smiling: Person is smiling - Male: Person is male - Young: Person is young - Eyeglasses: Person wears eyeglasses - Attractive: Person is attractive **Common Dataset Parameters** Defined in ``conf/dataset/_commons.yaml``: .. code-block:: yaml batch_size: 256 # Training batch size val_size: 0.15 # Validation split fraction test_size: 0.15 # Test split fraction num_workers: 4 # DataLoader workers pin_memory: true # Pin memory for GPU # Optional: Subsample concepts concept_subset: null # null = use all concepts # concept_subset: [concept1, concept2, concept3] **Overriding Dataset Parameters** From command line: .. code-block:: bash # Change batch size python run_experiment.py dataset.batch_size=512 # Use only specific concepts python run_experiment.py dataset.concept_subset=[has_wing_color::blue,has_back_color::brown] # Change validation split python run_experiment.py dataset.val_size=0.2 In a custom sweep file: .. code-block:: yaml # conf/my_sweep.yaml defaults: - _default - _self_ dataset: batch_size: 512 val_size: 0.2 .. dropdown:: Working with Models :icon: cpu **Model Configuration Files** Each model has a YAML file in ``conf/model/`` that specifies: 1. The model class (``_target_``) 2. Architecture parameters (from ``_commons.yaml``) 3. Inference strategy 4. Metric tracking options **Example - Concept Bottleneck Model** .. code-block:: yaml # conf/model/cbm_joint.yaml defaults: - _commons - _self_ _target_: torch_concepts.nn.ConceptBottleneckModel_Joint # Task variables (from dataset) task_names: ${dataset.default_task_names} # Inference strategy inference: _target_: torch_concepts.nn.DeterministicInference _partial_: true # Metric tracking summary_metrics: true # Aggregate metrics by concept type perconcept_metrics: false # Per-concept individual metrics **Example - Black-box Baseline** .. code-block:: yaml # conf/model/blackbox.yaml defaults: - _commons - _self_ _target_: torch_concepts.nn.BlackBox task_names: ${dataset.default_task_names} # Black-box models don't use concepts inference: null summary_metrics: false perconcept_metrics: false **Common Model Parameters** Defined in ``conf/model/_commons.yaml``: .. code-block:: yaml # Encoder architecture encoder_kwargs: hidden_size: 128 # Hidden layer dimension n_layers: 2 # Number of hidden layers activation: relu # Activation function dropout: 0.1 # Dropout probability # Concept distributions (how concepts are modeled) variable_distributions: binary: torch.distributions.Bernoulli categorical: torch.distributions.Categorical # Optimizer configuration optim_class: _target_: torch.optim.AdamW _partial_: true optim_kwargs: lr: 0.00075 # Learning rate weight_decay: 0.0 # L2 regularization # Learning rate scheduler scheduler_class: _target_: torch.optim.lr_scheduler.ReduceLROnPlateau _partial_: true scheduler_kwargs: mode: min factor: 0.5 patience: 10 min_lr: 0.00001 **Loss Configuration** Loss functions are type-aware, automatically selecting the appropriate loss based on concept types. Loss configurations are in ``conf/loss/``: **Standard losses** (``conf/loss/standard.yaml``): .. code-block:: yaml _target_: torch_concepts.nn.ConceptLoss _partial_: true fn_collection: discrete: binary: path: torch.nn.BCEWithLogitsLoss kwargs: {} categorical: path: torch.nn.CrossEntropyLoss kwargs: {} # continuous: # Not yet supported # path: torch.nn.MSELoss # kwargs: {} **Weighted losses** (``conf/loss/weighted.yaml``): .. code-block:: yaml _target_: torch_concepts.nn.ConceptLoss _partial_: true fn_collection: discrete: binary: path: torch.nn.BCEWithLogitsLoss kwargs: reduction: none # Required for weighting categorical: path: torch.nn.CrossEntropyLoss kwargs: reduction: none concept_loss_weight: 1.0 task_loss_weight: 1.0 **Metrics Configuration** Metrics are also type-aware and configured in ``conf/metrics/``: .. code-block:: yaml # conf/metrics/standard.yaml discrete: binary: accuracy: path: torchmetrics.classification.BinaryAccuracy kwargs: {} categorical: accuracy: path: torchmetrics.classification.MulticlassAccuracy kwargs: average: micro continuous: mae: path: torchmetrics.regression.MeanAbsoluteError kwargs: {} mse: path: torchmetrics.regression.MeanSquaredError kwargs: {} **Overriding Model Parameters** From command line: .. code-block:: bash # Change learning rate python run_experiment.py model.optim_kwargs.lr=0.001 # Enable per-concept metrics python run_experiment.py model.perconcept_metrics=true # Change encoder architecture python run_experiment.py model.encoder_kwargs.hidden_size=256 \ model.encoder_kwargs.n_layers=3 # Use weighted loss python run_experiment.py loss=weighted In a custom sweep file: .. code-block:: yaml # conf/my_sweep.yaml defaults: - _default - _self_ model: encoder_kwargs: hidden_size: 256 n_layers: 3 optim_kwargs: lr: 0.001 perconcept_metrics: true .. dropdown:: Running Experiments :icon: play **Single Experiment** Run with default configuration: .. code-block:: bash python run_experiment.py Specify dataset and model: .. code-block:: bash python run_experiment.py dataset=celeba model=cbm_joint With custom parameters: .. code-block:: bash python run_experiment.py \ dataset=cub \ model=cem \ model.optim_kwargs.lr=0.001 \ trainer.max_epochs=100 \ seed=42 **Multi-Run Sweeps** Sweep over multiple values using comma-separated lists: .. code-block:: bash # Sweep over datasets python run_experiment.py dataset=celeba,cub,mnist # Sweep over models python run_experiment.py model=cbm_joint,cem,cgm # Sweep over hyperparameters python run_experiment.py model.optim_kwargs.lr=0.0001,0.0005,0.001,0.005 # Sweep over seeds for robustness python run_experiment.py seed=1,2,3,4,5 # Combined sweeps python run_experiment.py \ dataset=celeba,cub \ model=cbm_joint,cem \ seed=1,2,3 This runs 2 × 2 × 3 = 12 experiments. **Custom Sweep Configuration** Create a sweep file (``conf/my_sweep.yaml``): .. code-block:: yaml defaults: - _default - _self_ hydra: job: name: my_sweep sweeper: params: dataset: celeba,cub,mnist model: cbm_joint,cem seed: 1,2,3,4,5 model.optim_kwargs.lr: 0.0001,0.001 # Default overrides trainer: max_epochs: 500 patience: 50 model: summary_metrics: true perconcept_metrics: true Run the sweep: .. code-block:: bash python run_experiment.py --config-name my_sweep **Parallel Execution** Use Hydra's joblib launcher for parallel execution: .. code-block:: bash python run_experiment.py \ --multirun \ hydra/launcher=joblib \ hydra.launcher.n_jobs=4 \ dataset=celeba,cub \ model=cbm_joint,cem Or use SLURM for cluster execution: .. code-block:: bash python run_experiment.py \ --multirun \ hydra/launcher=submitit_slurm \ hydra.launcher.partition=gpu \ hydra.launcher.gpus_per_node=1 \ dataset=celeba,cub \ model=cbm_joint,cem .. dropdown:: Output Structure :icon: file-directory **Directory Organization** Experiment outputs are organized by timestamp: .. code-block:: text outputs/ └── multirun/ └── 2025-11-27/ └── 14-30-15_my_experiment/ ├── 0/ # First run │ ├── .hydra/ # Hydra configuration │ │ ├── config.yaml # Full resolved config │ │ ├── hydra.yaml # Hydra settings │ │ └── overrides.yaml # CLI overrides │ ├── checkpoints/ # Model checkpoints │ │ ├── best.ckpt # Best model │ │ └── last.ckpt # Last epoch │ ├── logs/ # Training logs │ │ └── version_0/ │ │ ├── events.out.tfevents # TensorBoard │ │ └── hparams.yaml # Hyperparameters │ └── run.log # Console output ├── 1/ # Second run ├── 2/ # Third run └── multirun.yaml # Sweep configuration **Accessing Results** Each run directory contains: - **Checkpoints**: ``checkpoints/best.ckpt`` - Best model based on validation metric - **Logs**: ``logs/version_0/`` - TensorBoard logs - **Configuration**: ``.hydra/config.yaml`` - Full configuration used for this run - **Console output**: ``run.log`` - All printed output Load a checkpoint: .. code-block:: python import torch from torch_concepts.nn import ConceptBottleneckModel_Joint checkpoint = torch.load('outputs/multirun/.../0/checkpoints/best.ckpt') model = ConceptBottleneckModel_Joint.load_from_checkpoint(checkpoint) **Weights & Biases Integration** All experiments are automatically logged to W&B if configured: .. code-block:: yaml # In your config or _default.yaml wandb: project: my_project entity: my_team log_model: false # Set true to save models to W&B mode: online # or 'offline' or 'disabled' View results at https://wandb.ai/your-team/my_project .. dropdown:: Creating Custom Configurations :icon: pencil **Adding a New Model** 1. **Implement the model** in |pyc_logo| PyC (see ``examples/contributing/model.md``) 2. **Create configuration file** ``conf/model/my_model.yaml``: .. code-block:: yaml defaults: - _commons - loss: _default - metrics: _default - _self_ _target_: torch_concepts.nn.MyModel task_names: ${dataset.default_task_names} # Model-specific parameters my_param: 42 another_param: hello 3. **Run experiments**: .. code-block:: bash python run_experiment.py model=my_model dataset=cub **Adding a New Dataset** 1. **Implement the dataset and datamodule** (see ``examples/contributing/dataset.md``) 2. **Create configuration file** ``conf/dataset/my_dataset.yaml``: .. code-block:: yaml defaults: - _commons - _self_ _target_: my_package.MyDataModule name: my_dataset # Backbone (if needed) backbone: _target_: torchvision.models.resnet18 pretrained: true precompute_embs: false # Default tasks default_task_names: [my_task] # Dataset-specific parameters data_path: /path/to/data preprocess: true 3. **Run experiments**: .. code-block:: bash python run_experiment.py dataset=my_dataset model=cbm_joint **Adding Custom Loss/Metrics** Create ``conf/model/loss/my_loss.yaml``: .. code-block:: yaml _target_: torch_concepts.nn.WeightedConceptLoss _partial_: true fn_collection: discrete: binary: path: my_package.MyBinaryLoss kwargs: alpha: 0.25 gamma: 2.0 categorical: path: torch.nn.CrossEntropyLoss kwargs: label_smoothing: 0.1 concept_loss_weight: 0.5 task_loss_weight: 1.0 Use it: .. code-block:: bash python run_experiment.py model/loss=my_loss .. dropdown:: Advanced Usage :icon: gear **Conditional Configuration** Use Hydra's variable interpolation: .. code-block:: yaml # Automatically adjust batch size based on dataset dataset: batch_size: ${select:${dataset.name},{celeba:512,cub:256,mnist:1024}} # Scale learning rate with batch size model: optim_kwargs: lr: ${multiply:0.001,${divide:${dataset.batch_size},256}} **Configuration Validation** Add validation to catch errors early: .. code-block:: yaml # conf/model/cbm_joint.yaml defaults: - _commons - loss: _default - metrics: _default - _self_ _target_: torch_concepts.nn.ConceptBottleneckModel_Joint # Require task names task_names: ${dataset.default_task_names} ??? # Error if not provided **Experiment Grouping** Organize related experiments: .. code-block:: yaml # conf/ablation_study.yaml hydra: job: name: ablation_${model.encoder_kwargs.hidden_size} defaults: - _default - _self_ model: encoder_kwargs: hidden_size: ??? # Must be provided Run: .. code-block:: bash python run_experiment.py \ --config-name ablation_study \ model.encoder_kwargs.hidden_size=64,128,256,512 .. dropdown:: Best Practices :icon: checklist 1. **Use Descriptive Names** .. code-block:: yaml hydra: job: name: ${model._target_}_${dataset.name}_seed${seed} 2. **Keep Configs Small** - Use ``defaults`` to inherit common parameters - Only override what's different 3. **Document Custom Parameters** .. code-block:: yaml my_parameter: 42 # Controls X behavior, higher = more Y 4. **Version Control Configurations** - Commit all YAML files to git - Tag important configurations 5. **Use Sweeps for Exploration** - Start with broad sweeps - Narrow down based on results 6. **Monitor with W&B** - Enable W&B logging for all experiments - Use tags to organize runs 7. **Save Important Checkpoints** - Set ``trainer.save_top_k`` appropriately - Copy important checkpoints out of temp directories .. dropdown:: Troubleshooting :icon: tools **Common Issues** **Error: "Could not find dataset config"** - Check that ``conf/dataset/your_dataset.yaml`` exists - Verify the filename matches what you're passing to ``dataset=`` **Error: "Missing _target_ in config"** - Ensure your config has ``_target_`` pointing to the class - Check for typos in the class path **Error: "Validation loss not improving"** - Check learning rate: try ``model.optim_kwargs.lr=0.0001`` - Increase patience: ``trainer.patience=50`` - Check your loss configuration **Experiments running slowly** - Enable feature precomputation: ``dataset.precompute_embs=true`` - Increase batch size: ``dataset.batch_size=512`` - Use more workers: ``dataset.num_workers=8`` **Out of memory** - Reduce batch size: ``dataset.batch_size=128`` - Reduce model size: ``model.encoder_kwargs.hidden_size=64`` - Enable gradient checkpointing (model-specific) **Debugging** Check resolved configuration: .. code-block:: bash python run_experiment.py --cfg job Print config without running: .. code-block:: bash python run_experiment.py --cfg all Validate configuration: .. code-block:: bash python run_experiment.py --resolve See Also -------- - :doc:`using_high_level` - High-level API for programmatic usage - `Contributing Guide - Models `_ - Implementing custom models - `Contributing Guide - Datasets `_ - Implementing custom datasets - `Conceptarium README `_ - Additional documentation - `Hydra Documentation `_ - Advanced configuration patterns - `PyTorch Lightning `_ - Training framework documentation