Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 47 additions & 43 deletions captum/attr/_core/deep_lift.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,37 @@ def is_output_cloned(output_fn, input_grad_fn) -> bool:


class DeepLift(GradientAttribution):
r"""
Implements DeepLIFT algorithm based on the following paper:
Learning Important Features Through Propagating Activation Differences,
Avanti Shrikumar, et. al.
https://arxiv.org/abs/1704.02685

and the gradient formulation proposed in:
Towards better understanding of gradient-based attribution methods for
deep neural networks, Marco Ancona, et.al.
https://openreview.net/pdf?id=Sy21R9JAW

This implementation supports only Rescale rule. RevealCancel rule will
be supported in later releases.
In addition to that, in order to keep the implementation cleaner, DeepLIFT
for internal neurons and layers extends current implementation and is
implemented separately in LayerDeepLift and NeuronDeepLift.
Although DeepLIFT's(Rescale Rule) attribution quality is comparable with
Integrated Gradients, it runs significantly faster than Integrated
Gradients and is preferred for large datasets.

Currently we only support a limited number of non-linear activations
but the plan is to expand the list in the future.

Note: As we know, currently we cannot access the building blocks,
of PyTorch's built-in LSTM, RNNs and GRUs such as Tanh and Sigmoid.
Nonetheless, it is possible to build custom LSTMs, RNNS and GRUs
with performance similar to built-in ones using TorchScript.
More details on how to build custom RNNs can be found here:
https://pytorch.org/blog/optimizing-cuda-rnn-with-torchscript/
"""

def __init__(self, model: Module) -> None:
r"""
Args:
Expand Down Expand Up @@ -116,35 +147,6 @@ def attribute( # type: ignore
TensorOrTupleOfTensorsGeneric, Tuple[TensorOrTupleOfTensorsGeneric, Tensor]
]:
r""""
Implements DeepLIFT algorithm based on the following paper:
Learning Important Features Through Propagating Activation Differences,
Avanti Shrikumar, et. al.
https://arxiv.org/abs/1704.02685

and the gradient formulation proposed in:
Towards better understanding of gradient-based attribution methods for
deep neural networks, Marco Ancona, et.al.
https://openreview.net/pdf?id=Sy21R9JAW

This implementation supports only Rescale rule. RevealCancel rule will
be supported in later releases.
In addition to that, in order to keep the implementation cleaner, DeepLIFT
for internal neurons and layers extends current implementation and is
implemented separately in LayerDeepLift and NeuronDeepLift.
Although DeepLIFT's(Rescale Rule) attribution quality is comparable with
Integrated Gradients, it runs significantly faster than Integrated
Gradients and is preferred for large datasets.

Currently we only support a limited number of non-linear activations
but the plan is to expand the list in the future.

Note: As we know, currently we cannot access the building blocks,
of PyTorch's built-in LSTM, RNNs and GRUs such as Tanh and Sigmoid.
Nonetheless, it is possible to build custom LSTMs, RNNS and GRUs
with performance similar to built-in ones using TorchScript.
More details on how to build custom RNNs can be found here:
https://pytorch.org/blog/optimizing-cuda-rnn-with-torchscript/

Args:

inputs (tensor or tuple of tensors): Input for which
Expand Down Expand Up @@ -520,6 +522,22 @@ def has_convergence_delta(self) -> bool:


class DeepLiftShap(DeepLift):
r"""
Extends DeepLift algorithm and approximates SHAP values using Deeplift.
For each input sample it computes DeepLift attribution with respect to
each baseline and averages resulting attributions.
More details about the algorithm can be found here:

http://papers.nips.cc/paper/7062-a-unified-approach-to-interpreting-model-predictions.pdf

Note that the explanation model:
1. Assumes that input features are independent of one another
2. Is linear, meaning that the explanations are modeled through
the additive composition of feature effects.
Although, it assumes a linear model for each explanation, the overall
model across multiple explanations can be complex and non-linear.
"""

def __init__(self, model: Module) -> None:
r"""
Args:
Expand Down Expand Up @@ -573,20 +591,6 @@ def attribute( # type: ignore
TensorOrTupleOfTensorsGeneric, Tuple[TensorOrTupleOfTensorsGeneric, Tensor]
]:
r"""
Extends DeepLift algorithm and approximates SHAP values using Deeplift.
For each input sample it computes DeepLift attribution with respect to
each baseline and averages resulting attributions.
More details about the algorithm can be found here:

http://papers.nips.cc/paper/7062-a-unified-approach-to-interpreting-model-predictions.pdf

Note that the explanation model:
1. Assumes that input features are independent of one another
2. Is linear, meaning that the explanations are modeled through
the additive composition of feature effects.
Although, it assumes a linear model for each explanation, the overall
model across multiple explanations can be complex and non-linear.

Args:

inputs (tensor or tuple of tensors): Input for which
Expand Down
36 changes: 19 additions & 17 deletions captum/attr/_core/feature_ablation.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,25 @@


