Metadata-Version: 2.4
Name: sage-explainer
Version: 0.1.1
Summary: Sensitivity Analysis with Gradient Estimation
Author-email: Yash Kher <yashpkher@gmail.com>
License: MIT License
        
        Copyright (c) 2026 Yash Kher
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/yashkher-123/sage
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas>=2.0
Requires-Dist: numpy>=1.24
Requires-Dist: scikit-learn>=1.2
Requires-Dist: matplotlib>=3.7
Dynamic: license-file

# SAGE
### Sensitivity Analysis with Gradient Estimation

This project represents an extension of a project made to address wildfire severity prediction in Southern California (see my other repos with "fire" in the name).


## Overview

**SAGE finds model sensitivity to continuous features.** In the context of wildfire prediction, it explains what features to target to *most effectively* change/reduce fire potential.
It works through weighted secant slope regression within the local window of an instance. Unlike current XAI methods that focus on understanding *why* a model
made a given prediction (feature attribution), SAGE focuses on how to most effectively *change* predictions.

Paired with explainers such as SHAP/LIME, SAGE allows users to act on predictions, going a step beyond trust to allow for active risk management.


## Capabilities
- Model-agnostic sensitivity analysis: works with any model via a user-supplied prediction function + background dataset
- Weighted secant slope regression: perturbs each continuous feature within a local window around the instance, computes secant slopes, and fits a gaussian-weighted linear regression to estimate sensitivity at the exact instance value
- Selective feature analysis: user can supply features to ignore or include in sensitivity analysis, SAGE automatically filters out non-numeric features
- Sensitivity visualization:  horizontal bar chart showing signed sensitivities per feature, sorted by magnitude, with positive/negative coloring
- Epsilon-free stability: unlike finite difference methods whose accuracy depends heavily on a manually-tuned epsilon parameter (too small causes instability on piecewise models, too large overshoots local variation), SAGE's perturbation window scales automatically with each feature's standard deviation

## Usage

```python
import pandas as pd
from sage import Sage_Explainer

explainer = Sage_Explainer(predict_func=model.predict) # provide predict function

# fit on background dataset
explainer.fit(
    data_X=X_train,
    perturbation_strength=0.3,      # optional, default 0.3
    ignore_features=["feature_a"],  # optional, defaults to none
    used_features=["feature_b", "feature_c"]  # optional, defaults to all
)

# explain a single instance
instance = X_test.iloc[0]
sensitivities = explainer.explain(instance)
print(sensitivities)  # dict of {feature: sensitivity}

# visualize with bar chart
explainer.graph()
```


## Parameters

**`Sage_Explainer(predict_func)`** - must supply a model's prediction function to initialize explainer

**`fit(self, data_X, perturbation_strength, ignore_features, used_features)`**
- `data_X` - required, must be pandas DataFrame
- `perturbation_strength` - optional (default 0.3), scales window of perturbations. Strength=1 indicates perturbations range within 1 standard deviation of each feature's value
- `ignore_features` - optional (default empty list), allows SAGE to ignore certain features in sensitivity analysis
- `used_features` - optional (default all features list), allows SAGE to only use certain features in sensitivity analysis

**`explain(self, instance)`** - must supply an instance in the form of a dict or Series to get local feature sensitivities
- Returns a dict with feature sensitivities `{feature: sensitivity}`

**`graph(self, instance)`** - supplying instance (dict or Series) is optional, if not given it defaults to graphing a previously-given instance from explain()
- Returns a matplotlib bar chart of ranked feature sensitivities


## How it works

1. **Fit to dataset:** Compute the standard deviation of each continuous feature across the background dataset. Scale each std by `perturbation_strength` to define the local window radius around any given instance.

2. **Perturb features:** For a given instance, generate evenly spaced perturbation values within the local window `(feature_value - scaled_std, feature_value + scaled_std)` for each feature. The original feature value is excluded from perturbations to avoid division by zero.

3. **Compute secant slopes:** For each perturbation, replace the feature value in the instance and run it through the model. Compute the secant slope between the perturbed prediction and the original prediction: `slope = (perturbed_pred - original_pred) / (perturbed_value - original_value)`. This gives a set of local slope estimates across the window.

4. **Regress to estimate sensitivity:** Fit a gaussian-weighted linear regression over the perturbation values (x) and their corresponding secant slopes (y). Points closer to the original feature value are weighted more heavily. The regression is then evaluated at the original feature value to produce a single sensitivity estimate: the approximate rate of change of the model's prediction with respect to that feature at that instance.



## Limitations

- Compute: for each feature in an instance, SAGE perturbs values, gets model predictions, computes secant slopes, fits a linear model, and predicts sensitivity for original value. Compute scales with the number of features, as a separate regression is fit per feature per instance.
- The current implementation of SAGE only works on continuous features
- Sensitivity is local to instance, SAGE cannot find global feature sensitivities


## Requirements

- pandas
- numpy
- sklearn
- matplotlib
- python 3


## Contact

yashpkher@gmail.com
