Skip to main content

A minimal library to manage reproducible experiments.

Project description

expyro ๐Ÿงชโœจ

A minimal Python library to stop your experiments from being a hot mess. Because "it worked on my machine" is not a valid scientific publication.

expyro is your new lab assistant ๐Ÿง‘โ€๐Ÿ”ฌ that automatically organizes your chaos: configurations, results, plots, and even that random log file you swear you'll look at later.

Features at a Glance ๐Ÿ‘€

  • ๐Ÿ—‚๏ธ Structured Experiment Tracking: No more final_final_v2_test.py files. Each run gets its own fancy, timestamped folder. Look organized, even if you're not.
  • ๐ŸŽฏ Type Safety: Your config isn't just a bunch of random numbers. It's a well-defined bunch of random numbers! Thanks, type hints!
  • โ™ป๏ธ Reproducibility: Relive the magic (or the horror) of any past run. Perfect for when your advisor asks "can we get the results from last Tuesday?".
  • ๐Ÿ“Š Artifact Generation: Automatically save your beautiful plots and tables. Make your future thesis-writing self cry tears of joy.
  • ๐Ÿ’พ Data Capture: Easily dump any other file (models, logs, a screenshot of your error) right into the experiment's folder.

Installation ๐Ÿ’ป

Get the core package and become 10x more organized instantly:

pip install expyro

Want More? We Got More! ๐ŸŸ

Level up your experiment-fu with optional extras:

# For making pretty, pretty plots (matplotlib)
pip install "expyro[matplotlib]"

# For turning results into sweet, sweet tables (pandas)
pip install "expyro[pandas]"

# I want it ALL! ๐Ÿค‘
pip install "expyro[all]"

Quickstart: From Chaos to Clarity in 60 Seconds โฑ๏ธ

1. Define Your Experiment ๐Ÿงช

Decorate your experiment function. It's like putting a lab coat on it.

from dataclasses import dataclass
from pathlib import Path
import expyro

# Step 1: Define your config. This is your recipe.
@dataclass
class TrainConfig:
    learning_rate: float = 0.01 # The spice of life
    batch_size: int = 32        # The bigger, the better (until it crashes)
    epochs: int = 10            # The "are we there yet?" parameter

# Step 2: Declare your experiment. Give it a home ("runs/") and a name.
# Your experiment must take exactly one argument as a config.
# The input and output must be typed. 
@expyro.experiment(root=Path("runs"), name="my_awesome_experiment")
def train_model(config: TrainConfig) -> dict[str, float]:
    # Your brilliant (or "it should work") experiment logic goes here.
    final_loss = 0.1 * config.learning_rate
    final_accuracy = 0.9

    # Return whatever you want to remember
    return {"final_loss": final_loss, "final_accuracy": final_accuracy}

2. Run It! ๐Ÿƒโ€โ™‚๏ธ

Call your experiment. Watch the magic happen.

if __name__ == "__main__":
    cfg = TrainConfig(learning_rate=0.01, batch_size=32, epochs=10)
    run = train_model(cfg) # This saves everything! You're welcome.
    print(f"Run completed! Data is chilling in: {run.path}")

3. Make It Fancy! ๐ŸŽจ

Automatically save plots and tables. Impress everyone.

import matplotlib.pyplot as plt
import pandas as pd

# Artist function: Takes config & result, returns a masterpiece (figure) or even a nested string dict of masterpieces
def create_plot(config: TrainConfig, result: dict) -> plt.Figure:
    fig, ax = plt.subplots()
    ax.bar(["Loss", "Accuracy"], [result["final_loss"], result["final_accuracy"]])
    ax.set_title("How Did We Do?")
    return fig

# Analyst function: Takes config & result, returns a sweet, sweet table (or a nested string dict of tables)
def create_table(config: TrainConfig, result: dict) -> pd.DataFrame:
    return pd.DataFrame([{"metric": k, "value": v} for k, v in result.items()])

# Stack decorators like a pro! The order is bottom-up.
@expyro.plot(create_plot, file_format="pdf") # Save a high-res PDF
@expyro.table(create_table)                  # Save a CSV table
@expyro.experiment(root=Path("runs"), name="fancy_experiment")
def train_and_analyze(config: TrainConfig) -> dict:
    # ... your code ...
    return {"final_loss": 0.1, "final_accuracy": 0.9}

4. Save ALL THE THINGS! ๐Ÿ’พ

Use hook to save anything else right into the experiment's folder.

@expyro.experiment(root=Path("runs"), name="experiment_with_everything")
def train_with_logging(config: TrainConfig) -> dict:
    # Save a log file
    with expyro.hook("logs/training_log.txt", "w") as f:
        f.write(f"Let's hope this LR {config.learning_rate} works...\n")
        f.write("Epoch 1: Loss=0.5 ๐Ÿ˜ฌ\n")
        f.write("Epoch 2: Loss=0.2 ๐Ÿ˜Š\n")

    # Save a model file (pytorch example)
    # with expyro.hook("best_model.pt", "wb") as f:
    #    torch.save(model.state_dict(), f)

    return {"final_loss": 0.1}

