#4216·pycaret

[Bug] `predict_model` silently drops `Anomaly_Score` for bare estimators because `decision_function` uses raw `X`

Author: saitejabandaru-inCreated Jul 17, 2026Updated Jul 22, 2026

Describe the bug

In PyCaret 4.0's predict_model implementation within experiment.py, there is a bug affecting anomaly detection tasks when a bare estimator (rather than a Pipeline) is passed in.

The method correctly identifies if preprocessing is needed for a bare estimator and transforms X into X_for_pred:

python
        if preprocessor is not None and not estimator_is_pipeline:
            # Transform X through the legacy preprocessing chain first.
            X_for_pred = preprocessor.transform(X)
        else:
            X_for_pred = X

        preds = np.asarray(estimator.predict(X_for_pred))

However, when generating the Anomaly_Score column, it incorrectly passes the raw, un-preprocessed X to the decision_function:

python
        elif self.task == TaskType.ANOMALY:
            out["Anomaly"] = preds
            if hasattr(estimator, "decision_function"):
                try:
                    out["Anomaly_Score"] = estimator.decision_function(X)  # <-- BUG: Should be X_for_pred
                except Exception:  # pragma: no cover — defensive
                    pass

Because decision_function receives the raw X (which may contain categorical variables, NaNs, etc.), it will throw an exception that gets silently swallowed by the try...except Exception: pass block. As a result, the user silently does not get the Anomaly_Score column in their predictions.

Expected Behavior

The anomaly score calculation should use X_for_pred:

python
out["Anomaly_Score"] = estimator.decision_function(X_for_pred)

This mirrors how classification handles predict_proba:

python
proba = estimator.predict_proba(X_for_pred)

Reproduction Steps

python
from pycaret.datasets import get_data
from pycaret.tasks import AnomalyExperiment
from sklearn.ensemble import IsolationForest

df = get_data("anomaly")
exp = AnomalyExperiment(session_id=42, preprocess=True).fit(df)

# Train a bare estimator on the transformed data
X_transformed = exp._fit_state["X_transformed"]
model = IsolationForest(random_state=42).fit(X_transformed)

# Predict using the bare estimator
preds = exp.predict_model(model, data=df)

# Anomaly_Score is missing because decision_function failed on raw 'df' and was silently suppressed
print("Anomaly_Score" in preds.columns) 

Additional context

This bug is present in packages/engine/pycaret/core/experiment.py around line 1625.