Attribution methods quantitatively measure the contribution of each of a function's individual inputs to its output. Gradient-based attribution methods compute the gradient of a model with respect to its inputs to describe how important each input is towards the output prediction. These methods can be applied to assist in explaining deep networks.

TruLens provides implementations of several such techniques, found in this package.

## AttributionMethod¶

Interface used by all attribution methods.

An attribution method takes a neural network model and provides the ability to assign values to the variables of the network that specify the importance of each variable towards particular predictions.

###  model: ModelWrapper  property readonly ¶

Model for which attributions are calculated.

###  __init__(self, model, *args, **kwargs)  special ¶

Abstract constructor.

Parameters:

Name Type Description Default
model ModelWrapper

Model for which attributions are calculated.

required
Source code in trulens/nn/attribution.py
@abstractmethod
def __init__(self, model: ModelWrapper, *args, **kwargs):
"""
Abstract constructor.

Parameters:
model :
Model for which attributions are calculated.
"""
self._model = model


###  attributions(self, *model_args, **model_kwargs) ¶

Returns attributions for the given input. Attributions are in the same shape as the layer that attributions are being generated for.

The numeric scale of the attributions will depend on the specific implementations of the Distribution of Interest and Quantity of Interest. However it is generally related to the scale of gradients on the Quantity of Interest.

For example, Integrated Gradients uses the linear interpolation Distribution of Interest which subsumes the completeness axiom which ensures the sum of all attributions of a record equals the output determined by the Quantity of Interest on the same record.

The Point Distribution of Interest will be determined by the gradient at a single point, thus being a good measure of model sensitivity.

Parameters:

Name Type Description Default
model_args, model_kwargs

The args and kwargs given to the call method of a model. This should represent the records to obtain attributions for, assumed to be a batched input. if self.model supports evaluation on data tensors, the appropriate tensor type may be used (e.g., Pytorch models may accept Pytorch tensors in addition to np.ndarrays). The shape of the inputs must match the input shape of self.model.

required

Returns:

Type Description

An array of attributions, matching the shape and type of from_cut of the slice. Each entry in the returned array represents the degree to which the corresponding feature affected the model's outcome on the corresponding point.

Source code in trulens/nn/attribution.py
@abstractmethod
"""
Returns attributions for the given input. Attributions are in the same shape
as the layer that attributions are being generated for.

The numeric scale of the attributions will depend on the specific implementations
of the Distribution of Interest and Quantity of Interest. However it is generally
related to the scale of gradients on the Quantity of Interest.

For example, Integrated Gradients uses the linear interpolation Distribution of Interest
which subsumes the completeness axiom which ensures the sum of all attributions of a record
equals the output determined by the Quantity of Interest on the same record.

The Point Distribution of Interest will be determined by the gradient at a single point,
thus being a good measure of model sensitivity.

Parameters:
model_args, model_kwargs:
The args and kwargs given to the call method of a model.
This should represent the records to obtain attributions for,
assumed to be a *batched* input. if self.model supports
evaluation on *data tensors*, the  appropriate tensor type may
be used (e.g., Pytorch models may accept Pytorch tensors in
addition to np.ndarrays). The shape of the inputs must match
the input shape of self.model.

Returns:
An array of attributions, matching the shape and type of from_cut
of the slice. Each entry in the returned array represents the degree
to which the corresponding feature affected the model's outcome on
the corresponding point.
"""
raise NotImplementedError


## InputAttribution¶

Attributions of input features on either internal or output quantities. This is essentially an alias for

InternalInfluence(
model,
(trulens.nn.slices.InputCut(), cut),
qoi,
doi,
multiply_activation)


###  __init__(self, model, cut=None, qoi='max', doi='point', multiply_activation=True)  special ¶

Parameters:

Name Type Description Default
model ModelWrapper

Model for which attributions are calculated.

required
cut Optional[Union[trulens.nn.slices.Cut, int, str]]

The cut determining the layer from which the QoI is derived. Expects a Cut object, or a related type that can be interpreted as a Cut, as documented below.

If an int is given, it represents the index of a layer in model.

If a str is given, it represents the name of a layer in model.

None is an alternative for slices.OutputCut().

None
qoi Union[trulens.nn.quantities.QoI, int, Tuple[int], Callable, str]

quantities.QoI | int | tuple | str Quantity of interest to attribute. Expects a QoI object, or a related type that can be interpreted as a QoI, as documented below.

If an int is given, the quantity of interest is taken to be the slice output for the class/neuron/channel specified by the given integer, i.e.,