class FeatureAblation(PerturbationAttribution):
r"""
A perturbation based approach to computing attribution, involving
replacing each input feature with a given baseline / reference, and
computing the difference in output. By default, each scalar value within
each input tensor is taken as a feature and replaced independently. Passing
a feature mask, allows grouping features to be ablated together. This can
be used in cases such as images, where an entire segment or region
can be ablated, measuring the importance of the segment (feature group).
Each input scalar in the group will be given the same attribution value
equal to the change in target as a result of ablating the entire feature
group.

The forward function can either return a scalar per example, or a single
scalar for the full batch. If a single scalar is returned for the batch,
`perturbations_per_eval` must be 1, and the returned attributions will have
first dimension 1, corresponding to feature importance across all
examples in the batch.
"""

def __init__(self, forward_func: Callable) -> None:
r"""
Args:
Expand All @@ -43,23 +62,6 @@ def attribute(
**kwargs: Any
) -> TensorOrTupleOfTensorsGeneric:
r""""
A perturbation based approach to computing attribution, involving
replacing each input feature with a given baseline / reference, and
computing the difference in output. By default, each scalar value within
each input tensor is taken as a feature and replaced independently. Passing
a feature mask, allows grouping features to be ablated together. This can
be used in cases such as images, where an entire segment or region
can be ablated, measuring the importance of the segment (feature group).
Each input scalar in the group will be given the same attribution value
equal to the change in target as a result of ablating the entire feature
group.

The forward function can either return a scalar per example, or a single
scalar for the full batch. If a single scalar is returned for the batch,
`perturbations_per_eval` must be 1, and the returned attributions will have
first dimension 1, corresponding to feature importance across all
examples in the batch.

Args:

inputs (tensor or tuple of tensors): Input for which ablation
Expand Down
94 changes: 48 additions & 46 deletions captum/attr/_core/gradient_shap.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,41 @@


class GradientShap(GradientAttribution):
r"""
Implements gradient SHAP based on the implementation from SHAP's primary
author. For reference, please, view:

https://github.com/slundberg/shap\
#deep-learning-example-with-gradientexplainer-tensorflowkeraspytorch-models

A Unified Approach to Interpreting Model Predictions
http://papers.nips.cc/paper\
7062-a-unified-approach-to-interpreting-model-predictions

GradientShap approximates SHAP values by computing the expectations of
gradients by randomly sampling from the distribution of baselines/references.
It adds white noise to each input sample `n_samples` times, selects a
random baseline from baselines' distribution and a random point along the
path between the baseline and the input, and computes the gradient of outputs
with respect to those selected random points. The final SHAP values represent
the expected values of gradients * (inputs - baselines).

GradientShap makes an assumption that the input features are independent
and that the explanation model is linear, meaning that the explanations
are modeled through the additive composition of feature effects.
Under those assumptions, SHAP value can be approximated as the expectation
of gradients that are computed for randomly generated `n_samples` input
samples after adding gaussian noise `n_samples` times to each input for
different baselines/references.

In some sense it can be viewed as an approximation of integrated gradients
by computing the expectations of gradients for different baselines.

Current implementation uses Smoothgrad from `NoiseTunnel` in order to
randomly draw samples from the distribution of baselines, add noise to input
samples and compute the expectation (smoothgrad).
"""

def __init__(self, forward_func: Callable) -> None:
r"""
Args:
Expand Down Expand Up @@ -79,39 +114,6 @@ def attribute(
TensorOrTupleOfTensorsGeneric, Tuple[TensorOrTupleOfTensorsGeneric, Tensor]
]:
r"""
Implements gradient SHAP based on the implementation from SHAP's primary
author. For reference, please, view:

https://github.com/slundberg/shap\
#deep-learning-example-with-gradientexplainer-tensorflowkeraspytorch-models

A Unified Approach to Interpreting Model Predictions
http://papers.nips.cc/paper\
7062-a-unified-approach-to-interpreting-model-predictions

GradientShap approximates SHAP values by computing the expectations of
gradients by randomly sampling from the distribution of baselines/references.
It adds white noise to each input sample `n_samples` times, selects a
random baseline from baselines' distribution and a random point along the
path between the baseline and the input, and computes the gradient of outputs
with respect to those selected random points. The final SHAP values represent
the expected values of gradients * (inputs - baselines).

GradientShap makes an assumption that the input features are independent
and that the explanation model is linear, meaning that the explanations
are modeled through the additive composition of feature effects.
Under those assumptions, SHAP value can be approximated as the expectation
of gradients that are computed for randomly generated `n_samples` input
samples after adding gaussian noise `n_samples` times to each input for
different baselines/references.

In some sense it can be viewed as an approximation of integrated gradients
by computing the expectations of gradients for different baselines.

