!9003 Fix mistakes in docstring.

From: @yuhanshi
Reviewed-by: @wuxuejian,@ouwenchang
Signed-off-by: @wuxuejian
This commit is contained in:
mindspore-ci-bot 2020-11-25 17:07:39 +08:00 committed by Gitee
commit 829cc849a0
4 changed files with 26 additions and 43 deletions

View File

@ -16,10 +16,8 @@
import numpy as np
from mindspore import Tensor
from .metric import LabelAgnosticMetric
from ... import _operators as ops
from ...explanation._attribution.attribution import Attribution
from ..._utils import calc_correlation
@ -35,12 +33,12 @@ class ClassSensitivity(LabelAgnosticMetric):
"""
def evaluate(self, explainer: Attribution, inputs: Tensor) -> np.ndarray:
def evaluate(self, explainer, inputs):
"""
Evaluate class sensitivity on a single data sample.
Args:
explainer (Attribution): The explainer to be evaluated, see `mindspore.explainer.explanation`.
explainer (Explanation): The explainer to be evaluated, see `mindspore.explainer.explanation`.
inputs (Tensor): A data sample, a 4D tensor of shape :math:`(N, C, H, W)`.
Returns:
@ -49,7 +47,8 @@ class ClassSensitivity(LabelAgnosticMetric):
Examples:
>>> import mindspore as ms
>>> from mindspore.explainer.explanation import Gradient
>>> gradient = Gradient()
>>> model = resnet(10)
>>> gradient = Gradient(model)
>>> x = ms.Tensor(np.random.rand(1, 3, 224, 224), ms.float32)
>>> class_sensitivity = ClassSensitivity()
>>> res = class_sensitivity.evaluate(gradient, x)

View File