quantities.InternalChannelQoI(qoi)


If a tuple or list of two integers is given, then the quantity of interest is taken to be the comparative quantity for the class given by the first integer against the class given by the second integer, i.e.,

quantities.ComparativeQoI(*qoi)


If a callable is given, it is interpreted as a function representing the QoI, i.e.,

quantities.LambdaQoI(qoi)


If the string, 'max', is given, the quantity of interest is taken to be the output for the class with the maximum score, i.e.,

quantities.MaxClassQoI()


'max'
doi Union[trulens.nn.distributions.DoI, str]

distributions.DoI | str Distribution of interest over inputs. Expects a DoI object, or a related type that can be interpreted as a DoI, as documented below.

If the string, 'point', is given, the distribution is taken to be the single point passed to attributions, i.e.,

distributions.PointDoi()


If the string, 'linear', is given, the distribution is taken to be the linear interpolation from the zero input to the point passed to attributions, i.e.,

distributions.LinearDoi()


'point'
multiply_activation bool

bool, optional Whether to multiply the gradient result by its corresponding activation, thus converting from "influence space" to "attribution space."

True
Source code in trulens/nn/attribution.py
def __init__(
self,
model: ModelWrapper,
cut: CutLike = None,
qoi: QoiLike = 'max',
doi: DoiLike = 'point',
multiply_activation: bool = True):
"""
Parameters:
model :
Model for which attributions are calculated.

cut :
The cut determining the layer from which the QoI is derived.
Expects a Cut object, or a related type that can be
interpreted as a Cut, as documented below.

If an int is given, it represents the index of a layer in
model.

If a str is given, it represents the name of a layer in
model.

None is an alternative for slices.OutputCut().

qoi : quantities.QoI | int | tuple | str
Quantity of interest to attribute. Expects a QoI object, or a
related type that can be interpreted as a QoI, as documented
below.

If an int is given, the quantity of interest is taken to be
the slice output for the class/neuron/channel specified by the
given integer, i.e.,
python
quantities.InternalChannelQoI(qoi)


If a tuple or list of two integers is given, then the quantity
of interest is taken to be the comparative quantity for the
class given by the first integer against the class given by the
second integer, i.e.,
python
quantities.ComparativeQoI(*qoi)


If a callable is given, it is interpreted as a function
representing the QoI, i.e.,
python
quantities.LambdaQoI(qoi)


If the string, 'max', is given, the quantity of interest is
taken to be the output for the class with the maximum score,
i.e.,
python
quantities.MaxClassQoI()


doi : distributions.DoI | str
Distribution of interest over inputs. Expects a DoI object, or
a related type that can be interpreted as a DoI, as documented
below.

If the string, 'point', is given, the distribution is taken to
be the single point passed to attributions, i.e.,
python
distributions.PointDoi()


If the string, 'linear', is given, the distribution is taken
to be the linear interpolation from the zero input to the point
passed to attributions, i.e.,
python
distributions.LinearDoi()


multiply_activation : bool, optional
Whether to multiply the gradient result by its corresponding
activation, thus converting from "*influence space*" to
"""
super().__init__(
model, (InputCut(), cut),
qoi,
doi,
multiply_activation=multiply_activation)


## IntegratedGradients¶

Implementation for the Integrated Gradients method from the following paper:

This should be cited using:

@INPROCEEDINGS{
sundararajan17axiomatic,
author={Mukund Sundararajan and Ankur Taly, and Qiqi Yan},
booktitle={International Conference on Machine Learning (ICML)},
year={2017},
}


This is essentially an alias for

InternalInfluence(
model,
(trulens.nn.slices.InputCut(), trulens.nn.slices.OutputCut()),
'max',
trulens.nn.distributions.LinearDoi(baseline, resolution),
multiply_activation=True)


###  __init__(self, model, baseline=None, resolution=50)  special ¶

Parameters:

Name Type Description Default
model ModelWrapper

Model for which attributions are calculated.

required
baseline

The baseline to interpolate from. Must be same shape as the input. If None is given, the zero vector in the appropriate shape will be used.

None
resolution int

Number of points to use in the approximation. A higher resolution is more computationally expensive, but gives a better approximation of the mathematical formula this attribution method represents.

