Skip to main content

A minimal library to manage reproducible experiments.

Project description

expyro ๐Ÿงชโœจ

A minimal, type-safe 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]"

# For developers (building, publishing)
pip install "expyro[dev]"

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

1. Define Your Experiment ๐Ÿงช

Decorate your 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.
@expyro.experiment(root=Path("runs"), name="my_awesome_experiment")
def train_model(config: TrainConfig) -> dict[str, float]:
    # Your brilliant (or "it should work") code 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)
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
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("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.
        โ”‚   โ”œโ”€โ”€ data/                     # ๐Ÿ’พ Your custom files live here (from `hook`)
        โ”‚   โ”‚   โ””โ”€โ”€ training_log.txt
        โ”‚   โ”œโ”€โ”€ plots/                    # ๐ŸŽจ Home for your beautiful graphs
        โ”‚   โ”‚   โ””โ”€โ”€ create_plot.pdf
        โ”‚   โ””โ”€โ”€ tables/                   # ๐Ÿ“‹ Home for your elegant tables
        โ”‚       โ””โ”€โ”€ create_table.csv
        โ””โ”€โ”€ 14:22:10.456 1a2b3c4d/        # Another run! You've been busy!
            โ”œโ”€โ”€ config.pickle
            โ””โ”€โ”€ result.pickle

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.1.tar.gz (10.2 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.1-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: expyro-0.0.1.tar.gz
  • Upload date:
  • Size: 10.2 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.1.tar.gz
Algorithm Hash digest
SHA256 54d1fc9ab604c9f3e0066ebd75332c780311996701b66a5cd39d5dcefb315e01
MD5 b690dc3b92761c91bd78eb00f8ee5f3f
BLAKE2b-256 9a9dc5a62f681b5080c795a57d4b70682e0a150eff106159f3b5ce76c68489be

See more details on using hashes here.

Provenance

The following attestation bundles were made for expyro-0.0.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: expyro-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 9.5 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b00e4db90e5ee99f2e1a21e6a1942dcc6c37308bed11dd2b0610154d28d6e6bc
MD5 2ddd9950d4f52bc3f43db24afe3e6a1b
BLAKE2b-256 2cbc6f4c4ce9493e95c58734f2c9a4392cc24287afe48079d3bfb04b80e6dbfc

See more details on using hashes here.

Provenance

The following attestation bundles were made for expyro-0.0.1-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