|
- # Copyright 2019 Huawei Technologies Co., Ltd
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- """
- Base Class of Attack.
- """
- from abc import abstractmethod
-
- import numpy as np
-
- from mindarmour.utils._check_param import check_pair_numpy_param, \
- check_int_positive
- from mindarmour.utils.logger import LogUtil
-
- LOGGER = LogUtil.get_instance()
- TAG = 'Attack'
-
-
- class Attack:
- """
- The abstract base class for all attack classes creating adversarial examples.
- """
- def __init__(self):
- pass
-
- def batch_generate(self, inputs, labels, batch_size=64):
- """
- Generate adversarial examples in batch, based on input samples and
- their labels.
-
- Args:
- inputs (numpy.ndarray): Samples based on which adversarial
- examples are generated.
- labels (numpy.ndarray): Labels of samples, whose values determined
- by specific attacks.
- batch_size (int): The number of samples in one batch.
-
- Returns:
- numpy.ndarray, generated adversarial examples
-
- Examples:
- >>> inputs = Tensor([[0.2, 0.4, 0.5, 0.2], [0.7, 0.2, 0.4, 0.3]])
- >>> labels = [3, 0]
- >>> advs = attack.batch_generate(inputs, labels, batch_size=2)
- """
- arr_x, arr_y = check_pair_numpy_param('inputs', inputs, 'labels', labels)
- len_x = arr_x.shape[0]
- batch_size = check_int_positive('batch_size', batch_size)
- batchs = int(len_x / batch_size)
- rest = len_x - batchs*batch_size
- res = []
- for i in range(batchs):
- x_batch = arr_x[i*batch_size: (i + 1)*batch_size]
- y_batch = arr_y[i*batch_size: (i + 1)*batch_size]
- adv_x = self.generate(x_batch, y_batch)
- # Black-attack methods will return 3 values, just get the second.
- res.append(adv_x[1] if isinstance(adv_x, tuple) else adv_x)
-
- if rest != 0:
- x_batch = arr_x[batchs*batch_size:]
- y_batch = arr_y[batchs*batch_size:]
- adv_x = self.generate(x_batch, y_batch)
- # Black-attack methods will return 3 values, just get the second.
- res.append(adv_x[1] if isinstance(adv_x, tuple) else adv_x)
-
-
- adv_x = np.concatenate(res, axis=0)
- return adv_x
-
- @abstractmethod
- def generate(self, inputs, labels):
- """
- Generate adversarial examples based on normal samples and their labels.
-
- Args:
- inputs (numpy.ndarray): Samples based on which adversarial
- examples are generated.
- labels (numpy.ndarray): Labels of samples, whose values determined
- by specific attacks.
-
- Raises:
- NotImplementedError: It is an abstract method.
- """
- msg = 'The function generate() is an abstract function in class ' \
- '`Attack` and should be implemented in child class.'
- LOGGER.error(TAG, msg)
- raise NotImplementedError(msg)
|