!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 import numpy as np
from mindspore import Tensor
from .metric import LabelAgnosticMetric from .metric import LabelAgnosticMetric
from ... import _operators as ops from ... import _operators as ops
from ...explanation._attribution.attribution import Attribution
from ..._utils import calc_correlation 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. Evaluate class sensitivity on a single data sample.
Args: 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)`. inputs (Tensor): A data sample, a 4D tensor of shape :math:`(N, C, H, W)`.
Returns: Returns:
@ -49,7 +47,8 @@ class ClassSensitivity(LabelAgnosticMetric):
Examples: Examples:
>>> import mindspore as ms >>> import mindspore as ms
>>> from mindspore.explainer.explanation import Gradient >>> 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) >>> x = ms.Tensor(np.random.rand(1, 3, 224, 224), ms.float32)
>>> class_sensitivity = ClassSensitivity() >>> class_sensitivity = ClassSensitivity()
>>> res = class_sensitivity.evaluate(gradient, x) >>> res = class_sensitivity.evaluate(gradient, x)

View File

@ -14,21 +14,14 @@
# ============================================================================ # ============================================================================
"""Robustness.""" """Robustness."""
from typing import Optional, Union
import numpy as np import numpy as np
import mindspore as ms import mindspore as ms
import mindspore.nn as nn import mindspore.nn as nn
from mindspore import Tensor
from mindspore import log from mindspore import log
from .metric import LabelSensitiveMetric from .metric import LabelSensitiveMetric
from ...explanation._attribution import Attribution
from ...explanation._attribution._perturbation.replacement import RandomPerturb from ...explanation._attribution._perturbation.replacement import RandomPerturb
_Array = np.ndarray
_Label = Union[ms.Tensor, int]
class Robustness(LabelSensitiveMetric): class Robustness(LabelSensitiveMetric):
""" """
@ -44,7 +37,7 @@ class Robustness(LabelSensitiveMetric):
>>> robustness = Robustness(num_labels) >>> 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) super().__init__(num_labels)
self._perturb = RandomPerturb() self._perturb = RandomPerturb()
@ -52,12 +45,7 @@ class Robustness(LabelSensitiveMetric):
self._threshold = 0.1 # threshold to generate perturbation self._threshold = 0.1 # threshold to generate perturbation
self._activation_fn = activation_fn self._activation_fn = activation_fn
def evaluate(self, def evaluate(self, explainer, inputs, targets, saliency=None):
explainer: Attribution,
inputs: Tensor,
targets: _Label,
saliency: Optional[Tensor] = None
) -> _Array:
""" """
Evaluate robustness on single sample. 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., inputs (np.ndarray): Input array to perturb. The first dim of inputs is assumed to be the batch size, i.e.,
number of samples. number of samples.
reference (np.ndarray or float): Array of values to replace the elements in the original inputs. The shape 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.. given value..
masks (np.ndarray): Several boolean array to mark the perturbed positions. True marks the pixels to be 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 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 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. 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 (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 num_channels should be provided when input data have channels dimension, even if num_channel is 1.
provided, the inputs is assumed to be no-channel data, and the generated mask will have no channel If None is provided, the inputs is assumed to be no-channel data, and the generated mask will have
dimension. Default: None. no channel dimension. Default: None.
Return: Return:
mask (np.ndarray): boolen mask for generate perturbations. mask (np.ndarray): boolen mask for generate perturbations.

View File

@ -15,7 +15,6 @@
"""Occlusion explainer.""" """Occlusion explainer."""
import math import math
from typing import Tuple, Union
import numpy as np import numpy as np
from numpy.lib.stride_tricks import as_strided 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 as ms
import mindspore.nn as nn import mindspore.nn as nn
from mindspore import Tensor from mindspore import Tensor
from mindspore.nn import Cell
from .ablation import Ablation from .ablation import Ablation
from .perturbation import PerturbationAttribution from .perturbation import PerturbationAttribution
from .replacement import Constant from .replacement import Constant
from ...._utils import abs_max from ...._utils import abs_max
_Array = np.ndarray
_Label = Union[int, Tensor]
def _generate_patches(array, window_size, stride): def _generate_patches(array, window_size, stride):
"""View as windows.""" """View as windows."""
@ -76,16 +71,17 @@ class Occlusion(PerturbationAttribution):
Example: Example:
>>> from mindspore.explainer.explanation import Occlusion >>> 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") >>> param_dict = load_checkpoint("resnet50.ckpt")
>>> load_param_into_net(net, param_dict) >>> load_param_into_net(network, param_dict)
>>> occlusion = Occlusion(net) >>> occlusion = Occlusion(network)
>>> x = ms.Tensor(np.random.rand([1, 3, 224, 224]), ms.float32) >>> x = Tensor(np.random.rand([1, 3, 224, 224]), ms.float32)
>>> label = 1 >>> label = 1
>>> saliency = occlusion(x, label) >>> 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) super().__init__(network, activation_fn)
self._ablation = Ablation(perturb_mode='Deletion') 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_sample_per_dim = 32 # specify the number of perturbations each dimension.
self._num_per_eval = 32 # number of perturbations each evaluation step. 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'.""" """Call function for 'Occlusion'."""
self._verify_data(inputs, targets) 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) outputs_diff.reshape(outputs_diff.shape + (1,) * (len(masks.shape) - 2)) * masks).sum(axis=1).clip(1e-6)
weights += masks.sum(axis=1) weights += masks.sum(axis=1)
attribution = self._aggregation_fn(ms.Tensor(total_attribution / weights)) attribution = self._aggregation_fn(Tensor(total_attribution / weights))
return attribution return attribution
@staticmethod @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.""" """Generate masks to perturb contiguous regions."""
total_dim = np.prod(inputs.shape[1:]).item() total_dim = np.prod(inputs.shape[1:]).item()
template = np.arange(total_dim).reshape(inputs.shape[1:]) template = np.arange(total_dim).reshape(inputs.shape[1:])