UserWarning and RuntimeError in ProjectedGradientDescent due to Non-Writable NumPy Array and Device Mismatch
Closed this issue · 1 comments
Describe the bug
A UserWarning is raised, indicating that a given NumPy array is not writable, and PyTorch does not support non-writable tensors. Additionally, a RuntimeError is encountered stating that all tensors are expected to be on the same device.
To Reproduce
Steps to reproduce the behavior:
- Load a model onto a GPU using CUDA and initialize the optimizer.
- Use the Adversarial Robustness Toolbox (ART) to perform an adversarial attack using the
ProjectedGradientDescent
method withnorm = np.inf
. - Attempt to generate adversarial data with the
attack.generate
method. - Observe the warnings and error.
Expected behavior
The function should execute without raising a UserWarning or RuntimeError. The adversarial data should be generated correctly with all tensors on the same device.
Error Messages
adversarial-robustness-toolbox/art/attacks/evasion/projected_gradient_descent/projected_gradient_descent_pytorch.py:504: UserWarning: The given NumPy array is not writable, and PyTorch does not support non-writable tensors. This means writing to this tensor will result in undefined behavior. You may want to copy the array to protect its data or make it writable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at ../torch/csrc/utils/tensor_numpy.cpp:199.)
values_tmp = values_tmp.sign() * torch.minimum(values_tmp.abs(), torch.Tensor(eps))
Traceback (most recent call last):
[...]
data_attack = attack.generate(data.cpu().numpy(), y=targets.cpu().numpy())
File "adversarial-robustness-toolbox/art/attacks/evasion/projected_gradient_descent/projected_gradient_descent.py", line 202, in generate
return self._attack.generate(x=x, y=y, **kwargs)
File "adversarial-robustness-toolbox/art/attacks/evasion/projected_gradient_descent/projected_gradient_descent_pytorch.py", line 223, in generate
adv_x[batch_index_1:batch_index_2] = self._generate_batch(
File "adversarial-robustness-toolbox/art/attacks/evasion/projected_gradient_descent/projected_gradient_descent_pytorch.py", line 284, in _generate_batch
adv_x = self._compute_pytorch(
File "adversarial-robustness-toolbox/art/attacks/evasion/projected_gradient_descent/projected_gradient_descent_pytorch.py", line 451, in _compute_pytorch
perturbation = self._projection(x_adv - x_init, eps, self.norm)
File "adversarial-robustness-toolbox/art/attacks/evasion/projected_gradient_descent/projected_gradient_descent_pytorch.py", line 504, in _projection
values_tmp = values_tmp.sign() * torch.minimum(values_tmp.abs(), torch.Tensor(eps))
RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu!
Suggested solution:
Replace line 504, in "_projection" function in "adversarial-robustness-toolbox/art/attacks/evasion/projected_gradient_descent/projected_gradient_descent_pytorch.py":
From
values_tmp = values_tmp.sign() * torch.minimum(values_tmp.abs(), torch.Tensor(eps))
to
values_tmp = values_tmp.sign() * torch.minimum(values_tmp.abs(), torch.tensor(eps).to(values_tmp.device))
This solves both the non-writable NumPy array issue and the device mismatch issue.
System information (please complete the following information):
- OS: Linux-5.15.0-91-generic-x86_64-with-glibc2.35
- Python version: 3.9.7
- ART version: 1.18.0
- PyTorch version: 1.13.1+cu117
Hi @salomonhotegni Thank you very much for raising this issue and providing a pull request for the solution (#2455). We'll release it in the next days in ART 1.18.1.