Skip to main content

PRISM - Parameter Research & Investigation Sweep Manager

Project description

๐Ÿ”ฌ PRISM - Parameter Research & Investigation Sweep Manager

PyPI version Python 3.8+ License: MIT

PRISM is a simple tool to run parameter sweeps for ML experiments. Give it a base config and a sweep definition, and it will generate, validate, and execute all experiment variations.

What is PRISM?

PRISM takes your base experiment configuration and creates multiple variations by changing specific parameters. It then:

  1. Validates each configuration using your custom Python validator
  2. Runs your training script with each validated config
  3. Tracks progress and captures metrics
  4. Provides an interactive TUI to monitor experiments

Installation

From PyPI (Recommended)

pip install prism-sweep

From Source

git clone https://github.com/FrancescoCorrenti/prism-sweep.git
cd prism-sweep
pip install -e .

After installation, you can use prism_tui or prism commands from anywhere.


Quick Start Guide

Using the Interactive TUI (Recommended)

The easiest way to use PRISM is through the interactive terminal interface:

prism_tui

First Time Setup:

  1. Navigate to your project directory in the TUI
  2. Follow the guided setup to create prism.project.yaml
    • Give it a name
    • Select sweep definition(s)
    • Give it a name
  3. Run experiments: Study Menu โ†’ Execute Study โ†’ Run All
  • Select base config YAML
  • Select sweep definition(s)
  • Give it a name
  1. Monitor progress: Watch real-time logs and metrics
  2. Retry failures: Study Menu โ†’ Retry Failed
  3. Run experiments: Study Menu โ†’ Execute Study โ†’ Run All
  4. Monitor progress: Watch real-time logs and metrics
  5. Retry failures: Study Menu โ†’ Retry Failed

Using the Command Line

For automation and scripting, use the CLI:

# Create a study from base config and sweep definition
prism create --base configs/base.yaml \
             --prism configs/prism/lr_sweep.prism.yaml \
             --name lr_experiment

# Run all experiments in the study
prism run lr_experiment --all

# Run specific experiments
prism run lr_experiment lr_low lr_mid

# Check study status
prism status lr_experiment

# List all studies
prism list

# Retry failed experiments
prism retry lr_experiment

What Files Do I Need?

PRISM needs 3-4 files in your project:

1. prism.project.yaml (Project Configuration)

This tells PRISM where everything is. The TUI can create this for you, or create it manually:

project:
  name: my-ml-project
  version: "1.0"

paths:
  train_script: scripts/train.py        # Your training script
  configs_dir: configs                  # Where configs live
  prism_configs_dir: configs/prism      # Where sweep definitions live
  output_dir: outputs                   # Where results go

validator:
  module: configs/validator.py          # Optional: custom validator

metrics:
  output_mode: stdout_json              # How to capture metrics

2. Base Config (e.g., configs/base.yaml)

Your experiment's default configuration:

learning_rate: 0.001
batch_size: 32
epochs: 100
model: resnet18
data:
  path: /data/train
  augmentation: true

3. Sweep Definition (e.g., configs/prism/lr_sweep.yaml)

Defines which parameters to vary:

# Nominal parameters (creates named experiments)
learning_rate:
  lr_low: 0.0001
  lr_mid: 0.001
  lr_high: 0.01

4. Custom Validator (Optional: configs/validator.py)

Validates configs before training:

from typing import Dict, Any
from dataclasses import dataclass

@dataclass
class ExperimentConfig:
    learning_rate: float
    batch_size: int
    epochs: int
    
    def validate(self):
        if self.learning_rate <= 0:
            raise ValueError("Learning rate must be > 0")
        if self.batch_size < 1:
            raise ValueError("Batch size must be >= 1")

def validate(config_dict: Dict[str, Any]) -> ExperimentConfig:
    """Called by PRISM to validate each config."""
    config = ExperimentConfig(
        learning_rate=config_dict.get('learning_rate', 0.001),
        batch_size=config_dict.get('batch_size', 32),
        epochs=config_dict.get('epochs', 100)
    )
    config.validate()
    return config
