A poniard /ˈpɒnjərd/ or poignard (Fr.) is a long, lightweight thrusting knife (Wikipedia).
Poniard is a scikit-learn companion for multi-model diagnostics. Fit a handful of models, cross-validate them side by side, then answer the questions that actually matter:
- Where do the models fail, and why?
- Is model A really better than B, or is that fold noise?
- Which model is good enough and cheap enough?
Then export a plain sklearn pipeline you own and leave. Not AutoML. Not
end-to-end. Every feature earns its place.
pip install poniardPlotting is an optional extra:
pip install poniard[plot]from sklearn.datasets import make_classification
from poniard import PoniardClassifier
X, y = make_classification(n_samples=200, n_features=10, random_state=42)
clf = PoniardClassifier()
clf.setup(X, y) # configure: infer types, build preprocessing, CV, pipelines
clf.fit(X, y) # cross-validate every estimator
clf.get_results() # leaderboard with a dummy baselinesetup comes first on purpose: it lets you see what fit will do to your
data and modify it before anything is cross-validated. fit(X, y) will also
configure on its own if you skip it, but the preprocessor is never a black box —
inspect clf.feature_types, reassign types, or add preprocessing steps between
the two calls (see the in-depth guide).
Poniard is built around one loop: compare → explain → decide → export.
clf = PoniardClassifier() # or PoniardRegressor()
clf.setup(X, y) # configure, then adjust preprocessing if needed
clf.fit(X, y)
clf.get_results() # mean scores, fit/score timesEvery estimator is cross-validated on the same folds, with a DummyClassifier
/ DummyRegressor baseline included automatically.
ErrorAnalyzer answers where and why your models fail. One call returns a
structured ErrorReport:
from poniard.error_analysis import ErrorAnalyzer
report = ErrorAnalyzer.from_poniard(clf).analyze(X, y)
report.universal_failures # samples every model got wrong
report.disagreement_set # samples where models split (ensembling candidates)
report.lift_by_target # classes/bins over-represented in errors (lift > 1)
report.lift_by_feature # feature values over-represented in errorsclf.compare() # paired fold tests: is A really better than B?
clf.pareto() # best metric vs training time (Pareto front)
clf.best_under(seconds=0.5) # best model within a time budgetmodel = clf.get_estimator("LogisticRegression", retrain=True, X=X, y=y)
# a fitted sklearn.pipeline.Pipeline with no poniard references — deploy it| Area | What you get |
|---|---|
| Error analysis | Universal failures, disagreement sets, lift vs baseline — ranked per sample, sliced by target and features |
| Statistical comparison | Paired fold tests so you stop trusting fold-mean leaderboards |
| Time / quality | Pareto front and best-under-budget helpers |
| Preprocessing | Automatic numeric / categorical / datetime type inference, imputation, encoding, scaling; per-estimator preprocessors (preprocessor_map) — HistGradientBoosting automatically uses a native NaN/categorical profile |
| Tuning | Grid, random, and halving search that re-enters the experiment as a new named estimator |
| Ensembles | Diversity-aware voting / stacking built from your fitted estimators |
| Plotting | Metrics, ROC, confusion matrices, residuals, feature importance (optional, requires [plot]) |
- In-depth guide — the full workflow, preprocessing internals, error-analysis semantics, tuning, ensembles, plotting, and export.
- Examples — runnable scripts, executed in CI so they never go stale:
examples/00_getting_started.py— fit, results, predictionsexamples/01_error_analysis.py— full failure-forensics workflowexamples/02_plotting.py— the plotting APIexamples/03_preprocessing.py— per-estimator preprocessors and the native profile
python examples/00_getting_started.pyEstimators are named by class name, with collision suffixes (_2, _3, ...).
Override names with tuple syntax:
clf = PoniardClassifier(estimators=[("my_lr", LogisticRegression())])
# pipelines: {'my_lr': ..., 'DummyClassifier': ...}PONIARD_TQDM_LEAVE— set to"True"to keep progress bars on screen after fitting completes. Default"False".
3.10–3.13, tested on Linux, macOS, and Windows.
git clone https://github.com/rxavier/poniard.git
cd poniard
uv sync --dev
uv run pytestMIT
