Metadata-driven ML pipelines for labeled structured data
Project description
XDFlow
Metadata-driven ML pipelines for labeled structured data
xdflow is a machine learning framework that leverages metadata in labeled structured data. Built on xarray objects, it uses dimensions and coordinates such as trial, channel, time, stimulus, session, and subject as pipeline context for transforms, prediction, cross-validation, tuning, and scoring.
That lets the pipeline do more for you:
- Shape-preserving transforms operate on named dimensions, so
per_dim="trial"means normalize each trial independently using statistics over the remaining dimensions. - Target, group, session, and subject coordinates drive validation without custom split code.
- The pipeline knows which steps are stateful and which are reusable, so expensive stateless work runs once across folds and tuning trials.
- Predictions, scores, and out-of-fold outputs stay tied to the coordinates that produced them, which makes alignment mistakes easier to catch.
sklearn-compatible estimators — sklearn, LightGBM, XGBoost, or your own — drop in via SKLearnTransformer and SKLearnPredictor.
For comparison, in a plain NumPy/sklearn workflow, structure like this usually becomes side data:
X.shape # (180, 100) # was (180, 4, 25)
y # was a coordinate
sessions # tracked separately
channel_names # tracked separately
xdflow removes this side-data bookkeeping by making structure part of the pipeline itself.
Installation
# Core framework (minimal dependencies)
pip install xdflow
# With hyperparameter tuning
pip install xdflow[tuning]
# With all extras (LightGBM, visualization, MLflow, spectral analysis)
pip install xdflow[all]
Requirements: Python 3.11+
Quick Example
This example works with the core install. A full runnable version lives at examples/quickstart.py.
import numpy as np
import xarray as xr
from sklearn.linear_model import LogisticRegression
from xdflow.composite import Pipeline
from xdflow.core import DataContainer
from xdflow.cv import KFoldValidator
from xdflow.transforms.basic_transforms import FlattenTransform
from xdflow.transforms.normalization import ZScoreTransform
from xdflow.transforms.sklearn_transform import SKLearnPredictor
rng = np.random.default_rng(0)
stimuli = np.repeat(["rest", "tone", "odor"], 60)
rng.shuffle(stimuli)
values = rng.normal(0.0, 1.2, size=(stimuli.size, 4, 25))
values[stimuli == "tone", 1, 8:15] += 1.5
values[stimuli == "odor", 2, 14:22] += 1.5
data = xr.DataArray(
values,
dims=("trial", "channel", "time"),
coords={
"trial": np.arange(stimuli.size),
"channel": [f"ch{i}" for i in range(4)],
"time": np.linspace(-0.2, 0.8, 25),
"stimulus": ("trial", stimuli),
},
)
container = DataContainer(data)
pipeline = Pipeline(
name="core_quickstart",
steps=[
("zscore", ZScoreTransform(per_dim="trial")),
("flatten", FlattenTransform(dims=("channel", "time"))),
(
"classifier",
SKLearnPredictor(
LogisticRegression,
sample_dim="trial",
target_coord="stimulus",
max_iter=500,
),
),
],
)
cv = KFoldValidator(
n_splits=5,
shuffle=True,
random_state=0,
stratify_coord="stimulus",
scoring="f1_weighted",
verbose=False,
)
cv.set_pipeline(pipeline)
score = cv.cross_validate(container, verbose=False)
print(f"Weighted F1: {score:.3f}")
# Coordinates stay attached, and stateful steps are refit per fold.
Key Features
- Dimension contracts: transforms declare the dimensions they consume and produce, so invalid reshapes and step handoffs fail earlier.
- Composition primitives: sequential
Pipeline, parallelTransformUnion, conditionalSwitchTransform, per-groupGroupApplyTransform, and toggleableOptionalTransform. - Leakage-aware cross-validation: validators split on named trial, target, and group coordinates; stateful steps refit only on training folds; out-of-fold predictions are emitted for stacking and ensembles.
- Fold-invariant caching: expensive stateless work such as spectrograms or filtering can run once and be reused across folds and tuning trials.
- Hyperparameter tuning: Optuna-based search across pipeline architectures, reusable static-prefix caching across tuning trials, optional MLflow logging, and explicit seed management.
- Pluggable estimators: any class implementing the sklearn API, including sklearn itself, LightGBM, XGBoost, or your own, drops into the pipeline via
SKLearnTransformerandSKLearnPredictor. - Multi-output support: a unified interface for multi-target regression, multilabel classification, and sample-weighted training with sklearn-compatible estimators.
- Explicit API contracts: focused transform, predictor, and validation interfaces keep custom code small enough to write, test, review, and generate with LLM coding tools.
Documentation
XDFlow is designed for custom transforms, predictors, and validation policies. See Writing Custom Transforms and Writing Custom Cross-Validators for examples.
Quick Links:
- Data Contract
- Installation & Setup
- 5-Minute Core Quickstart
- Core Concepts
- Tutorials
- Writing Custom Transforms
- Writing Custom Cross-Validators
- Using XDFlow With LLMs
- API Reference
Contributing
We welcome contributions! Whether you're:
- Adding a new transform
- Improving documentation
- Reporting bugs
- Requesting features
- Sharing use cases
See CONTRIBUTING.md for guidelines.
Early adopters especially welcome - the API is still stabilizing, and your feedback shapes the future of this project.
Development Setup
This project uses uv for dependency management.
# Install uv (if you don't have it)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Clone and install
git clone https://github.com/canaery/xdflow.git
cd xdflow
uv sync --all-extras # creates .venv and installs everything
# Run commands via uv
uv run pytest # run tests
uv run ruff check xdflow tests examples # lint
# Or activate the venv directly
source .venv/bin/activate
pytest
License
MIT License - see LICENSE for details.
Acknowledgments
- xarray - Labeled multidimensional arrays
- scikit-learn - ML fundamentals
- Optuna - Hyperparameter optimization
- MLflow - Experiment tracking
Contact
- Lead maintainer: Julien Bloch
- GitHub Issues: Report bugs or request features
- Discussions: Ask questions, share ideas
The repository is hosted under canaery/xdflow for continuity with the project's original organization name.
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 xdflow-0.2.0.tar.gz.
File metadata
- Download URL: xdflow-0.2.0.tar.gz
- Upload date:
- Size: 621.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
80903081415408e79fb0c3b4cdfbe795f010591d167492d66cb67b39b73687a6
|
|
| MD5 |
6f928e258a8f7f4076c48ab1661ef26e
|
|
| BLAKE2b-256 |
2b2d009c65fcbfdff671946ff24cafae6d75c426ba288bfbc80d9d8a79f6592e
|
Provenance
The following attestation bundles were made for xdflow-0.2.0.tar.gz:
Publisher:
ci.yml on general-sense/xdflow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xdflow-0.2.0.tar.gz -
Subject digest:
80903081415408e79fb0c3b4cdfbe795f010591d167492d66cb67b39b73687a6 - Sigstore transparency entry: 1700921455
- Sigstore integration time:
-
Permalink:
general-sense/xdflow@387c975d485529c7e81cb4293fedfa34f65fe0c1 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/general-sense
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@387c975d485529c7e81cb4293fedfa34f65fe0c1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file xdflow-0.2.0-py3-none-any.whl.
File metadata
- Download URL: xdflow-0.2.0-py3-none-any.whl
- Upload date:
- Size: 183.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42a5f52e7e6a10a37266be3f8d14e506b4fa2cb8ff5ace24ccaae55a0feb396f
|
|
| MD5 |
03ef37f0cf23309b5189dc25d6e9ed97
|
|
| BLAKE2b-256 |
7600bafd1c0e895bb24c0031043ffe57825d0b095344d2d6a6a883e34152b0b6
|
Provenance
The following attestation bundles were made for xdflow-0.2.0-py3-none-any.whl:
Publisher:
ci.yml on general-sense/xdflow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xdflow-0.2.0-py3-none-any.whl -
Subject digest:
42a5f52e7e6a10a37266be3f8d14e506b4fa2cb8ff5ace24ccaae55a0feb396f - Sigstore transparency entry: 1700921515
- Sigstore integration time:
-
Permalink:
general-sense/xdflow@387c975d485529c7e81cb4293fedfa34f65fe0c1 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/general-sense
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@387c975d485529c7e81cb4293fedfa34f65fe0c1 -
Trigger Event:
push
-
Statement type: