Claude Cursor Skill

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

LLM Mart · 0 points · 4 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download datarobot-oss-datarobot-agent-skills-skills_datarobot-model-explainability-e6dddbe.zip · 9 KB
Part of datarobot-oss/datarobot-agent-skills — 14 skills

Install

skills CLI npx skills add https://github.com/datarobot-oss/datarobot-agent-skills/tree/main/skills/datarobot-model-explainability
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install datarobot-oss-datarobot-agent-skills@llmmart
Git 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.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

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()):

  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
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_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

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.

No comments yet.

Reviews (0)

No reviews yet.

Related