50
Source code in trulens/nn/attribution.py
def __init__(
self, model: ModelWrapper, baseline=None, resolution: int = 50):
"""
Parameters:
model:
Model for which attributions are calculated.

baseline:
The baseline to interpolate from. Must be same shape as the
input. If None is given, the zero vector in the appropriate
shape will be used.

resolution:
Number of points to use in the approximation. A higher
resolution is more computationally expensive, but gives a better
approximation of the mathematical formula this attribution
method represents.
"""
super().__init__(
model,
OutputCut(),
'max',
LinearDoi(baseline, resolution),
multiply_activation=True)


## InternalInfluence¶

Internal attributions parameterized by a slice, quantity of interest, and distribution of interest.

The slice specifies the layers at which the internals of the model are to be exposed; it is represented by two cuts, which specify the layer the attributions are assigned to and the layer from which the quantity of interest is derived. The Quantity of Interest (QoI) is a function of the output specified by the slice that determines the network output behavior that the attributions are to describe. The Distribution of Interest (DoI) specifies the records over which the attributions are aggregated.

Influence-Directed Explanations for Deep Convolutional Networks

This should be cited using:

@INPROCEEDINGS{
leino18influence,
author={
Klas Leino and
Shayak Sen and
Anupam Datta and
Matt Fredrikson and
Linyi Li},
title={
Influence-Directed Explanations
for Deep Convolutional Networks},
booktitle={IEEE International Test Conference (ITC)},
year={2018},
}


###  __init__(self, model, cuts, qoi, doi, multiply_activation=True)  special ¶

Parameters:

Name Type Description Default
model ModelWrapper

Model for which attributions are calculated.

required
cuts Optional[Union[trulens.nn.slices.Slice, Tuple[Union[trulens.nn.slices.Cut, int, str, NoneType]], trulens.nn.slices.Cut, int, str]]

The slice to use when computing the attributions. The slice keeps track of the layer whose output attributions are calculated and the layer for which the quantity of interest is computed. Expects a Slice object, or a related type that can be interpreted as a Slice, as documented below.

If a single Cut object is given, it is assumed to be the cut representing the layer for which attributions are calculated (i.e., from_cut in Slice) and the layer for the quantity of interest (i.e., to_cut in slices.Slice) is taken to be the output of the network. If a tuple or list of two Cuts is given, they are assumed to be from_cut and to_cut, respectively.

A cut (or the cuts within the tuple) can also be represented as an int, str, or None. If an int is given, it represents the index of a layer in model. If a str is given, it represents the name of a layer in model. None is an alternative for slices.InputCut.

required
qoi Union[trulens.nn.quantities.QoI, int, Tuple[int], Callable, str]

Quantity of interest to attribute. Expects a QoI object, or a related type that can be interpreted as a QoI, as documented below.

If an int is given, the quantity of interest is taken to be the slice output for the class/neuron/channel specified by the given integer, i.e.,

quantities.InternalChannelQoI(qoi)


If a tuple or list of two integers is given, then the quantity of interest is taken to be the comparative quantity for the class given by the first integer against the class given by the second integer, i.e.,

quantities.ComparativeQoI(*qoi)


If a callable is given, it is interpreted as a function representing the QoI, i.e.,

quantities.LambdaQoI(qoi)


If the string, 'max', is given, the quantity of interest is taken to be the output for the class with the maximum score, i.e.,

quantities.MaxClassQoI()


required
doi Union[trulens.nn.distributions.DoI, str]

Distribution of interest over inputs. Expects a DoI object, or a related type that can be interpreted as a DoI, as documented below.

If the string, 'point', is given, the distribution is taken to be the single point passed to attributions, i.e.,

distributions.PointDoi()


If the string, 'linear', is given, the distribution is taken to be the linear interpolation from the zero input to the point passed to attributions, i.e.,

distributions.LinearDoi()


required
multiply_activation bool

Whether to multiply the gradient result by its corresponding activation, thus converting from "influence space" to "attribution space."

