Trusted-AI / adversarial-robustness-toolbox

Adversarial Robustness Toolbox (ART) - Python Library for Machine Learning Security - Evasion, Poisoning, Extraction, Inference - Red and Blue Teams
https://adversarial-robustness-toolbox.readthedocs.io/en/latest/
MIT License
4.91k stars 1.17k forks source link

float type mismatch #2475

Open j-moeller opened 3 months ago

j-moeller commented 3 months ago

Describe the bug float32 inputs get transformed internally into float64 inputs which leads to RuntimeError: Input type (double) and bias type (float) should be the same.

To Reproduce

  1. Create copy of get_started_pytorch.py
  2. Import HopSkipJump and replace FastGradientMethod(estimator=classifier, eps=0.2) with HopSkipJump(classifier=classifier)
  3. Run

Expected behavior The get_started_pytorch.py should run with the HopSkipJump attack instead of the FastGradientMethod.

System information (please complete the following information):

Possible fix

Through trial-and-error I tried to find the locations where float32 get transformed into float64. My working solution so far is this, but there might be places I missed or a better fix altogether:

@@ -438,9 +438,10 @@ class HopSkipJump(EvasionAttack):
             epsilon = 2.0 * dist / np.sqrt(self.curr_iter + 1)
             success = False

+
             while not success:
                 epsilon /= 2.0
-                potential_sample = current_sample + epsilon * update
+                potential_sample = (current_sample + epsilon * update).astype(current_sample.dtype)
                 success = self._adversarial_satisfactory(  # type: ignore
                     samples=potential_sample[None],
                     target=target,
@@ -499,6 +500,9 @@ class HopSkipJump(EvasionAttack):
             if threshold is None:
                 threshold = np.minimum(upper_bound * self.theta, self.theta)

+        upper_bound = upper_bound.astype(current_sample.dtype)
+        lower_bound = lower_bound.astype(current_sample.dtype)
+
         # Then start the binary search
         while (upper_bound - lower_bound) > threshold:
             # Interpolation point
@@ -602,7 +606,7 @@ class HopSkipJump(EvasionAttack):
                 keepdims=True,
             )
         )
-        eval_samples = np.clip(current_sample + delta * rnd_noise, clip_min, clip_max)
+        eval_samples = np.clip(current_sample + delta * rnd_noise, clip_min, clip_max, dtype=current_sample.dtype)
         rnd_noise = (eval_samples - current_sample) / delta
beat-buesser commented 1 month ago

Hi @j-moeller Thank you very much for raising this issue. I think your analysis is correct. We'll try to fix it as soon as possible.