@ -14,21 +14,14 @@
# ============================================================================
"""Robustness."""
from typing import Optional, Union
import numpy as np
import mindspore as ms
import mindspore.nn as nn
from mindspore import Tensor
from mindspore import log
from .metric import LabelSensitiveMetric
from ...explanation._attribution import Attribution
from ...explanation._attribution._perturbation.replacement import RandomPerturb
_Array = np.ndarray
_Label = Union[ms.Tensor, int]
class Robustness(LabelSensitiveMetric):
"""
@ -39,12 +32,12 @@ class Robustness(LabelSensitiveMetric):
num_labels (int): Number of classes in the dataset.
Examples:
>>> from mindspore.explainer.benchmark import Robustness
>>> num_labels = 100
>>> robustness = Robustness(num_labels)
>>> from mindspore.explainer.benchmark import Robustness
>>> num_labels = 100
>>> robustness = Robustness(num_labels)
"""
def __init__(self, num_labels: int, activation_fn=nn.Softmax()):
def __init__(self, num_labels, activation_fn=nn.Softmax()):
super().__init__(num_labels)
self._perturb = RandomPerturb()
@ -52,12 +45,7 @@ class Robustness(LabelSensitiveMetric):
self._threshold = 0.1 # threshold to generate perturbation
self._activation_fn = activation_fn
def evaluate(self,
explainer: Attribution,
inputs: Tensor,
targets: _Label,
saliency: Optional[Tensor] = None
) -> _Array:
def evaluate(self, explainer, inputs, targets, saliency=None):
"""
Evaluate robustness on single sample.

View File

@ -48,7 +48,7 @@ class Ablation:
inputs (np.ndarray): Input array to perturb. The first dim of inputs is assumed to be the batch size, i.e.,
number of samples.
reference (np.ndarray or float): Array of values to replace the elements in the original inputs. The shape
of reference must math the inputs. If scalar is provided, the perturbed elements will be assigned the
of reference must match the inputs. If scalar is provided, the perturbed elements will be assigned the
given value..
masks (np.ndarray): Several boolean array to mark the perturbed positions. True marks the pixels to be
perturbed, otherwise the pixels will be kept. The shape of masks is assumed to be
@ -134,9 +134,9 @@ class AblationWithSaliency(Ablation):
saliency is expected to be: [batch_size, optional(num_channels), *spatial_size]. If multi-channel
saliency is provided, an averaged saliency will be taken to calculate pixel order in spatial dimension.
num_channels (optional[int]): Number of channels of the input data. In order to match the shape of inputs,
num_channels should be provided when input data have channels dimension, even if num_channel. If None is
provided, the inputs is assumed to be no-channel data, and the generated mask will have no channel
dimension. Default: None.
num_channels should be provided when input data have channels dimension, even if num_channel is 1.
If None is provided, the inputs is assumed to be no-channel data, and the generated mask will have
no channel dimension. Default: None.
Return:
mask (np.ndarray): boolen mask for generate perturbations.

View File

@ -15,7 +15,6 @@
"""Occlusion explainer."""
import math
from typing import Tuple, Union
import numpy as np
from numpy.lib.stride_tricks import as_strided
@ -23,15 +22,11 @@ from numpy.lib.stride_tricks import as_strided
import mindspore as ms
import mindspore.nn as nn
from mindspore import Tensor
from mindspore.nn import Cell
from .ablation import Ablation
from .perturbation import PerturbationAttribution
from .replacement import Constant
from ...._utils import abs_max
_Array = np.ndarray
_Label = Union[int, Tensor]
def _generate_patches(array, window_size, stride):
"""View as windows."""
@ -67,25 +62,26 @@ class Occlusion(PerturbationAttribution):
network (Cell): Specify the black-box model to be explained.
Inputs:
inputs (Tensor): The input data to be explained, a 4D tensor of shape :math:`(N, C, H, W)`.
targets (Tensor, int): The label of interest. It should be a 1D or 0D tensor, or an integer.
If it is a 1D tensor, its length should be the same as `inputs`.
inputs (Tensor): The input data to be explained, a 4D tensor of shape :math:`(N, C, H, W)`.
targets (Tensor, int): The label of interest. It should be a 1D or 0D tensor, or an integer.
If it is a 1D tensor, its length should be the same as `inputs`.
Outputs:
Tensor, a 4D tensor of shape :math:`(N, 1, H, W)`.
Tensor, a 4D tensor of shape :math:`(N, 1, H, W)`.
Example:
>>> from mindspore.explainer.explanation import Occlusion
>>> net = resnet50(10)
>>> from mindspore.train.serialization import load_checkpoint, load_param_into_net
>>> network = resnet50(10)
>>> param_dict = load_checkpoint("resnet50.ckpt")
>>> load_param_into_net(net, param_dict)
>>> occlusion = Occlusion(net)
>>> x = ms.Tensor(np.random.rand([1, 3, 224, 224]), ms.float32)
>>> load_param_into_net(network, param_dict)
>>> occlusion = Occlusion(network)
>>> x = Tensor(np.random.rand([1, 3, 224, 224]), ms.float32)
>>> label = 1
>>> saliency = occlusion(x, label)
"""
def __init__(self, network: Cell, activation_fn: Cell = nn.Softmax()):
def __init__(self, network, activation_fn=nn.Softmax()):
super().__init__(network, activation_fn)
self._ablation = Ablation(perturb_mode='Deletion')
@ -94,7 +90,7 @@ class Occlusion(PerturbationAttribution):
self._num_sample_per_dim = 32 # specify the number of perturbations each dimension.
self._num_per_eval = 32 # number of perturbations each evaluation step.
def __call__(self, inputs: Tensor, targets: _Label) -> Tensor:
def __call__(self, inputs, targets):
"""Call function for 'Occlusion'."""
self._verify_data(inputs, targets)
@ -145,11 +141,11 @@ class Occlusion(PerturbationAttribution):
outputs_diff.reshape(outputs_diff.shape + (1,) * (len(masks.shape) - 2)) * masks).sum(axis=1).clip(1e-6)
weights += masks.sum(axis=1)
attribution = self._aggregation_fn(ms.Tensor(total_attribution / weights))
attribution = self._aggregation_fn(Tensor(total_attribution / weights))
return attribution
@staticmethod
def _generate_masks(inputs: Tensor, window_size: Tuple[int, ...], strides: Tuple[int, ...]) -> _Array:
def _generate_masks(inputs, window_size, strides):
"""Generate masks to perturb contiguous regions."""
total_dim = np.prod(inputs.shape[1:]).item()
template = np.arange(total_dim).reshape(inputs.shape[1:])