True
Source code in trulens/nn/attribution.py
def __init__(
self,
model: ModelWrapper,
cuts: SliceLike,
qoi: QoiLike,
doi: DoiLike,
multiply_activation: bool = True):
"""
Parameters:
model:
Model for which attributions are calculated.

cuts:
The slice to use when computing the attributions. The slice
keeps track of the layer whose output attributions are
calculated and the layer for which the quantity of interest is
computed. Expects a Slice object, or a related type that can
be interpreted as a Slice, as documented below.

If a single Cut object is given, it is assumed to be the cut
representing the layer for which attributions are calculated
(i.e., from_cut in Slice) and the layer for the quantity of
interest (i.e., to_cut in slices.Slice) is taken to be the
output of the network. If a tuple or list of two Cuts is
given, they are assumed to be from_cut and to_cut,
respectively.

A cut (or the cuts within the tuple) can also be represented as
an int, str, or None. If an int is given, it represents
the index of a layer in model. If a str is given, it
represents the name of a layer in model. None is an
alternative for slices.InputCut.

qoi:
Quantity of interest to attribute. Expects a QoI object, or a
related type that can be interpreted as a QoI, as documented
below.

If an int is given, the quantity of interest is taken to be
the slice output for the class/neuron/channel specified by the
given integer, i.e.,
python
quantities.InternalChannelQoI(qoi)


If a tuple or list of two integers is given, then the quantity
of interest is taken to be the comparative quantity for the
class given by the first integer against the class given by the
second integer, i.e.,
python
quantities.ComparativeQoI(*qoi)


If a callable is given, it is interpreted as a function
representing the QoI, i.e.,
python
quantities.LambdaQoI(qoi)


If the string, 'max', is given, the quantity of interest is
taken to be the output for the class with the maximum score,
i.e.,
python
quantities.MaxClassQoI()


doi:
Distribution of interest over inputs. Expects a DoI object, or
a related type that can be interpreted as a DoI, as documented
below.

If the string, 'point', is given, the distribution is taken to
be the single point passed to attributions, i.e.,
python
distributions.PointDoi()


If the string, 'linear', is given, the distribution is taken
to be the linear interpolation from the zero input to the point
passed to attributions, i.e.,
python
distributions.LinearDoi()


multiply_activation:
Whether to multiply the gradient result by its corresponding
activation, thus converting from "*influence space*" to
"""
super().__init__(model)

self.slice = InternalInfluence.__get_slice(cuts)
self.qoi = InternalInfluence.__get_qoi(qoi)
self.doi = InternalInfluence.__get_doi(doi)
self._do_multiply = multiply_activation


###  attributions(self, *model_args, **model_kwargs) ¶

Returns attributions for the given input. Attributions are in the same shape as the layer that attributions are being generated for.

The numeric scale of the attributions will depend on the specific implementations of the Distribution of Interest and Quantity of Interest. However it is generally related to the scale of gradients on the Quantity of Interest.

For example, Integrated Gradients uses the linear interpolation Distribution of Interest which subsumes the completeness axiom which ensures the sum of all attributions of a record equals the output determined by the Quantity of Interest on the same record.

The Point Distribution of Interest will be determined by the gradient at a single point, thus being a good measure of model sensitivity.

Parameters:

Name Type Description Default
model_args, model_kwargs

The args and kwargs given to the call method of a model. This should represent the records to obtain attributions for, assumed to be a batched input. if self.model supports evaluation on data tensors, the appropriate tensor type may be used (e.g., Pytorch models may accept Pytorch tensors in addition to np.ndarrays). The shape of the inputs must match the input shape of self.model.

required

Returns:

Type Description

An array of attributions, matching the shape and type of from_cut of the slice. Each entry in the returned array represents the degree to which the corresponding feature affected the model's outcome on the corresponding point.

Source code in trulens/nn/attribution.py
def attributions(self, *model_args, **model_kwargs):
doi_cut = self.doi.cut() if self.doi.cut() else InputCut()

doi_val = self.model.fprop(model_args, model_kwargs, to_cut=doi_cut)
# DoI supports tensor or list of tensor. unwrap args to perform DoI on
# top level list

# Depending on the model_arg input, the data may be nested in data
# containers. We unwrap so that there operations are working on a single
# level of data container.
if isinstance(doi_val, DATA_CONTAINER_TYPE) and isinstance(
doi_val[0], DATA_CONTAINER_TYPE):
doi_val = doi_val[0]

if isinstance(doi_val, DATA_CONTAINER_TYPE) and len(doi_val) == 1:
doi_val = doi_val[0]

D = self.doi(doi_val)
n_doi = len(D)
D = InternalInfluence.__concatenate_doi(D)

# Calculate the gradient of each of the points in the DoI.
self.qoi,
model_args,
model_kwargs,
to_cut=self.slice.to_cut,
intervention=D,
doi_cut=doi_cut)
# Take the mean across the samples in the DoI.
get_backend().mean(
get_backend().reshape(
]
else:
get_backend().reshape(
axis=0)

# Multiply by the activation multiplier if specified.
if self._do_multiply:
z_val = self.model.fprop(
model_args, model_kwargs, to_cut=self.slice.from_cut)
if isinstance(z_val, DATA_CONTAINER_TYPE) and len(z_val) == 1:
z_val = z_val[0]