- Cross-field validation
- Set default values
- Convert enums, paths, etc.

### Your Training Script

Make sure it accepts a `--config` argument:

```python
# scripts/train.py
import argparse
import yaml
import json

parser = argparse.ArgumentParser()
parser.add_argument('--config', required=True)
args = parser.parse_args()

with open(args.config) as f:
    config = yaml.safe_load(f)

# Train your model...
learning_rate = config['learning_rate']
# ...

# Print metrics for PRISM
print(json.dumps({"loss": 0.123, "accuracy": 0.95}))

File Structure

After running PRISM, your project will look like:

your-project/
โ”œโ”€โ”€ prism.project.yaml           # Project config
โ”œโ”€โ”€ configs/
โ”‚   โ”œโ”€โ”€ validator.py             # Optional: custom validator
โ”‚   โ”œโ”€โ”€ base.yaml                # Base configuration
โ”‚   โ””โ”€โ”€ prism/
โ”‚       โ””โ”€โ”€ lr_sweep.yaml        # Sweep definition
โ”œโ”€โ”€ scripts/
โ”‚   โ””โ”€โ”€ train.py                 # Your training script
โ””โ”€โ”€ outputs/                     # Generated by PRISM
    โ”œโ”€โ”€ lr_experiment.prism      # Study state (created by PRISM)
    โ””โ”€โ”€ lr_experiment/           # Experiment outputs (created by PRISM)
        โ”œโ”€โ”€ lr_low/
        โ”‚   โ”œโ”€โ”€ config.yaml      # Validated config for this experiment
        โ”‚   โ””โ”€โ”€ ...              # Your training outputs
        โ”œโ”€โ”€ lr_mid/

Sweep Definition Syntax

Named Parameters (Nominal)

# Creates experiments with custom names
model:
  size:
    small_model: small
    large_model: large
  layers:
    small_model: 12
    large_model: 24

Creates experiments: small_model, large_model

Positional Parameters (Lists - Zipped Together)

# Creates experiments run_0, run_1, run_2
batch_size: [16, 32, 64]
learning_rate: [0.01, 0.001, 0.0001]
  • run_0: batch_size=16, lr=0.01
  • run_1: batch_size=32, lr=0.001
  • run_2: batch_size=64, lr=0.0001

Sweep Definitions (Advanced)

# Choice sweep
optimizer:
  lr:
    _type: choice
    _values: [0.001, 0.01, 0.1]

# Range sweep
epochs:
  _type: range
  _min: 10
  _max: 100
  _step: 10

# Linspace sweep
momentum:
  _type: linspace
  _min: 0.0
  _max: 0.99
  _num: 5

Multiple Files (Cartesian Product)

prism create --base base.yaml \
             --prism models.yaml \
             --prism optimizers.yaml \
             --name model_opt_sweep

If models.yaml has 3 variations and optimizers.yaml has 2, you get 3ร—2=6 experiments.

Complete Example

Base config (configs/base.yaml):

optimizer:
  type: adam
  lr: 0.001
  weight_decay: 0.0001
model:
  backbone: resnet50
  hidden_dim: 512

Sweep config (configs/prism/lr_sweep.prism.yaml):

optimizer:
  lr:
    lr_low: 0.0001
    lr_mid: 0.001
    lr_high: 0.01

This creates 3 experiments:

  • lr_low: with optimizer.lr = 0.0001
  • lr_mid: with optimizer.lr = 0.001
  • lr_high: with optimizer.lr = 0.01

All other parameters stay the same from base config.


Metrics Capture

PRISM can capture metrics in three ways:

1. JSON stdout (default)

Your training script prints JSON:

import json
print(json.dumps({"loss": 0.5, "accuracy": 0.92}))

2. File output

# In prism.project.yaml
metrics:
  output_mode: file
  output_file: metrics.json

Your script writes metrics.json in the output directory.

3. Exit code only

metrics:
  output_mode: exit_code

PRISM only checks if the script succeeded (exit code 0).


Advanced Features

Custom Train Arguments

You can customize how PRISM calls your training script:

# In prism.project.yaml  
paths:
  train_script: scripts/train.py
  train_args:
    - --config
    - "{config_path}"
    - --gpu
    - "0"

Resume Failed Experiments

prism retry study_name

Or in TUI: Study Menu โ†’ Retry Failed


Tips

  1. Start small: Test with 2-3 experiments before scaling up
  2. Use the TUI: It's much easier than CLI for exploration
  3. Validate early: Run one experiment manually before creating a big sweep
  4. Check metrics: Make sure your training script prints/writes them correctly

Troubleshooting

"No train_script defined" โ†’ Add paths.train_script: scripts/train.py to prism.project.yaml

"Validator module not found"
โ†’ Check the path in validator.module is correct relative to project root

"Config validation failed" โ†’ Check your validate() function - it's rejecting the config

Experiments hang at "Testing data loading" โ†’ Fixed! Make sure you have latest version with PYTHONUNBUFFERED=1

โ†’ Fixed! Latest version forces colors with FORCE_COLOR=1


  • Python 3.8+
  • pyyaml
  • rich (for TUI) That's it! No other dependencies.

  • Organized: Never lose track of which experiment used which parameters
  • Validated: Catch config errors before training starts
  • Interactive: TUI makes it easy to monitor and manage experiments

Ready to start? Run prism_tui and follow the prompts!
parameters: training.learning_rate: 0.001

  • name: lr_high parameters: training.learning_rate: 0.01

### 3. Create and Run Study

## Sweep Configuration



## Custom Python Validator

PRISM supports custom Python validators for config validation. This is useful when you have:

- Complex type conversions (e.g., YAML โ†’ Python dataclasses)
- Cross-field validation logic
- Enum types with custom behavior
- Integration with existing config systems

### Setup

In `prism.project.yaml`:
```yaml
project:
  name: my-project
  version: "1.0"

