Skip to content

Bring-your-own-model

mli interprets a model you trained elsewhere through two entry points, picked by whether mli has a native adapter for the model.

In short

  • A supported tree ensemble or glass-box model goes to fit_profiler: the full native surface.
  • Any other scorer with predict_proba / predict goes to monitor_predictions(model=...).
  • With only the scores, pass monitor_predictions(predictions=...).
  • result.capabilities.backend says which path ran: native, lite_model or lite_predictions.
You have Use Backend What runs
A model mli has an adapter for fit_profiler native native profiling plus requested optional stages; geometry and rule support depend on the family
A model with predict_proba / predict but no adapter monitor_predictions lite_model surrogate / error tree / archetype-lite / metrics / drift / fairness
A tabular foundation model (an in-context learner) monitor_predictions lite_model the same lite path: an in-context learner has no leaf structure and exact SHAP is intractable, so there is no native adapter
Only predictions (no model) monitor_predictions lite_predictions the same lite path, with no model call
from parleml_mli import (
    ProfilingConfig,
    RulesConfig,
    fit_profiler,
    monitor_predictions,
    TaskType,
)

Supported models

The native path (fit_profiler) is taken only for models mli has an adapter for. These fall into two tiers by how archetypes are built:

Leaf-space — archetypes from tree-leaf co-occurrence, plus IF-THEN rule extraction:

  • CatBoost — CatBoostClassifier, CatBoostRegressor, CatBoostRanker
  • LightGBM — LGBMClassifier, LGBMRegressor, LGBMRanker, lightgbm.Booster
  • XGBoost — XGBClassifier, XGBRegressor, XGBRanker, xgboost.Booster
  • scikit-learn ensembles — RandomForest, ExtraTrees, GradientBoosting (Classifier / Regressor)

SHAP-space — archetypes built from SHAP values instead of per-sample leaves. Rule support is separate from archetype geometry: HGB and single-tree classifiers have tree-rule extractors; linear and additive models expose their native structure rather than the same tree-mining surface:

  • HistGradientBoostingClassifier / Regressor
  • DecisionTreeClassifier / Regressor
  • EBM — ExplainableBoostingClassifier / Regressor
  • RuleFit — RuleFitClassifier / Regressor
  • scikit-learn linear / GLM — LogisticRegression, LinearRegression, Ridge, Lasso, ElasticNet, SGDClassifier / SGDRegressor, PoissonRegressor, GammaRegressor, TweedieRegressor

Any other estimator that exposes predict_proba / predict (custom wrappers, Pipelines, neural nets) runs the lite path via monitor_predictions; passing only predictions runs the predictions-only path.

Supported tasks

Both entry points handle binary classification (the default, task_type=TaskType.BINARY), multiclass (profiled as a primary-class one-vs-rest slice with a per-class fan-out), and regression (task_type=TaskType.REGRESSION). They are not classification-only.

Native — a recognised model

If your model is in the supported list above, call fit_profiler directly for the full surface. With a binary y it profiles the positive class — the model's classes_[1], the probability column every artifact scores — whatever the labels are (0/1, 1/2, "no"/"yes", booleans); multiclass and regression run their own fan-out / all-rows path:

result = fit_profiler(
    X=X_train,
    y=y_train,
    model=my_lgbm,
    X_test=X_test,
    y_test=y_test,
    config=ProfilingConfig(rules=RulesConfig()),
)
assert result.capabilities.backend == "native"
print(result.target_.positive_label, result.target_.source)   # e.g. "yes" model_classes

positive_class= names the positive label explicitly — by string or numeric form, so a stored form value such as "True" or "1.0" names the model's True / 1.0; with a fitted model it must be model.classes_[1] (anything else raises rather than silently explaining the other class). The resolved answer is on result.target_, and the binary decision cut every threshold-aware artifact — error analysis included — used on result.threshold_ (result.decision_threshold is its value).

Labels need no preprocessing

Pass y in the model's own labels. Rows with a missing label are rejected (drop or impute them first) instead of being assigned a class.

Lite — an unrecognised model

A model exposing predict_proba / predict that mli has no native adapter for (a custom wrapper, a pipeline, a neural net) runs the lite path — a decision-tree surrogate, error tree, archetype-lite clustering, holdout metrics, drift, and fairness. monitor_predictions treats the model as an opaque scorer:

result = monitor_predictions(
    X=X_train,
    y=y_train,
    model=my_custom_estimator,      # has predict_proba, not in the adapter registry
    X_test=X_test, y_test=y_test,
    mode="all",                     # surrogate + error + archetype_lite + metrics
    surrogate_engine="lgbm",
)
assert result.capabilities.backend == "lite_model"

Lite — predictions only

When you can't ship the model at all, hand over its scores:

result = monitor_predictions(
    X=X_train,
    y=y_train,
    predictions=my_scores,          # 1-D array of probabilities / values
    predictions_test=my_test_scores,
    X_test=X_test, y_test=y_test,
    task_type=TaskType.BINARY,
)
assert result.capabilities.backend == "lite_predictions"

Inspect result.capabilities to see exactly which artifacts the chosen backend was able to produce, then save and view as usual:

result.save("out/byo_profiling.joblib")

See the monitor_predictions reference, the fit_profiler reference, and Configuration for every tuning section.

Next