Combinatorial Fusion Analysis for Python
Project description
Syzygy CFA
Combinatorial Fusion Analysis for Python — squeeze more performance out of the models you already have, by finding the best way to combine them. 🧩
Syzygy CFA implements Combinatorial Fusion Analysis (CFA) — a principled way to combine the outputs of several models (classifiers, regressors, rankers) rather than pick a single "best" one. Instead of guessing which ensembling recipe will work, Syzygy CFA systematically tries every model subset and every fusion strategy, and tells you which one actually performs best on held-out data.
It ships in two flavours:
- 🔧
CombinatorialFusion— a low-level analyzer that works directly on arrays of predictions, for full control. - 🤖
ClassifierFusion/RegressorFusion— scikit-learn-style ensembles that wrap a list of already-fitted models and pick the best fusion strategy for you.
Table of Contents
- Features
- Installation
- Quick Start
- How It Works
- Supported Metrics
- Running the Tests
- Acknowledgements
- License
✨ Features
- No retraining required —
ClassifierFusion/RegressorFusionaccept models you've already trained; Syzygy CFA only learns how to combine them. - Exhaustive strategy search — every non-empty subset of models is tried, in both score-space and rank-space, with three weighting schemes each (simple average, performance-weighted, diversity-weighted).
- Robust weight estimation — strategies are scored across multiple folds/seeds and averaged, not picked from a single lucky split.
- scikit-learn compatible —
ClassifierFusion/RegressorFusionsubclassBaseEstimator, soget_params(),set_params(), and pipelines work as expected. - Metric-agnostic — plug in any of the built-in classification, regression, or ranking metrics (see Supported Metrics).
📦 Installation
pip install syzygy-cfa
or, for local development:
git clone https://github.com/OlivierBeq/syzygy-cfa.git
cd syzygy-cfa
pip install -e .
Requires Python 3.10+, numpy, pandas, scipy, and scikit-learn.
🚀 Quick Start
Fusing already-fitted models
This is the recommended entry point: train your own models however you like, then let Syzygy CFA figure out how best to combine them on a held-out set.
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from syzygy import ClassifierFusion
# Models trained beforehand, on your own training set — Syzygy CFA never touches this step.
lr = LogisticRegression().fit(X_train, y_train)
rf = RandomForestClassifier().fit(X_train, y_train)
svm = SVC(probability=True).fit(X_train, y_train)
# `X_holdout, y_holdout` is data these models have NOT been trained on.
fusion = ClassifierFusion(
estimators=[("lr", lr), ("rf", rf), ("svm", svm)],
metric="roc-auc", # the metric used to pick the best fusion strategy
cv=5, # folds carved out of X_holdout to estimate weights robustly
)
fusion.fit(X_holdout, y_holdout)
print(fusion.best_combination_) # e.g. "rf&svm_wps"
print(fusion.fusion_results_) # every strategy that was tried, ranked best-first
# Use it on new data exactly like any scikit-learn classifier.
fusion.predict_proba(X_new)
fusion.predict(X_new)
RegressorFusion works the same way for regression models, using .predict() only:
from syzygy import RegressorFusion
fusion = RegressorFusion(estimators=[("ridge", ridge), ("rf", rf), ("svr", svr)], metric="mae")
fusion.fit(X_holdout, y_holdout)
fusion.predict(X_new)
Low-level array-based analysis
If you already have raw prediction arrays (e.g. from a cross-validation loop across several seeds) and just want
the analysis, use CombinatorialFusion directly. Its arguments share terminology with
ClassifierFusion/RegressorFusion: metric is the same, and holdout_predictions is the array equivalent of
what those estimators compute internally, on the X passed to .fit():
from syzygy import CombinatorialFusion
analyzer = CombinatorialFusion(
model_names=["xgb", "rf", "svm"],
holdout_predictions=[xgb_holdout_preds, rf_holdout_preds, svm_holdout_preds], # one array (or list of arrays) per model
test_predictions=[xgb_test_preds, rf_test_preds, svm_test_preds],
y_holdout=y_holdout,
y_test=y_test,
)
results = analyzer.analyze(metric="roc-auc") # ranked DataFrame of every strategy, best first
results.head()
🧠 How It Works
For n models, CFA looks at every non-empty subset and, for each one, builds several candidate predictions:
| Suffix | Space | Combination |
|---|---|---|
| (none) | score | single model |
_r |
rank | single model |
_ups |
score | simple average across the subset |
_ups_r |
rank | simple average across the subset |
_wps |
score | weighted by each model's Performance Strength (PS) |
_wps_r |
rank | weighted by each model's Performance Strength |
_ds |
score | weighted by each model's Diversity Strength (DS) |
_ds_r |
rank | weighted by each model's Diversity Strength |
- Performance Strength (PS) is how well a model scores on its own, on held-out data.
- Diversity Strength (DS) is how different a model's predictions are from the rest of the ensemble — models that disagree more with the pack can contribute more complementary information.
Every one of these candidates is scored against your chosen metric, across every seed/fold, and averaged. The
result is a single ranked table (analyze() / fusion_results_) — no guessing which ensembling trick to reach for.
📏 Supported Metrics
Pass any of these names as metric, whether to ClassifierFusion/RegressorFusion or to
CombinatorialFusion.analyze() / .combine():
| Classification | Regression | Ranking / Correlation |
|---|---|---|
roc-auc, pr-auc |
mse, rmse, mae, r2 |
spearman, kendall, pearson |
f1, micro-f1, macro-f1 |
||
precision, recall, accuracy, kappa |
||
rp@k, pr@k |
🧪 Running the Tests
pip install -e . pytest
pytest tests/
🙏 Acknowledgements
Syzygy CFA draws inspiration from mquazi/cfanalysis, an earlier open-source implementation of Combinatorial Fusion Analysis for ADMET modelling, and the accompanying paper:
Jiang N., Quazi M., Schweikert C., Hsu F., Oprea T. & Sirimulla S.
Enhancing ADMET Property Models Performance through Combinatorial Fusion Analysis.
ChemRxiv. 29 November 2023.
DOI: https://doi.org/10.26434/chemrxiv-2023-dh70x
Syzygy CFA is an independent implementation (not a fork, and not affiliated with the original authors) with a
different API, a different internal architecture, and a scikit-learn-compatible estimator layer that operates on
already-fitted models rather than raw prediction arrays. tests/test_reference_example.py uses example data
copied from that repository (see tests/data/reference_cfanalysis/README.md for provenance) to cross-check
Syzygy CFA's output against an independent computation.
📄 License
Released under the MIT License.
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 syzygy_cfa-0.0.1.dev0.tar.gz.
File metadata
- Download URL: syzygy_cfa-0.0.1.dev0.tar.gz
- Upload date:
- Size: 17.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e82775db555c216ba4f8027596595b9fe6638b2605becb8d3be4caed45787950
|
|
| MD5 |
5ea98a39a1d957c70cb8dcb9b33ae2ab
|
|
| BLAKE2b-256 |
774b6b259b236ca3f11d13b0ede4e633aa85dc31625484736bbd986250a04b60
|
File details
Details for the file syzygy_cfa-0.0.1.dev0-py3-none-any.whl.
File metadata
- Download URL: syzygy_cfa-0.0.1.dev0-py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51930a867ad9f11985bfeb32fcb6b77dccfd4020cfe8342380788048c0521303
|
|
| MD5 |
d52542e00fdccfb8b40caeef83aa9155
|
|
| BLAKE2b-256 |
bfff2cd6529b6bc232438dc97e49e33337fef6ab93ccd2b866aa5ac46f04e23e
|