paths:
  train_script: scripts/train.py
  output_dir: outputs

# Custom Python validator
validator:
  module: configs/validator.py

Validator Module Interface

Your validator module must expose a validate(config_dict) function:

# configs/validator.py
from typing import Dict, Any
from dataclasses import dataclass
from enum import Enum

class ModelType(str, Enum):
    RESNET = "resnet"
    VIT = "vit"

@dataclass
class ModelConfig:
    type: ModelType
    hidden_size: int = 768

@dataclass
class ExperimentConfig:
    model: ModelConfig
    learning_rate: float
    epochs: int
    
    def validate(self):
        """Custom validation logic."""
        if self.model.type == ModelType.VIT and self.epochs < 100:
            raise ValueError("ViT requires at least 100 epochs")

def validate(config_dict: Dict[str, Any]) -> ExperimentConfig:
    """
    Validate and convert raw config dict to typed dataclass.
    
    This function is called by PRISM before passing the config
    to your training script.
    
    Args:
        config_dict: Raw YAML config as dictionary
        
    Returns:
        Validated ExperimentConfig (dataclass will be serialized back to YAML)
        
    Raises:
        ValueError: If validation fails
    """
    # Convert dict to dataclass
    model = ModelConfig(
        type=ModelType(config_dict.get('model', {}).get('type', 'resnet')),
        hidden_size=config_dict.get('model', {}).get('hidden_size', 768)
    )
    
    config = ExperimentConfig(
        model=model,
        learning_rate=config_dict.get('learning_rate', 0.001),
        epochs=config_dict.get('epochs', 100)
    )
    
    # Run validation
    config.validate()
    
    return config

How It Works

  1. PRISM loads your base config YAML
  2. PRISM expands it with sweep parameters
  3. PRISM calls your validate(config_dict) function
  4. If validation passes, the result is serialized back to YAML
  5. The validated YAML is passed to your training script

This means your training script can simply reload the YAML - it's already validated!