5. Analyze Your Glory (or Mistakes) ๐Ÿ”

Iterate over past runs like a data archaeologist.

# Your experiment is now also a container for all its runs!
my_experiment = train_model # This is your decorated function

print("Behold, all my past runs:")
for run in my_experiment: # ๐Ÿš€ Iterate over everything!
    print(f"Run {run.path.name}: Config={run.config}, Result={run.result}")

# Load a specific run from its path
that_one_run = my_experiment["2024-05-27/12:30:45.123 abcdef00"]
print(f"Ah yes, the run where loss was: {that_one_run.result['final_loss']}")

What's In The Box? ๐Ÿ“ฆ (The Project Structure)

Hereโ€™s how expyro organizes your brilliance:

runs/
โ””โ”€โ”€ my_awesome_experiment/    # Your experiment name
    โ””โ”€โ”€ 2024-05-27/           # The date (so you know when you did the work)
        โ”œโ”€โ”€ 12:30:45.123 abcdef00/        # Time & unique ID (so you can find it)
        โ”‚   โ”œโ”€โ”€ config.pickle             # ๐Ÿ—ƒ๏ธ Your configuration, pickled.
        โ”‚   โ”œโ”€โ”€ result.pickle             # ๐Ÿ“Š Your results, also pickled.
        โ”‚   โ”œโ”€โ”€ artifacts/
        โ”‚   โ”‚   โ”œโ”€โ”€ plots/                # ๐ŸŽจ Home for your beautiful graphs
        โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ create_plot.pdf
        โ”‚   โ”‚   โ””โ”€โ”€ tables/               # ๐Ÿ“‹ Home for your elegant tables
        โ”‚   โ”‚       โ””โ”€โ”€ create_table.csv
        โ”‚   โ””โ”€โ”€ data/                     # ๐Ÿ’พ Your custom files live here (from `hook`)
        โ”‚       โ””โ”€โ”€ logs/
        โ”‚           โ””โ”€โ”€ training_log.txt
        โ””โ”€โ”€ 14:22:10.456 1a2b3c4d/        # Another run! You've been busy!
            โ”œโ”€โ”€ config.pickle
            โ””โ”€โ”€ result.pickle

CLI Time Travel Machine โณ๐Ÿ’ป

Prefer the command line life? expyro scans your project for decorated experiments and hands each one its own subcommand. It's like giving every lab rat a keyboard. ๐Ÿ€

# Run a fresh experiment
expyro my_awesome_experiment run --learning-rate 0.01 --batch-size 32

# Reproduce an old run with the exact same config
expyro my_awesome_experiment reproduce "2024-05-27/12:30:45.123 abcdef00"

# Redo an artifact when you forgot to save that plot ๐ŸŽจ
expyro my_awesome_experiment redo plots "2024-05-27/12:30:45.123 abcdef00"

Why so many verbs? Because reproducibility is king ๐Ÿ‘‘:

  • run starts a brand-new adventure and saves everything.
  • reproduce reruns an experiment with the original config, giving you a carbon-copy run for free.
  • redo regenerates plots or tables for an existing run, so you can tweak your visuals without touching the science.

All from the shell, all consistent, all reproducible. ๐Ÿ”

For detailed information for your specific setup, run

expyro --help

from the root directory of your project.

License ๐Ÿ“„

MIT License. Go forth and experiment! Just maybe use this library first.


Now go forth and reproduce! ๐Ÿš€

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

expyro-0.0.2.tar.gz (15.6 kB view details)

Uploaded Source

Built Distribution

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

expyro-0.0.2-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

File details

Details for the file expyro-0.0.2.tar.gz.

File metadata

  • Download URL: expyro-0.0.2.tar.gz
  • Upload date:
  • Size: 15.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for expyro-0.0.2.tar.gz
Algorithm Hash digest
SHA256 560b7a509a557964b8cc05d69c6fe073d995c4bb3b85ac3bdc9056c7152d9929
MD5 dfeda4801d45a8afc2b2985de791fefe
BLAKE2b-256 753610b329d89be457e087c17499b2dca6c1ff4017d70a09b2b291f71ace1b21

See more details on using hashes here.

Provenance

The following attestation bundles were made for expyro-0.0.2.tar.gz:

Publisher: pypi-release.yml on lukashaverbeck/expyro

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

File details

Details for the file expyro-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: expyro-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 12.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for expyro-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 db4a3e45c476d229b3fa03baca2a560b64dd24081de07ff0f67de73e76ba7680
MD5 3d55f840b12b766e61302c52db5c54d4
BLAKE2b-256 b0192a5996f1860dc6fefc0c5a077d2c84c3c06af30833d13e524ef748920db0

See more details on using hashes here.

Provenance

The following attestation bundles were made for expyro-0.0.2-py3-none-any.whl:

Publisher: pypi-release.yml on lukashaverbeck/expyro

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