Current implementation uses Smoothgrad from `NoiseTunnel` in order to
randomly draw samples from the distribution of baselines, add noise to input
samples and compute the expectation (smoothgrad).

Args:

inputs (tensor or tuple of tensors): Input for which SHAP attribution
Expand Down Expand Up @@ -222,19 +224,19 @@ def attribute(
The deltas are ordered by each input example and `n_samples`
noisy samples generated for it.

Examples::

>>> # ImageClassifier takes a single input tensor of images Nx3x32x32,
>>> # and returns an Nx10 tensor of class probabilities.
>>> net = ImageClassifier()
>>> gradient_shap = GradientShap(net)
>>> input = torch.randn(3, 3, 32, 32, requires_grad=True)
>>> # choosing baselines randomly
>>> baselines = torch.randn(20, 3, 32, 32)
>>> # Computes gradient shap for the input
>>> # Attribution size matches input size: 3x3x32x32
>>> attribution = gradient_shap.attribute(input, baselines,
target=5)
Examples::

>>> # ImageClassifier takes a single input tensor of images Nx3x32x32,
>>> # and returns an Nx10 tensor of class probabilities.
>>> net = ImageClassifier()
>>> gradient_shap = GradientShap(net)
>>> input = torch.randn(3, 3, 32, 32, requires_grad=True)
>>> # choosing baselines randomly
>>> baselines = torch.randn(20, 3, 32, 32)
>>> # Computes gradient shap for the input
>>> # Attribution size matches input size: 3x3x32x32
>>> attribution = gradient_shap.attribute(input, baselines,
target=5)

"""
# since `baselines` is a distribution, we can generate it using a function
Expand Down
62 changes: 33 additions & 29 deletions captum/attr/_core/guided_backprop_deconvnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ def _remove_hooks(self):


class GuidedBackprop(ModifiedReluGradientAttribution):
r"""
Computes attribution using guided backpropagation. Guided backpropagation
computes the gradient of the target output with respect to the input,
but gradients of ReLU functions are overridden so that only
non-negative gradients are backpropagated.

More details regarding the guided backpropagation algorithm can be found
in the original paper here:
https://arxiv.org/abs/1412.6806

Warning: Ensure that all ReLU operations in the forward function of the
given model are performed using a module (nn.module.ReLU).
If nn.functional.ReLU is used, gradients are not overridden appropriately.
"""

def __init__(self, model: Module):
r"""
Args:
Expand All @@ -111,19 +126,6 @@ def attribute(
additional_forward_args: Any = None,
) -> TensorOrTupleOfTensorsGeneric:
r""""
Computes attribution using guided backpropagation. Guided backpropagation
computes the gradient of the target output with respect to the input,
but gradients of ReLU functions are overridden so that only
non-negative gradients are backpropagated.

More details regarding the guided backpropagation algorithm can be found
in the original paper here:
https://arxiv.org/abs/1412.6806

Warning: Ensure that all ReLU operations in the forward function of the
given model are performed using a module (nn.module.ReLU).
If nn.functional.ReLU is used, gradients are not overridden appropriately.

Args:

inputs (tensor or tuple of tensors): Input for which
Expand Down Expand Up @@ -197,6 +199,24 @@ def attribute(


class Deconvolution(ModifiedReluGradientAttribution):
r"""
Computes attribution using deconvolution. Deconvolution
computes the gradient of the target output with respect to the input,
but gradients of ReLU functions are overridden so that the gradient
of the ReLU input is simply computed taking ReLU of the output gradient,
essentially only propagating non-negative gradients (without
dependence on the sign of the ReLU input).

More details regarding the deconvolution algorithm can be found
in these papers:
https://arxiv.org/abs/1311.2901
https://link.springer.com/chapter/10.1007/978-3-319-46466-4_8

Warning: Ensure that all ReLU operations in the forward function of the
given model are performed using a module (nn.module.ReLU).
If nn.functional.ReLU is used, gradients are not overridden appropriately.
"""

def __init__(self, model: Module):
r"""
Args:
Expand All @@ -212,22 +232,6 @@ def attribute(
additional_forward_args: Any = None,
) -> TensorOrTupleOfTensorsGeneric:
r""""
Computes attribution using deconvolution. Deconvolution
computes the gradient of the target output with respect to the input,
but gradients of ReLU functions are overridden so that the gradient
of the ReLU input is simply computed taking ReLU of the output gradient,
essentially only propagating non-negative gradients (without
dependence on the sign of the ReLU input).

More details regarding the deconvolution algorithm can be found
in these papers:
https://arxiv.org/abs/1311.2901
https://link.springer.com/chapter/10.1007/978-3-319-46466-4_8

Warning: Ensure that all ReLU operations in the forward function of the
given model are performed using a module (nn.module.ReLU).
If nn.functional.ReLU is used, gradients are not overridden appropriately.

Args:

inputs (tensor or tuple of tensors): Input for which
Expand Down
Loading