# scripts/train.py
import yaml
with open(args.config) as f:
    config = yaml.safe_load(f)
# ... use config['model']['type'], config['learning_rate'], etc.

Directory Structure

my_project/
โ”œโ”€โ”€ prism.project.yaml    # Project configuration
โ”œโ”€โ”€ configs/              # Base configurations
โ”‚   โ”œโ”€โ”€ base.yaml
โ”‚   โ”œโ”€โ”€ validator.py      # Optional: custom validator
โ”‚   โ””โ”€โ”€ prism/            # Sweep definitions
โ”‚       โ”œโ”€โ”€ lr_sweep.prism.yaml
โ”‚       โ””โ”€โ”€ model_sweep.prism.yaml
โ”œโ”€โ”€ scripts/
โ”‚   โ””โ”€โ”€ train.py          # Your training script
โ””โ”€โ”€ outputs/              # Results and state
    โ”œโ”€โ”€ my_study.prism    # Study state file
    โ””โ”€โ”€ my_study/         # Experiment outputs

Commands Reference

CLI Commands

# Project management
prism init                          # Initialize new project
prism list                          # List all studies

# Study management  
prism create --name NAME --config BASE --prism SWEEP  # Create new study
prism status NAME                   # Show study status
prism delete NAME --force           # Delete a study
prism reset NAME                    # Reset study to pending

# Experiment execution
prism run --study NAME --all        # Run all pending experiments
prism run --study NAME --next       # Run next pending
prism run --study NAME --key KEY    # Run specific experiment
prism retry NAME                    # Retry failed experiments

# Inspection
prism show-config NAME KEY          # Show experiment config
prism diff NAME KEY1 KEY2           # Compare two configs
prism mark NAME KEY done/failed     # Mark experiment status

# Interactive
prism tui                           # Launch TUI

TUI Interface

prism_tui                     # Launch interactive TUI

The TUI provides:

  • ๐Ÿ“š Recent projects quick-access
  • ๐Ÿ“Š Study overview with experiment status
  • ๐Ÿš€ One-click experiment execution
  • ๐Ÿ“ˆ Real-time metrics display
  • โš™๏ธ Configuration browser

State Management

Each study has a .prism state file that tracks:

  • Experiment configurations
  • Execution status (PENDING, RUNNING, DONE, FAILED)
  • Timestamps and metrics
  • Original config paths for reset

Requirements

  • Python 3.8+
  • PyYAML
  • Rich (for TUI)

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Development Setup

# Clone the repository
git clone https://github.com/FrancescoCorrenti/prism-sweep.git
cd prism-sweep

# Install in development mode
pip install -e ".[dev]"

License

MIT License - see LICENSE file for details.

Author

Francesco Correnti

Links

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

prism_sweep-0.1.0.tar.gz (49.9 kB view details)

Uploaded Source

Built Distribution

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

prism_sweep-0.1.0-py3-none-any.whl (47.9 kB view details)

Uploaded Python 3

File details

Details for the file prism_sweep-0.1.0.tar.gz.

File metadata

  • Download URL: prism_sweep-0.1.0.tar.gz
  • Upload date:
  • Size: 49.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for prism_sweep-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e56b33d9a377e3dda1d0e8495d7958220d14a5c33d3100cd0bdf13d1b7fd456d
MD5 3c66776ed83b549b7f084165b8f40df1
BLAKE2b-256 6f22b6b873a2e6fe853d019c82addb07a7f679a4f95f3b5741ba377969255b47

See more details on using hashes here.

File details

Details for the file prism_sweep-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: prism_sweep-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 47.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for prism_sweep-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bc9bc0a24ceb67797e710ea08830e749ce0d57b295c0be36ea65e549c2fb3fe6
MD5 f0277b21a235d5dff97c8c3c31bd0206
BLAKE2b-256 c2fb96af1790b06d1dab8f85c63f265250fb8671a16d3339bbbc8899efca9e02

See more details on using hashes here.

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