Skip to content

FAQ

Why does fit() raise TypeError: Unsupported model type? Decision-point extraction reads the serialized trees and accepts only a LightGBM Booster or an XGBoost Booster. The scikit-learn wrappers (LGBMClassifier, XGBClassifier, …) are not accepted directly — pass the underlying booster instead, e.g. SWIFTMonitor(model=clf.booster_) for LightGBM, or train with the native API (lgb.train).

Why is no p-value ever exactly zero? The permutation test uses the conservative formula \(p = (1 + \#\{\text{permutation score} \ge \text{observed}\}) / (1 + B)\), so the smallest attainable p-value is \(1/(1+B)\). With the default n_permutations=1000 that is roughly 0.001; raise n_permutations when you need finer resolution.

Can I compare two production windows instead of testing against the reference? Yes. score() and test() accept X_compare: the comparison then runs between X and X_compare, while the SHAP transformation (buckets + mean SHAP) is always the one fitted on the reference. See scikit-learn integration.

How are missing values handled? Every feature's bucket set includes a null bucket (index 0). NaN values map to it during transform(), so missingness gets its own mean-SHAP level and a change in the missing-value rate is visible to the drift test. See Buckets.

What happens to a feature the model never splits on? It gets no decision points, so its whole domain is a single catch-all bucket \((-\infty, +\infty)\). Every value transforms to the same mean SHAP, both distributions become identical after transformation, and the feature's SWIFT score is 0 — a feature the model ignores cannot raise a drift alarm. This is intended behavior, not a bug. See Buckets.

What is n_synthetic for? Buckets with zero reference observations have no data to average SHAP over. During fit(), SWIFT samples n_synthetic real reference rows, places the feature value inside the empty bucket, and computes SHAP on those synthetic rows. If no model were available the bucket would fall back to mean_shap = 0.0 with a warning. See Normalization.

Which strings does correction accept? "benjamini-hochberg" (aliases "bh", "fdr") and "bonferroni" (alias "bonf"), case-insensitively; enum members from swift.types.CorrectionMethod also work. Anything else raises ValueError listing the valid values.

The permutation test is slow on large datasets — what can I do? Set max_samples: when the pooled reference + monitoring data exceeds it, both samples are randomly subsampled (preserving the reference/monitoring ratio) before the permutation loop — a significant speedup with negligible impact on statistical power. Lowering n_permutations (e.g. to 200 for exploratory runs) also helps; see configuration.

Do I need to re-fit after changing parameters? Only when the fitted state depends on them: changing model or n_synthetic requires calling fit() again. Test-time parameters — order, n_permutations, alpha, correction, max_samples — are read from the instance on each test() call, so set_params() is enough.