def test_isnan_true(t: Tensor) -> Tensor: return ep.isnan(t + ep.nan)
def test_isnan_false(t: Tensor) -> Tensor: return ep.isnan(t)
def run( self, model: Model, inputs: T, criterion: Union[Criterion, T], *, early_stop: Optional[float] = None, starting_points: Optional[T] = None, **kwargs: Any, ) -> T: """For models that preprocess their inputs by binarizing the inputs, this attack can improve adversarials found by other attacks. It does this by utilizing information about the binarization and mapping values to the corresponding value in the clean input or to the right side of the threshold. Parameters ---------- threshold : float The treshold used by the models binarization. If none, defaults to (model.bounds()[1] - model.bounds()[0]) / 2. included_in : str Whether the threshold value itself belongs to the lower or upper interval. """ raise_if_kwargs(kwargs) if starting_points is None: raise ValueError( "BinarizationRefinementAttack requires starting_points") (o, x), restore_type = ep.astensors_(inputs, starting_points) del inputs, starting_points, kwargs criterion = get_criterion(criterion) is_adversarial = get_is_adversarial(criterion, model) if self.threshold is None: min_, max_ = model.bounds threshold = (min_ + max_) / 2.0 else: threshold = self.threshold assert o.dtype == x.dtype nptype = o.reshape(-1)[0].numpy().dtype.type if nptype not in [np.float16, np.float32, np.float64]: raise ValueError( # pragma: no cover f"expected dtype to be float16, float32 or float64, found '{nptype}'" ) threshold = nptype(threshold) offset = nptype(1.0) if self.included_in == "lower": lower_ = threshold upper_ = np.nextafter(threshold, threshold + offset) elif self.included_in == "upper": lower_ = np.nextafter(threshold, threshold - offset) upper_ = threshold else: raise ValueError( f"expected included_in to be 'lower' or 'upper', found '{self.included_in}'" ) assert lower_ < upper_ p = ep.full_like(o, ep.nan) lower = ep.ones_like(o) * lower_ upper = ep.ones_like(o) * upper_ indices = ep.logical_and(o <= lower, x <= lower) p = ep.where(indices, o, p) indices = ep.logical_and(o <= lower, x >= upper) p = ep.where(indices, upper, p) indices = ep.logical_and(o >= upper, x <= lower) p = ep.where(indices, lower, p) indices = ep.logical_and(o >= upper, x >= upper) p = ep.where(indices, o, p) assert not ep.any(ep.isnan(p)) is_adv1 = is_adversarial(x) is_adv2 = is_adversarial(p) if (is_adv1 != is_adv2).any(): raise ValueError( "The specified threshold does not match what is done by the model." ) return restore_type(p)
def run( self, model: Model, inputs: T, criterion: Union[Criterion, T], *, early_stop: Optional[float] = None, starting_points: Optional[T] = None, **kwargs: Any, ) -> T: raise_if_kwargs(kwargs) if starting_points is None: raise ValueError("BinarizationRefinementAttack requires starting_points") (o, x), restore_type = ep.astensors_(inputs, starting_points) del inputs, starting_points, kwargs criterion = get_criterion(criterion) is_adversarial = get_is_adversarial(criterion, model) if self.threshold is None: min_, max_ = model.bounds threshold = (min_ + max_) / 2.0 else: threshold = self.threshold assert o.dtype == x.dtype nptype = o.reshape(-1)[0].numpy().dtype.type if nptype not in [np.float16, np.float32, np.float64]: raise ValueError( # pragma: no cover f"expected dtype to be float16, float32 or float64, found '{nptype}'" ) threshold = nptype(threshold) offset = nptype(1.0) if self.included_in == "lower": lower_ = threshold upper_ = np.nextafter(threshold, threshold + offset) elif self.included_in == "upper": lower_ = np.nextafter(threshold, threshold - offset) upper_ = threshold else: raise ValueError( f"expected included_in to be 'lower' or 'upper', found '{self.included_in}'" ) assert lower_ < upper_ p = ep.full_like(o, ep.nan) lower = ep.ones_like(o) * lower_ upper = ep.ones_like(o) * upper_ indices = ep.logical_and(o <= lower, x <= lower) p = ep.where(indices, o, p) indices = ep.logical_and(o <= lower, x >= upper) p = ep.where(indices, upper, p) indices = ep.logical_and(o >= upper, x <= lower) p = ep.where(indices, lower, p) indices = ep.logical_and(o >= upper, x >= upper) p = ep.where(indices, o, p) assert not ep.any(ep.isnan(p)) is_adv1 = is_adversarial(x) is_adv2 = is_adversarial(p) if (is_adv1 != is_adv2).any(): raise ValueError( "The specified threshold does not match what is done by the model." ) return restore_type(p)
def __call__( self, inputs, labels, *, adversarials, criterion, threshold=None, included_in="upper", ): """For models that preprocess their inputs by binarizing the inputs, this attack can improve adversarials found by other attacks. It does this by utilizing information about the binarization and mapping values to the corresponding value in the clean input or to the right side of the threshold. Parameters ---------- threshold : float The treshold used by the models binarization. If none, defaults to (model.bounds()[1] - model.bounds()[0]) / 2. included_in : str Whether the threshold value itself belongs to the lower or upper interval. """ originals = ep.astensor(inputs) labels = ep.astensor(labels) def is_adversarial(p: ep.Tensor) -> ep.Tensor: """For each input in x, returns true if it is an adversarial for the given model and criterion""" logits = ep.astensor(self.model.forward(p.tensor)) return criterion(originals, labels, p, logits) o = ep.astensor(inputs) x = ep.astensor(adversarials) min_, max_ = self.model.bounds() if threshold is None: threshold = (min_ + max_) / 2.0 assert o.dtype == x.dtype dtype = o.dtype if dtype == o.backend.float16: nptype = np.float16 elif dtype == o.backend.float32: nptype = np.float32 elif dtype == o.backend.float64: nptype = np.float64 else: raise ValueError( "expected dtype to be float16, float32 or float64, found '{dtype}'" ) threshold = nptype(threshold) offset = nptype(1.0) if included_in == "lower": lower = threshold upper = np.nextafter(threshold, threshold + offset) elif included_in == "upper": lower = np.nextafter(threshold, threshold - offset) upper = threshold else: raise ValueError( "expected included_in to be 'lower' or 'upper', found '{included_in}'" ) assert lower < upper p = ep.full_like(o, ep.nan) lower = ep.ones_like(o) * lower upper = ep.ones_like(o) * upper indices = ep.logical_and(o <= lower, x <= lower) p = ep.where(indices, o, p) indices = ep.logical_and(o <= lower, x >= upper) p = ep.where(indices, upper, p) indices = ep.logical_and(o >= upper, x <= lower) p = ep.where(indices, lower, p) indices = ep.logical_and(o >= upper, x >= upper) p = ep.where(indices, o, p) assert not ep.any(ep.isnan(p)) is_adv1 = is_adversarial(x) is_adv2 = is_adversarial(p) assert (is_adv1 == is_adv2).all( ), "The specified threshold does not match what is done by the model." return p.tensor