diff --git a/mindarmour/attacks/black/natural_evolutionary_strategy.py b/mindarmour/attacks/black/natural_evolutionary_strategy.py index 4f76135..91f6ab9 100644 --- a/mindarmour/attacks/black/natural_evolutionary_strategy.py +++ b/mindarmour/attacks/black/natural_evolutionary_strategy.py @@ -29,12 +29,6 @@ LOGGER = LogUtil.get_instance() TAG = 'NES' -def _one_hot(index, total): - arr = np.zeros((total)) - arr[index] = 1.0 - return arr - - def _bound(image, epislon): lower = np.clip(image - epislon, 0, 1) upper = np.clip(image + epislon, 0, 1) diff --git a/mindarmour/attacks/black/pointwise_attack.py b/mindarmour/attacks/black/pointwise_attack.py index 7d7c554..3a45df5 100644 --- a/mindarmour/attacks/black/pointwise_attack.py +++ b/mindarmour/attacks/black/pointwise_attack.py @@ -167,10 +167,9 @@ class PointWiseAttack(Attack): 'is: {}'.format(unperturbed_img.dtype, perturbed_img.dtype) LOGGER.error(TAG, msg) raise ValueError(msg) - - LOGGER.debug(TAG, 'Before optimize, the mse distance between original ' - 'sample and adversarial sample is: {}' - .format(self._distance(perturbed_img, unperturbed_img))) + l2_dis = np.linalg.norm(perturbed_img - unperturbed_img) + LOGGER.debug(TAG, 'Before optimize, the l2 distance between original ' + 'sample and adversarial sample is: {}'.format(l2_dis)) # recover pixel if image is adversarial for _ in range(self._max_iter): is_improve = False @@ -190,8 +189,9 @@ class PointWiseAttack(Attack): break else: recover[ite_ind] = perturbed_img[ite_ind] - if not is_improve or (self._distance( - perturbed_img, unperturbed_img) <= self._get_threthod()): + l2_dis = np.linalg.norm(perturbed_img - unperturbed_img) + if not is_improve or (np.square(l2_dis) / np.sqrt(len(pixels_ind)) + <= self._get_threthod()): break LOGGER.debug(TAG, 'first round: Query count {}'.format(query_count)) LOGGER.debug(TAG, 'Starting binary searches.') @@ -213,12 +213,10 @@ class PointWiseAttack(Attack): is_improve = True mask[ite_ind] = True perturbed_img[ite_ind] = recover[ite_ind] + l2_dis = np.linalg.norm(perturbed_img - unperturbed_img) LOGGER.debug(TAG, 'Reset {}th pixel value to original, ' - 'mse distance: {}.'.format( - ite_ind, - self._distance(perturbed_img, - unperturbed_img))) + 'l2 distance: {}.'.format(ite_ind, l2_dis)) break else: # use binary searches @@ -232,15 +230,15 @@ class PointWiseAttack(Attack): is_improve = True mask[ite_ind] = True perturbed_img[ite_ind] = optimized_value + l2_dis = np.linalg.norm(perturbed_img - unperturbed_img) LOGGER.debug(TAG, 'Reset {}th pixel value to original, ' - 'mse distance: {}.'.format( - ite_ind, - self._distance(perturbed_img, - unperturbed_img))) + 'l2 distance: {}.'.format(ite_ind, + l2_dis)) break - if not is_improve or (self._distance( - perturbed_img, unperturbed_img) <= self._get_threthod()): + l2_dis = np.linalg.norm(perturbed_img - unperturbed_img) + if not is_improve or (np.square(l2_dis) / np.sqrt(len(pixels_ind)) + <= self._get_threthod()): LOGGER.debug(TAG, 'second optimized finish.') break LOGGER.info(TAG, 'Optimized finished, query count is {}'.format(query_count)) @@ -295,32 +293,14 @@ class PointWiseAttack(Attack): is_adv, start_adv, query_c = self._init_attack.generate(inputs, labels) return is_adv, start_adv, query_c - def _distance(self, perturbed_img, unperturbed_img): - """ - Calculate Mean Squared Error (MSE) to evaluate the optimized process. - - Args: - perturbed_img (numpy.ndarray): Adversarial sample to be optimized. - unperturbed_img (numpy.ndarray): As a reference benigh sample. - - Returns: - float, Calculation of Mean Squared Error (MSE). - """ - return np.square(np.subtract(perturbed_img, unperturbed_img)).mean() - - def _get_threthod(self, method='MSE'): + def _get_threthod(self): """ Return a float number, when distance small than this number, optimize will abort early. - Args: - method: distance method. Default: MSE. - Returns: float, the optimized level, the smaller of number, the better of adversarial sample. """ predefined_threshold = 0.01 - if method == 'MSE': - return predefined_threshold return predefined_threshold diff --git a/mindarmour/attacks/lbfgs.py b/mindarmour/attacks/lbfgs.py index 42ded16..a3c2ccc 100644 --- a/mindarmour/attacks/lbfgs.py +++ b/mindarmour/attacks/lbfgs.py @@ -127,12 +127,13 @@ class LBFGS(Attack): def _loss(self, cur_input, start_input, cur_eps, shape, labels): """ - The l-bfgs-b loss used is Mean Square Error distance from original - input plus crossentropy loss. + The l-bfgs-b loss is the sum of l2 distances to the original input plus + the cross-entropy loss. """ cur_input = cur_input.astype(self._dtype) - mse_distance = np.mean(np.square(start_input - cur_input)) / \ - ((self._box_max - self._box_min)**2) + l2_distance = np.linalg.norm(cur_input.reshape( + (cur_input.shape[0], -1)) - start_input.reshape( + (start_input.shape[0], -1))) logits = self._forward_one(cur_input.reshape(shape)).flatten() logits = logits - np.max(logits) if self._sparse: @@ -146,7 +147,7 @@ class LBFGS(Attack): crossentropy = logits[target_class] - np.log(np.sum(np.exp(logits))) gradient = -self._gradient(cur_input, labels, shape).flatten() - return (mse_distance + cur_eps*crossentropy).astype(self._dtype), \ + return (l2_distance + cur_eps*crossentropy).astype(self._dtype), \ gradient.astype(np.float64) def _lbfgsb(self, start_input, cur_eps, shape, labels, bounds):