datarobot-model-explainability
Tools and guidance for model explainability, prediction explanations, feature impact analysis, SHAP values, SHAP distributions, anomaly assessment, and model diagnostics. Use when analyzing model explanations, feature impact, SHAP values, SHAP distributions, anomaly assessment, o
Install
npx skills add https://github.com/datarobot-oss/datarobot-agent-skills/tree/main/skills/datarobot-model-explainability
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install datarobot-oss-datarobot-agent-skills@llmmart
git clone https://github.com/datarobot-oss/datarobot-agent-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole datarobot-oss/datarobot-agent-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
DataRobot Model Explainability Skill
This skill covers SHAP insights, XEMP prediction explanations, anomaly explanations, and model diagnostics.
SDK version: Use
datarobot>=3.6.0for the full API set in this skill (ShapDistributionswas added in 3.6;ShapMatrix,ShapImpact, andShapPrevieware available indatarobot>=3.4.0). Usefrom datarobot.insights import ShapMatrix, ...withentity_id=model_id— not legacydatarobot.models.ShapMatrix(project_id/dataset_id).ShapMatrix,ShapImpact,ShapPreview, andShapDistributionsare the canonical SHAP API. The olderdr.PredictionExplanations(XEMP-based) remains available but is the secondary path.
Quick Start
| Goal | API to use | Prerequisites |
|---|---|---|
| SHAP values for all features, all rows | ShapMatrix.create(entity_id=model_id) |
None - universal SHAP |
| Per-row top-feature explanations | ShapPreview.create(entity_id=model_id) |
None |
| Aggregated feature importance via SHAP | ShapImpact.create(entity_id=model_id) |
None |
| SHAP value distributions across features | ShapDistributions.create(entity_id=model_id) |
None |
| SHAP for a filtered segment | dr.DataSlice.create(...) + ShapMatrix.create(..., data_slice_id=...) |
Data slice definition |
| XEMP-based prediction explanations | dr.PredictionExplanations.create(...) |
Feature Impact; PE initialization; dataset uploaded |
| Anomaly explanations (time series) | AnomalyAssessmentRecord.compute(project_id, model_id, ...) |
Anomaly model |
| ROC / lift / confusion (insights) | RocCurve.create(...) / LiftChart.create(...) / ConfusionMatrix.create(...) |
Validation data |
| ROC / lift / confusion (Model helpers) | model.get_roc_curve() / model.get_lift_chart() / model.get_confusion_chart() |
Validation data |
Universal SHAP is the preferred path - no dataset pre-upload or Feature Impact step required.
When to use this skill
Use this skill when you need to explain leaderboard model behavior, compute SHAP insights, use XEMP prediction explanations, analyze anomaly explanations, or retrieve model diagnostics.
Key capabilities
1. SHAP insights
- Compute
ShapMatrix,ShapPreview,ShapImpact, andShapDistributions - Filter insights with
dr.DataSlice
2. XEMP and anomaly explanations
- Use XEMP
dr.PredictionExplanationswhen specifically required - Retrieve time series anomaly assessment records and explanations
3. Diagnostics
- Retrieve ROC, lift, and confusion insights
- Use Model helpers for ROC, lift, confusion, and feature effects
Setup
import datarobot as dr
from datarobot.insights import ShapMatrix, ShapImpact, ShapPreview, ShapDistributions
dr.Client()
Core API: datarobot.insights
import pandas as pd
from datarobot.insights import ShapMatrix, ShapImpact, ShapPreview, ShapDistributions
model_id = "YOUR_MODEL_ID"
matrix = ShapMatrix.create(entity_id=model_id)
df = pd.DataFrame(matrix.matrix, columns=matrix.columns)
impact = ShapImpact.create(entity_id=model_id)
preview = ShapPreview.create(entity_id=model_id)
distributions = ShapDistributions.create(entity_id=model_id)
Use ShapMatrix for full row-by-feature SHAP values, ShapPreview for compact top-driver rows,
ShapImpact for aggregated SHAP importance, and ShapDistributions for per-feature SHAP
distributions. Use source="externalTestSet" plus external_dataset_id for external datasets.
See references/shap_api_reference.md for parameters, exports, and limitations.
Secondary path: XEMP Prediction Explanations
Use dr.PredictionExplanations when XEMP explanations are specifically required (e.g., certain
regulatory contexts, or when SHAP is unavailable for the model type).
Prerequisites (all required before calling .create()):
- Feature Impact must be computed:
model.request_feature_impact()and wait - Prediction explanations initialized:
dr.PredictionExplanationsInitialization.create(...) - Scoring dataset uploaded to the AI Catalog
import datarobot as dr
model = dr.Model.get(project=project_id, model_id=model_id)
model.request_feature_impact().wait_for_completion()
dr.PredictionExplanationsInitialization.create(project_id=project_id, model_id=model_id)
dataset = dr.Dataset.upload("./data/scoring_data.csv")
pe_job = dr.PredictionExplanations.create(
project_id=project_id,
model_id=model_id,
dataset_id=dataset.id,
max_explanations=5, # top N features per row, up to 50
threshold_high=0.5, # only explain rows with prediction >= threshold
threshold_low=0.1, # only explain rows with prediction <= threshold
)
pe_obj = pe_job.get_result_when_complete()
Use pe_obj.get_rows(), pe_obj.get_all_as_dataframe(), or pe_obj.download_to_csv(...) to
retrieve results. For parameters, multiclass modes, and exposure-adjusted predictions, see
references/xemp_pe_reference.md.
Data slices for filtered insights
Use dr.DataSlice when the user asks to explain model behavior for a segment, such as a
region, product line, target class, or high-risk cohort. Pass the resulting data_slice_id into
the datarobot.insights SHAP APIs.
import datarobot as dr
from datarobot.insights import ShapMatrix
data_slice = dr.DataSlice.create(
name="high_income_customers",
filters=[{"operand": "income", "operator": ">", "values": 100000}],
project=project_id,
)
shap_matrix = ShapMatrix.create(
entity_id=model_id,
source="validation",
data_slice_id=data_slice.id,
)
Anomaly assessment (time series models)
For time series anomaly detection models, use AnomalyAssessmentRecord.
from datarobot.models.anomaly_assessment import AnomalyAssessmentRecord
record = AnomalyAssessmentRecord.compute(
project_id=project_id,
model_id=model_id,
backtest=0, # backtest index (int) or "holdout"
source="validation", # "training" or "validation" only
series_id=None, # required for multiseries projects
)
records = AnomalyAssessmentRecord.list(project_id=project_id, model_id=model_id)
latest = record.get_latest_explanations()
regions = record.get_predictions_preview().find_anomalous_regions()
explanations = record.get_explanations_data_in_regions(regions=regions)
ranged = record.get_explanations(
start_date="2024-01-01T00:00:00.000000Z",
end_date="2024-06-01T00:00:00.000000Z",
)
Model diagnostics
Use the same entity_id=model_id pattern as SHAP insights. FeatureEffects / partial dependence
is still retrieved through Model helpers (not in datarobot.insights).
Insights diagnostics (preferred — matches SHAP API)
from datarobot.insights import RocCurve, LiftChart, ConfusionMatrix
roc = RocCurve.create(entity_id=model_id)
lift = LiftChart.create(entity_id=model_id)
confusion = ConfusionMatrix.create(entity_id=model_id)
Model helpers (alternative)
model = dr.Model.get(project=project_id, model_id=model_id)
roc = model.get_roc_curve(source="validation")
lift = model.get_lift_chart(source="validation")
confusion = model.get_confusion_chart(source="validation")
# Feature Impact (non-SHAP) and Feature Effects (partial dependence for top features)
fi = model.get_feature_impact()
feature_effects = model.get_feature_effect(source="validation")
Interpreting SHAP values
- Positive value: feature pushes prediction higher than baseline
- Negative value: feature pushes prediction lower than baseline
- Magnitude: size of influence; larger absolute value = stronger effect
- Sum: all SHAP values for a row sum to
prediction - base_valuein the link-function space base_value: the model's mean prediction (the "no information" baseline)
Example: if base_value = 0.35 and a row's prediction is 0.72, the row's SHAP values sum to
0.37 when link_function = "identity". A feature with SHAP +0.20 contributed 20 units in
that same link-function space above baseline.
When link_function = "logit", SHAP values are in log-odds space. Add feature contributions to
base_value in log-odds space, then use inverse-logit (scipy.special.expit) on the resulting
total to convert it to a probability. Do not apply expit to individual SHAP values as if they
were probability deltas.
Decision guide
Task: explain predictions
|
- Need all features + all rows? -> ShapMatrix.create(entity_id=model_id)
- Need top-N features per row? -> ShapPreview.create(entity_id=model_id)
- Need aggregated importance? -> ShapImpact.compute(entity_id=model_id)
- Need feature SHAP distributions? -> ShapDistributions.create(entity_id=model_id)
- Need a segment/cohort only? -> dr.DataSlice + data_slice_id
- XEMP required (regulatory/type)? -> dr.PredictionExplanations.create(...)
- Time series / anomaly model? -> AnomalyAssessmentRecord.compute(project_id, model_id, ...)
Common errors
| Error | Cause | Fix |
|---|---|---|
SHAP not available for this model |
Unsupported model type, or anomaly-detection model with >1000 features | Check model support; use XEMP PE if SHAP is unavailable |
Feature Impact not computed |
PredictionExplanations prerequisite missing | Run model.request_feature_impact() and wait |
Missing PredictionExplanationsInitialization |
PE not initialized | Call PredictionExplanationsInitialization.create() |
source='holdout' fails |
Holdout not unlocked | Unlock holdout in project settings first |
Empty previews |
No rows in partition | Check partition contains data |
Reference files
references/shap_api_reference.md- full parameter signatures for ShapMatrix, ShapImpact, ShapPreview, ShapDistributionsreferences/xemp_pe_reference.md- PredictionExplanations and PredictionExplanationsInitialization parameter referencescripts/compute_shap_matrix.py- compute and export ShapMatrix to CSV or DataFrame
Resources
Files (datarobot-agent-skills)
-
references
-
shap_api_reference.md 7.4 KB
# SHAP API Reference Full parameter signatures for `datarobot.insights` classes. SDK version: `datarobot>=3.6.0` for the full set below (`ShapDistributions` was added in 3.6; `ShapMatrix`, `ShapImpact`, and `ShapPreview` are available in `datarobot>=3.4.0`) Source: https://datarobot-public-api-client.readthedocs-hosted.com/en/latest-release/insights.html --- ## Import ```python from datarobot.insights import ShapMatrix, ShapImpact, ShapPreview, ShapDistributions ``` --- ## ShapMatrix Raw SHAP values for each feature column and each row. ### `ShapMatrix.create(entity_id, source='validation', **kwargs)` Blocking call - computes and returns a ShapMatrix. | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `entity_id` | str | required | Model ID | | `source` | str | `'validation'` | Partition: `'validation'`, `'crossValidation'`, `'holdout'`, `'externalTestSet'` | | `data_slice_id` | str | None | Optional Data Slice ID to filter the selected partition | | `external_dataset_id` | str | None | Dataset ID from AI Catalog; required when `source='externalTestSet'` | | `quick_compute` | bool | None | If true/unspecified, compute on a 2500-row sample; if false, compute all rows | ### `ShapMatrix.compute(entity_id, source='validation', **kwargs)` Non-blocking - returns a job reference. Same parameters as `.create()`. Call `job.get_result_when_complete()` to wait. ### `ShapMatrix.get(entity_id, source)` Retrieve an already-computed ShapMatrix by model + partition. ### `ShapMatrix.list(entity_id)` List all computed ShapMatrix objects for a model (one per partition computed). ### Attributes | Attribute | Type | Description | |-----------|------|-------------| | `matrix` | list[list[float]] | 2D array: rows x features | | `columns` | list[str] | Feature names (same order as matrix columns) | | `base_value` | float | Model's mean prediction (baseline) | | `link_function` | str | Link function: `'identity'` for regression, `'logit'` for binary classification | | `source` | str | Partition this matrix was computed on | ### Export to DataFrame or CSV After `.create()` / `.compute()`, values are on the result (`matrix`, `columns`): ```python import pandas as pd df = pd.DataFrame(result.matrix, columns=result.columns) ``` `get_as_dataframe` and `get_as_csv` are **classmethods** on `ShapMatrix` (re-fetch from the API). Pass the same `entity_id`, `source`, and optional kwargs used at compute time: ```python df = ShapMatrix.get_as_dataframe(entity_id=model_id, source="validation") csv = ShapMatrix.get_as_csv( entity_id=model_id, source="externalTestSet", external_dataset_id=dataset_id, ) ``` Do not call `result.get_as_dataframe()` — that API shape is for legacy `datarobot.models.ShapMatrix`. ### Notes - Available for blenders - The >1000-feature limitation applies to anomaly-detection models only - When `link_function='logit'`, values are in log-odds space; add contributions to `base_value` in log-odds space, then use inverse-logit (`scipy.special.expit`) on the total. Do not apply `expit` to individual SHAP values as probability deltas --- ## ShapImpact Aggregated feature importance based on SHAP matrix values. ### `ShapImpact.create(entity_id, source='training')` Blocking call. | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `entity_id` | str | required | Model ID | | `source` | str | `'training'` | Source type to use when computing the insight | | `data_slice_id` | str | None | Optional Data Slice ID | | `quick_compute` | bool | None | If true/unspecified, compute on a 2500-row sample; if false, compute all rows | ### `ShapImpact.compute(entity_id, source='training')` Non-blocking. Returns job; call `job.get_result_when_complete()`. ### `ShapImpact.get(entity_id, source=..., ...)` / `ShapImpact.list(entity_id)` Retrieve existing ShapImpact results. Pass the same `source` used when computing the insight. ### Attributes | Attribute | Type | Description | |-----------|------|-------------| | `shap_impacts` | list | Each entry is `[feature_name, normalized, unnormalized]` or a dict with `feature_name`, `impact_normalized`, `impact_unnormalized` | | `base_value` | float or list[float] | Baseline prediction value(s) | | `row_count` | int | Number of rows used for computation | | `capping` | bool | Whether extreme SHAP values were capped | | `link` | str | Link function | ### Notes - `normalized_impact`: impact scaled so features sum to 1.0 - `unnormalized_impact`: raw mean absolute SHAP value for the feature - Results are sorted descending by importance --- ## ShapPreview Per-row top-feature SHAP explanations in a compact "preview" format. ### `ShapPreview.create(entity_id, source='validation', **kwargs)` Blocking. | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `entity_id` | str | required | Model ID | | `source` | str | `'validation'` | Partition: same options as ShapMatrix | | `data_slice_id` | str | None | Optional Data Slice ID | | `external_dataset_id` | str | None | Required when `source='externalTestSet'` | ### `ShapPreview.compute(entity_id, source='validation', **kwargs)` Non-blocking variant. ### Attributes | Attribute | Type | Description | |-----------|------|-------------| | `previews` | list[dict] | Per-row preview data (see structure below) | | `previews_count` | int | Total number of rows | ### `previews` row structure ```python { "row_index": 0, "prediction_value": 0.72, "preview_values": [ { "feature_rank": 1, "feature_name": "income", "feature_value": "85000", "shap_value": 0.18, "has_text_explanations": False, "text_explanations": [], }, # ... top-N features ], } ``` --- ## ShapDistributions Distribution of SHAP values across rows for each feature. ### `ShapDistributions.create(entity_id, source='validation', data_slice_id=None, **kwargs)` Blocking. ### `ShapDistributions.compute(entity_id, source='validation', data_slice_id=None, **kwargs)` Non-blocking. ### Attributes | Attribute | Type | Description | |-----------|------|-------------| | `features` | list[dict] | Per-feature distribution data | | `total_features_count` | int | Total number of features | --- ## Insights diagnostics (non-SHAP) Same `BaseInsight` pattern as SHAP: `create`, `compute`, `get`, `list` with `entity_id=model_id`. | Class | Import | Notable result attributes | |-------|--------|---------------------------| | `RocCurve` | `from datarobot.insights import RocCurve` | `auc`, `roc_points` | | `LiftChart` | `from datarobot.insights import LiftChart` | `bins` | | `ConfusionMatrix` | `from datarobot.insights import ConfusionMatrix` | `confusion_matrix_data`, `global_metrics` | `FeatureEffects` / partial dependence is not in `datarobot.insights`; use `model.get_feature_effect(source=...)` or `model.get_or_request_feature_effect(...)`. --- ## Constraints and limitations | Constraint | Detail | |-----------|--------| | Blenders | SHAP insights are available for blenders | | Feature count | The >1000-feature limitation applies to anomaly-detection models only | | Holdout | `source='holdout'` requires holdout to be unlocked in the project | | Data slices | Use `dr.DataSlice.create()`, `.list()`, or `.get()`, then pass `data_slice_id` | | Custom models | SHAP for custom models requires additional setup (see SHAP insights user guide) | -
xemp_pe_reference.md 5.3 KB
# XEMP Prediction Explanations Reference Parameter reference for `dr.PredictionExplanations` and related classes. SDK version: `datarobot>=2.26` (XEMP API is stable; `datarobot.insights` SHAP API is preferred for new code). Source: https://datarobot-public-api-client.readthedocs-hosted.com/en/latest-release/reference/modeling/insights/prediction_explanations.html --- ## When to use XEMP vs SHAP | Situation | Use | |-----------|-----| | Default / new code | `ShapMatrix` / `ShapPreview` from `datarobot.insights` | | Anomaly-detection models with >1000 features | XEMP PE if SHAP is unavailable | | Regulatory requirement for XEMP | XEMP PE | | Feature Impact methodology required | XEMP PE | --- ## Prerequisites All must be satisfied before calling `PredictionExplanations.create()`: 1. **Feature Impact computed**: ```python job = model.request_feature_impact() job.wait_for_completion() ``` 2. **PredictionExplanationsInitialization created** (one-time per model): ```python dr.PredictionExplanationsInitialization.create(project_id=project_id, model_id=model_id) ``` 3. **Scoring dataset uploaded** to the AI Catalog (`dataset_id` passed to `.create()`). --- ## PredictionExplanationsInitialization ### `PredictionExplanationsInitialization.create(project_id, model_id)` One-time initialization. Safe to call multiple times; check first with `.get()`. ### `PredictionExplanationsInitialization.get(project_id, model_id)` Check whether initialization exists. Raises `ClientError` if not found. ### `PredictionExplanationsInitialization.delete(project_id, model_id)` Delete initialization (forces re-initialization on next `.create()`). --- ## PredictionExplanations ### `PredictionExplanations.create(project_id, model_id, dataset_id, ...)` Submit an async job to compute explanations on a dataset. Call `pe_job.get_result_when_complete()` to retrieve the `PredictionExplanations` result. | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `project_id` | str | required | DataRobot project ID | | `model_id` | str | required | DataRobot model ID | | `dataset_id` | str | required | AI Catalog dataset ID to explain | | `max_explanations` | int | 3 | Top-N feature explanations per row; at most 50 can be returned | | `threshold_high` | float | None | Only explain rows with prediction >= this | | `threshold_low` | float | None | Only explain rows with prediction <= this | | `mode` | `TopPredictionsMode` or `ClassListMode` | predicted class only | For multiclass/clustering: which classes to explain | ### `PredictionExplanations.create_on_training_data(project_id, model_id, ...)` Same as `.create()` but runs on the model's training data instead of an uploaded dataset. ### `PredictionExplanations.get(project_id, prediction_explanations_id)` Retrieve a computed PE object by ID. ### `PredictionExplanations.list(project_id, model_id=None)` List all PE objects for a project (optionally filtered by model). ### Methods on PE result object | Method | Returns | Description | |--------|---------|-------------| | `.get_rows(batch_size=None)` | iterator | Iterate explanation rows | | `.get_all_as_dataframe(exclude_adjusted_predictions=True)` | `pd.DataFrame` | All rows as DataFrame | | `.download_to_csv(filename, exclude_adjusted_predictions=True)` | None | Write to CSV | | `.is_multiclass()` | bool | Whether this is a multiclass explanation | --- ## Explanation row structure Each row from `.get_rows()` has: | Field | Type | Description | |-------|------|-------------| | `row_index` | int | Position in dataset | | `prediction` | float | Model's prediction for this row | | `adjusted_prediction` | float | Exposure-adjusted prediction (if applicable) | | `prediction_explanations` | list[dict] | Feature explanations | Each entry in `prediction_explanations`: ```python { "feature": "income", # feature name "featureValue": "85000", # actual value of the feature "strength": 0.18, # XEMP contribution (positive = increases prediction) "label": "income", # display label "qualitative_strength": "++", # qualitative indicator } ``` --- ## Adjusted predictions (exposure projects) For insurance or other exposure-normalized projects: ```python df = pe_obj.get_all_as_dataframe(exclude_adjusted_predictions=False) # DataFrame now includes 'adjusted_prediction' column ``` --- ## Multiclass / clustering ```python pe_job = dr.PredictionExplanations.create( project_id=project_id, model_id=model_id, dataset_id=dataset.id, mode=dr.models.ClassListMode( ["class_a", "class_b"] ), # specify which classes to explain ) # Check if multiclass pe_obj = pe_job.get_result_when_complete() print(pe_obj.is_multiclass()) ``` --- ## Notes - `max_explanations` can return at most 50 explanations because XEMP computes explanations for the global top 50 features - `threshold_high` and `threshold_low` can be combined to explain only extreme predictions - XEMP explanations use the XEMP methodology (not SHAP); magnitudes are not comparable across models - For SHAP-based explanations, prefer `datarobot.insights.ShapMatrix` / `ShapPreview` with `entity_id=model_id`. Export via `pd.DataFrame(result.matrix, columns=result.columns)` or `ShapMatrix.get_as_dataframe(entity_id=..., source=...)` — not legacy `datarobot.models.ShapMatrix`.
-
-
scripts
-
compute_shap_matrix.py 3.3 KB
#!/usr/bin/env python3 # Copyright (c) 2026 DataRobot, Inc. All rights reserved. # SPDX-License-Identifier: Apache-2.0 """ Compute a ShapMatrix for a DataRobot model and export to CSV or DataFrame. Usage: python compute_shap_matrix.py --model-id <model_id> [--source validation] [--output out.csv] python compute_shap_matrix.py --model-id <model_id> --data-slice-id <slice_id> python compute_shap_matrix.py --model-id <model_id> --source externalTestSet \ --dataset-path ./data/scoring.csv --output out.csv python compute_shap_matrix.py --model-id <model_id> --list-existing """ import argparse from typing import Any import datarobot as dr import pandas as pd from datarobot.insights import ShapMatrix def compute_shap_matrix( model_id: str, source: str = "validation", dataset_path: str | None = None, output_path: str | None = None, data_slice_id: str | None = None, quick_compute: bool | None = None, ) -> Any: external_dataset_id: str | None = None if source == "externalTestSet": if not dataset_path: raise ValueError("--dataset-path required when source=externalTestSet") print(f"Uploading dataset: {dataset_path}") dataset = dr.Dataset.upload(dataset_path) external_dataset_id = dataset.id print(f" Dataset ID: {external_dataset_id}") print(f"Computing ShapMatrix: model={model_id!r} source={source!r} ...") result = ShapMatrix.create( entity_id=model_id, source=source, data_slice_id=data_slice_id, external_dataset_id=external_dataset_id, quick_compute=quick_compute, ) print(f" Features: {len(result.columns)}") print(f" Rows: {len(result.matrix)}") print(f" Base value: {result.base_value:.6f}") print(f" Link: {result.link_function}") if output_path: df = pd.DataFrame(result.matrix, columns=result.columns) df.to_csv(output_path, index=False) print(f" Exported to: {output_path}") return result def main() -> None: parser = argparse.ArgumentParser(description="Compute DataRobot ShapMatrix") parser.add_argument("--model-id", required=True) parser.add_argument( "--source", default="validation", choices=["validation", "crossValidation", "holdout", "externalTestSet"], ) parser.add_argument("--data-slice-id", default=None) parser.add_argument("--dataset-path", default=None) parser.add_argument("--output", default=None) parser.add_argument("--full-compute", action="store_true") parser.add_argument("--list-existing", action="store_true") args = parser.parse_args() dr.Client() if args.list_existing: matrices = ShapMatrix.list(entity_id=args.model_id) print(f"Found {len(matrices)} existing ShapMatrix computation(s):") for m in matrices: print( f" source={m.source} features={len(m.columns)} rows={len(m.matrix)}" ) return compute_shap_matrix( model_id=args.model_id, source=args.source, dataset_path=args.dataset_path, output_path=args.output, data_slice_id=args.data_slice_id, quick_compute=False if args.full_compute else None, ) if __name__ == "__main__": main()
-
-
SKILL.md 10.5 KB
--- name: datarobot-model-explainability description: > Tools and guidance for model explainability, prediction explanations, feature impact analysis, SHAP values, SHAP distributions, anomaly assessment, and model diagnostics. Use when analyzing model explanations, feature impact, SHAP values, SHAP distributions, anomaly assessment, or diagnosing model behavior. --- # DataRobot Model Explainability Skill This skill covers SHAP insights, XEMP prediction explanations, anomaly explanations, and model diagnostics. > **SDK version**: Use `datarobot>=3.6.0` for the full API set in this skill (`ShapDistributions` > was added in 3.6; `ShapMatrix`, `ShapImpact`, and `ShapPreview` are available in > `datarobot>=3.4.0`). Use `from datarobot.insights import ShapMatrix, ...` with > `entity_id=model_id` — not legacy `datarobot.models.ShapMatrix` (`project_id` / `dataset_id`). > `ShapMatrix`, `ShapImpact`, `ShapPreview`, and `ShapDistributions` are the canonical SHAP API. > The older `dr.PredictionExplanations` (XEMP-based) remains available but is the secondary path. --- ## Quick Start | Goal | API to use | Prerequisites | |------|-----------|---------------| | SHAP values for all features, all rows | `ShapMatrix.create(entity_id=model_id)` | None - universal SHAP | | Per-row top-feature explanations | `ShapPreview.create(entity_id=model_id)` | None | | Aggregated feature importance via SHAP | `ShapImpact.create(entity_id=model_id)` | None | | SHAP value distributions across features | `ShapDistributions.create(entity_id=model_id)` | None | | SHAP for a filtered segment | `dr.DataSlice.create(...)` + `ShapMatrix.create(..., data_slice_id=...)` | Data slice definition | | XEMP-based prediction explanations | `dr.PredictionExplanations.create(...)` | Feature Impact; PE initialization; dataset uploaded | | Anomaly explanations (time series) | `AnomalyAssessmentRecord.compute(project_id, model_id, ...)` | Anomaly model | | ROC / lift / confusion (insights) | `RocCurve.create(...)` / `LiftChart.create(...)` / `ConfusionMatrix.create(...)` | Validation data | | ROC / lift / confusion (Model helpers) | `model.get_roc_curve()` / `model.get_lift_chart()` / `model.get_confusion_chart()` | Validation data | **Universal SHAP is the preferred path** - no dataset pre-upload or Feature Impact step required. ## When to use this skill Use this skill when you need to explain leaderboard model behavior, compute SHAP insights, use XEMP prediction explanations, analyze anomaly explanations, or retrieve model diagnostics. ## Key capabilities ### 1. SHAP insights - Compute `ShapMatrix`, `ShapPreview`, `ShapImpact`, and `ShapDistributions` - Filter insights with `dr.DataSlice` ### 2. XEMP and anomaly explanations - Use XEMP `dr.PredictionExplanations` when specifically required - Retrieve time series anomaly assessment records and explanations ### 3. Diagnostics - Retrieve ROC, lift, and confusion insights - Use Model helpers for ROC, lift, confusion, and feature effects ## Setup ```python import datarobot as dr from datarobot.insights import ShapMatrix, ShapImpact, ShapPreview, ShapDistributions dr.Client() ``` --- ## Core API: `datarobot.insights` ```python import pandas as pd from datarobot.insights import ShapMatrix, ShapImpact, ShapPreview, ShapDistributions model_id = "YOUR_MODEL_ID" matrix = ShapMatrix.create(entity_id=model_id) df = pd.DataFrame(matrix.matrix, columns=matrix.columns) impact = ShapImpact.create(entity_id=model_id) preview = ShapPreview.create(entity_id=model_id) distributions = ShapDistributions.create(entity_id=model_id) ``` Use `ShapMatrix` for full row-by-feature SHAP values, `ShapPreview` for compact top-driver rows, `ShapImpact` for aggregated SHAP importance, and `ShapDistributions` for per-feature SHAP distributions. Use `source="externalTestSet"` plus `external_dataset_id` for external datasets. See `references/shap_api_reference.md` for parameters, exports, and limitations. --- ## Secondary path: XEMP Prediction Explanations Use `dr.PredictionExplanations` when XEMP explanations are specifically required (e.g., certain regulatory contexts, or when SHAP is unavailable for the model type). **Prerequisites** (all required before calling `.create()`): 1. Feature Impact must be computed: `model.request_feature_impact()` and wait 2. Prediction explanations initialized: `dr.PredictionExplanationsInitialization.create(...)` 3. Scoring dataset uploaded to the AI Catalog ```python import datarobot as dr model = dr.Model.get(project=project_id, model_id=model_id) model.request_feature_impact().wait_for_completion() dr.PredictionExplanationsInitialization.create(project_id=project_id, model_id=model_id) dataset = dr.Dataset.upload("./data/scoring_data.csv") pe_job = dr.PredictionExplanations.create( project_id=project_id, model_id=model_id, dataset_id=dataset.id, max_explanations=5, # top N features per row, up to 50 threshold_high=0.5, # only explain rows with prediction >= threshold threshold_low=0.1, # only explain rows with prediction <= threshold ) pe_obj = pe_job.get_result_when_complete() ``` Use `pe_obj.get_rows()`, `pe_obj.get_all_as_dataframe()`, or `pe_obj.download_to_csv(...)` to retrieve results. For parameters, multiclass modes, and exposure-adjusted predictions, see `references/xemp_pe_reference.md`. ## Data slices for filtered insights Use `dr.DataSlice` when the user asks to explain model behavior for a segment, such as a region, product line, target class, or high-risk cohort. Pass the resulting `data_slice_id` into the `datarobot.insights` SHAP APIs. ```python import datarobot as dr from datarobot.insights import ShapMatrix data_slice = dr.DataSlice.create( name="high_income_customers", filters=[{"operand": "income", "operator": ">", "values": 100000}], project=project_id, ) shap_matrix = ShapMatrix.create( entity_id=model_id, source="validation", data_slice_id=data_slice.id, ) ``` --- ## Anomaly assessment (time series models) For time series anomaly detection models, use `AnomalyAssessmentRecord`. ```python from datarobot.models.anomaly_assessment import AnomalyAssessmentRecord record = AnomalyAssessmentRecord.compute( project_id=project_id, model_id=model_id, backtest=0, # backtest index (int) or "holdout" source="validation", # "training" or "validation" only series_id=None, # required for multiseries projects ) records = AnomalyAssessmentRecord.list(project_id=project_id, model_id=model_id) latest = record.get_latest_explanations() regions = record.get_predictions_preview().find_anomalous_regions() explanations = record.get_explanations_data_in_regions(regions=regions) ranged = record.get_explanations( start_date="2024-01-01T00:00:00.000000Z", end_date="2024-06-01T00:00:00.000000Z", ) ``` --- ## Model diagnostics Use the same `entity_id=model_id` pattern as SHAP insights. `FeatureEffects` / partial dependence is still retrieved through Model helpers (not in `datarobot.insights`). ### Insights diagnostics (preferred — matches SHAP API) ```python from datarobot.insights import RocCurve, LiftChart, ConfusionMatrix roc = RocCurve.create(entity_id=model_id) lift = LiftChart.create(entity_id=model_id) confusion = ConfusionMatrix.create(entity_id=model_id) ``` ### Model helpers (alternative) ```python model = dr.Model.get(project=project_id, model_id=model_id) roc = model.get_roc_curve(source="validation") lift = model.get_lift_chart(source="validation") confusion = model.get_confusion_chart(source="validation") # Feature Impact (non-SHAP) and Feature Effects (partial dependence for top features) fi = model.get_feature_impact() feature_effects = model.get_feature_effect(source="validation") ``` --- ## Interpreting SHAP values - **Positive value**: feature pushes prediction higher than baseline - **Negative value**: feature pushes prediction lower than baseline - **Magnitude**: size of influence; larger absolute value = stronger effect - **Sum**: all SHAP values for a row sum to `prediction - base_value` in the link-function space - **`base_value`**: the model's mean prediction (the "no information" baseline) Example: if `base_value = 0.35` and a row's prediction is `0.72`, the row's SHAP values sum to `0.37` when `link_function = "identity"`. A feature with SHAP `+0.20` contributed 20 units in that same link-function space above baseline. When `link_function = "logit"`, SHAP values are in log-odds space. Add feature contributions to `base_value` in log-odds space, then use inverse-logit (`scipy.special.expit`) on the resulting total to convert it to a probability. Do not apply `expit` to individual SHAP values as if they were probability deltas. --- ## Decision guide ``` Task: explain predictions | - Need all features + all rows? -> ShapMatrix.create(entity_id=model_id) - Need top-N features per row? -> ShapPreview.create(entity_id=model_id) - Need aggregated importance? -> ShapImpact.compute(entity_id=model_id) - Need feature SHAP distributions? -> ShapDistributions.create(entity_id=model_id) - Need a segment/cohort only? -> dr.DataSlice + data_slice_id - XEMP required (regulatory/type)? -> dr.PredictionExplanations.create(...) - Time series / anomaly model? -> AnomalyAssessmentRecord.compute(project_id, model_id, ...) ``` --- ## Common errors | Error | Cause | Fix | |-------|-------|-----| | `SHAP not available for this model` | Unsupported model type, or anomaly-detection model with >1000 features | Check model support; use XEMP PE if SHAP is unavailable | | `Feature Impact not computed` | PredictionExplanations prerequisite missing | Run `model.request_feature_impact()` and wait | | Missing `PredictionExplanationsInitialization` | PE not initialized | Call `PredictionExplanationsInitialization.create()` | | `source='holdout'` fails | Holdout not unlocked | Unlock holdout in project settings first | | Empty `previews` | No rows in partition | Check partition contains data | --- ## Reference files - `references/shap_api_reference.md` - full parameter signatures for ShapMatrix, ShapImpact, ShapPreview, ShapDistributions - `references/xemp_pe_reference.md` - PredictionExplanations and PredictionExplanationsInitialization parameter reference - `scripts/compute_shap_matrix.py` - compute and export ShapMatrix to CSV or DataFrame ## Resources - [datarobot.insights API reference](https://datarobot-public-api-client.readthedocs-hosted.com/en/latest-release/insights.html) - [Prediction Explanations user guide](https://datarobot-public-api-client.readthedocs-hosted.com/en/latest-release/reference/modeling/insights/prediction_explanations.html)
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.