Investigation is an machine learning experiment management library that couple with project source code to provide version dependent experiment assistance.
Project description
Investigation
Investigation is a machine learning experiment management library that couples with project source code to provide version-dependent experiment assistance.
做的更快,更 robust,更 solid。 让别人在 queue 中等,而不是你。 让你的 paper 被傻逼 reviewer 拒稿,而不是被 reasonable critics。
Features
- 🔬 Experiment Management: Manage machine learning experiments with version control integration
- 📊 Training Log Visualization: Real-time visualization of training curves and metrics
- 🎯 Design of Experiments (DoE): Generate and manage experiment configurations
- 📈 Multi-Instance Comparison: Compare and aggregate results across multiple training runs
- 🔍 Advanced Filtering: Filter and organize experiments using regex patterns
- 🏗️ Nested Dataclass Support: Organize hyperparameters hierarchically (Hydra.cc-style)
Installation
# Using poetry (recommended)
poetry add investigation
# Or install with pip
pip install investigation flask
Quick Start
Basic Usage as Terminal Tools
Investigation provides two main terminal tools: ivst and ivst-vsl.
Experiment Management with ivst
In an external project, use ivst to manage experiments:
# Add investigation to your project
poetry add investigation
# Initialize a new experiment
poetry run ivst init --name doe
# Commit experiment configuration
poetry run ivst commit --commit githash --name doe
# Submit experiments
poetry run ivst submit --commit githash
Example Usage with a ML Project
Here is a detailed example of integrating investigation into a machine learning project (mlctrl).
-
Clone the project and navigate into the directory:
# Replace with your actual repository URL git clone https://github.com/your-username/mlctrl.git cd mlctrl
-
Add
investigationas a dependency:poetry add investigation
-
Create
entry/init.pyfor experiment configuration:This file defines how parameters map to a job, like a
SlurmJob.from investigation.doeargs.args import ExampleArgs from typing import Type, List, Dict from slurming.SlurmJob.job import SlurmJob from slurming.Slurm.shellUtils import make_command from pathlib import Path import environs import numpy as np import os # This file is part of EpisodicRL. from example.models.model1 import Args as FlowArgs from example.models.model2 import FourierDiffusionArgs, UnetDiffusionArgs, AttentionDiffusionArgs CLUSTER_CONFIG = { "clusterC-dense": { "hostname": "clusterC", "mem_per_core": 4.4, "min_cores": 1, "core_per_job": 6, "vip": ["clusterB", "clusterA"], "partition": ["cpu", "cpu-exp"], }, "clusterA-dense": { "hostname": "clusterA", "mem_per_core": 4.84, "min_cores": 1, "core_per_job": 32, "vip": ["clusterB"], "partition": ["cpu", "gpu"], } } cwd = Path.cwd() env = environs.Env() env.read_env(str(cwd / ".env")) LIST_OF_ARGS: List[Type[ExampleArgs]] = [ FlowArgs, UnetDiffusionArgs, FourierDiffusionArgs, AttentionDiffusionArgs, ] LIST_OF_CLUSTERS: List[str] = ["clusterA", "clusterC", "clusterB"] def parameter2SlurmJob(param_dict: Dict, ) -> SlurmJob: """ Convert a parameter dictionary to a SlurmJob instance. Args: param_dict (Dict): A dictionary containing parameters for the Slurm job. Returns: SlurmJob: An instance of SlurmJob configured with the provided parameters. """ python_run_json_head_lightning = f"src.train" gpus = 1 hostname = os.uname().nodename match hostname[0]: case "p": host = "clusterC-dense" case "c": host = "clusterA-dense" case _: host = "clusterC-dense" cores = max( int(np.ceil(CLUSTER_CONFIG[host]["core_per_job"])), CLUSTER_CONFIG[host]["min_cores"], ) partition = CLUSTER_CONFIG[host]["partition"] job_duration = 40 if (gpus > 0): job_duration = job_duration // 20 job = SlurmJob( account=env.str("SLURM_ACCOUNT"), content=[ "wandb offline", f"rm -rf logger.json videos wandb", "find example/ -type f -name \"*.pyc\" | xargs rm -fv", make_command( "accelerate launch --main_process_port 54874 poetry run python", params1_dict={ "m": python_run_json_head_lightning, }, params2_dict=param_dict, connection=" ", ), ], licenses={}, modules=[], env_vars={ "WANDB_CONSOLE": "off", "SLURM_CPU_PER_TASK": str(cores), }, notify_email=[], aliases={}, paths=[], sbatch_args={}, hours=job_duration, cpus_per_task=cores, gpus=gpus, interactive=True, output_storage=["history.csv"], partition=",".join(partition), ) return job
-
Create the main entry point
src/entry.py:This script uses the
@ctrl.main()decorator to handle experiment logic.import investigation as ctrl import tyro from investigation.doeargs.args import ExampleArgs @ctrl.main() def main() -> None: """Entry point for loading configurations and running training.""" args, _ = tyro.cli( ExampleArgs, return_unknown_args=True, ) match args.name: case "ModelName1": from example.models.model2 import FourierDiffusionArgs args = tyro.cli(FourierDiffusionArgs) case "ModelName2": from example.models.model2 import UnetDiffusionArgs args = tyro.cli(UnetDiffusionArgs) case _: raise NotImplementedError(f"{args.name} not implemented yet.") from src.train import train train(args) if __name__ == '__main__': main()
-
Initialize a DoE configuration file
doe.json:This JSON file defines the parameter space for the experiments.
{ "meta": { "num_seeds": {"type": "<class 'int'>", "default": 1, "value": 1}, "include": { "type": "List[Dict[str, Dict]]", "default": [], "value": [] } }, "shared": { "batch_size": {"type": "<class 'int'>", "default": 16, "range": []}, "epochs": {"type": "<class 'int'>", "default": 100, "range": []} }, "ModelName1": { "name": {"type": "<class 'str'>", "default": "ModelName1", "range": []}, }
-
Run the experiments:
Execute the entry script with the DoE configuration and a commit hash.
poetry run python src/entry.py --doe-config doe.json --commit <your_commit_hash>
This command will:
- Create a JSON case database under
.investigation/<your_commit_hash>/. - Generate shell scripts for each experiment case in
.investigation/<your_commit_hash>/shell/. - Submit the jobs defined in
doe.json.
- Create a JSON case database under
Training Log Visualization with ivst-vsl
The visualization tool reads data from .investigation/commithash/storage/*.csv:
# Start the visualization server
poetry run ivst-vsl
# Or specify custom port
poetry run ivst-vsl --port 8080
Both ivst and ivst-vsl are terminal tools that operate on data in workdir/.investigation.
The visualization tool specifically looks for CSV files in the structure: workdir/.investigation/commithash/storage/*.csv.
Then open your browser to http://127.0.0.1:5000
Features:
- 📊 Real-time Visualization: Automatically refresh and display latest training data
- 🔍 Instance Filtering: Filter training instances using regex patterns
- 📈 Multi-Instance Comparison: Display curves from multiple training instances simultaneously
- 🎯 Data Aggregation: Aggregate multiple instances with mean, min, or max
- 🎨 Interactive Charts: Modern interactive charts powered by Chart.js
- 🌐 Bilingual Interface: Supports both Chinese and English
For detailed usage instructions, see Visualization Guide.
Nested Dataclass Support
Investigation now supports hierarchical dataclass structures, similar to Hydra.cc configurations:
from dataclasses import dataclass, field
from investigation.doeargs.args import ExampleArgs
@dataclass
class DataConfig:
data_path: str = "./data/"
batch_size: int = 16
@dataclass
class TrainingConfig:
epochs: int = 100
learning_rate: float = 0.001
@dataclass
class Args(ExampleArgs):
name: str = "MyExperiment"
data: DataConfig = field(default_factory=DataConfig)
training: TrainingConfig = field(default_factory=TrainingConfig)
Nested fields are automatically flattened using dot notation (data.batch_size, training.epochs) and work seamlessly with all Investigation features.
For more details, see Nested Dataclass Support Guide.
CSV Log Format
The system expects CSV files with training metrics. Example format:
policy_loss,log_pi,cgqp,q_loss,qf1_loss,qf2_loss,cnqp,cnqn,-qf_res1_min,qf_res1_max,-qf_res2_min,qf_res2_max,episodic_return,episodic_length,last_step_reward,goal_reward,test_goal_reward,test_episodic_return,test_last_step_reward,SPS,global_step,buffer_filled,epoch,step
Key columns:
global_steporstep: X-axis (training steps)- Other numeric columns: Selectable Y-axis metrics
Project Structure
Investigation/
├── investigation/ # Core experiment management
├── visualization/ # Web-based visualization system
│ ├── app.py # Flask application
│ ├── cli.py # Command-line interface
│ ├── templates/ # HTML templates
│ └── README.md # Visualization documentation
├── docs/ # Documentation
│ └── VISUALIZATION_GUIDE.md
└── .investigation/ # Default storage for training logs
Usage Examples
Basic Visualization
- Start the server:
python -m visualization.cli - Select a training instance from the left panel
- Choose a metric to visualize (e.g.,
episodic_return) - View the training curve on the right
Comparing Multiple Experiments
- Check multiple training instances in the left panel
- Select a metric to compare
- The chart displays all selected instances with different colors
Aggregating Experiments
- Select multiple instances
- Choose aggregation method (Mean/Min/Max)
- Click "聚合选中实例" (Aggregate Selected Instances)
- View the aggregated curve
API Endpoints
The visualization module provides REST API endpoints:
GET /api/instances- List all training instancesGET /api/data/<path>- Get data for specific instancePOST /api/filter- Filter instances by patternPOST /api/aggregate- Aggregate multiple instances
See Visualization README for full API documentation.
Development
# Install dependencies
poetry install
# Run with debug mode
python -m visualization.cli --debug
# Run tests (if available)
pytest
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Author
Yuxiang Luo yuxiang.lll@outlook.com
Acknowledgments
- Built with Flask for the backend
- Chart.js for interactive visualizations
- Designed for machine learning experiment tracking and analysis
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file investigation-0.1.2a3.tar.gz.
File metadata
- Download URL: investigation-0.1.2a3.tar.gz
- Upload date:
- Size: 155.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6197b9fd97b75ef3a34534d7356dc7e9da44a7a89d2cdb29b63c8e8f85f7a19
|
|
| MD5 |
492f3cd08945c3c9919487b92a3e8f72
|
|
| BLAKE2b-256 |
5e6ad1c8b23bc1b115b51ab052d55d287cf675ed93d86c44a8df2ed90f62f94e
|
Provenance
The following attestation bundles were made for investigation-0.1.2a3.tar.gz:
Publisher:
publish.yml on DeliYuxiang/Investigation
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
investigation-0.1.2a3.tar.gz -
Subject digest:
b6197b9fd97b75ef3a34534d7356dc7e9da44a7a89d2cdb29b63c8e8f85f7a19 - Sigstore transparency entry: 1059355195
- Sigstore integration time:
-
Permalink:
DeliYuxiang/Investigation@72f4ab1f16e910bb87df93f14c03ad28f9369570 -
Branch / Tag:
refs/tags/v0.1.2a3 - Owner: https://github.com/DeliYuxiang
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@72f4ab1f16e910bb87df93f14c03ad28f9369570 -
Trigger Event:
push
-
Statement type:
File details
Details for the file investigation-0.1.2a3-py3-none-any.whl.
File metadata
- Download URL: investigation-0.1.2a3-py3-none-any.whl
- Upload date:
- Size: 45.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4aa00ba0dd6aa543c362a91eb482b29e0007e2e3087b48b33ad6c89706ae55ec
|
|
| MD5 |
c1d2ac3f1d8484a5e8645cf59ac63695
|
|
| BLAKE2b-256 |
dae2e94432ab5ed2818ffc5fd3f6f413e33ebcf4d62ad79249a7aca2ab11875b
|
Provenance
The following attestation bundles were made for investigation-0.1.2a3-py3-none-any.whl:
Publisher:
publish.yml on DeliYuxiang/Investigation
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
investigation-0.1.2a3-py3-none-any.whl -
Subject digest:
4aa00ba0dd6aa543c362a91eb482b29e0007e2e3087b48b33ad6c89706ae55ec - Sigstore transparency entry: 1059355202
- Sigstore integration time:
-
Permalink:
DeliYuxiang/Investigation@72f4ab1f16e910bb87df93f14c03ad28f9369570 -
Branch / Tag:
refs/tags/v0.1.2a3 - Owner: https://github.com/DeliYuxiang
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@72f4ab1f16e910bb87df93f14c03ad28f9369570 -
Trigger Event:
push
-
Statement type: