3 votes

L'utilisation de torchvision.utils.save_image deux fois sur le même tenseur d'image fait que la deuxième sauvegarde ne fonctionne pas. Que se passe-t-il ?

(Méthode d'attaque rapide par signe de gradient détaillée ici : https://pytorch.org/tutorials/beginner/fgsm_tutorial.html )

J'ai un classificateur entraîné avec une précision de >90% que j'utilise pour créer ces exemples contradictoires, puis j'utilise torchvision.utils.save_image pour enregistrer les images dans différents dossiers.

La hiérarchie des dossiers est la suivante :

  • DOSSIER_1
    • original_image.jpg (1)
    • image_perturbée.jpg (2)
  • DOSSIER_2
    • image_perturbée.jpg (3)

Aquí (2) y (3) sont le même tenseur d'image, qui est la somme du tenseur d'image original et d'un tenseur d'image de perturbation - je veux juste sauver les images qui ont trompé le classificateur deux fois. Ce que je constate, c'est que (1) y (2) imprimer O.K., mais (3) n'imprime que le tenseur d'image de la perturbation (il a soustrait le tenseur d'image original !). Ainsi, lorsque j'ouvre (2) Je vois mon image originale avec tout le bruit en haut (des commutations aléatoires de pixels RVB à cause de l'attaque FGSM), mais lorsque j'ouvre le fichier (3) Je vois une toile blanche avec ces interrupteurs aléatoires de pixels RVB SEULEMENT.

Puisque j'imprime la même variable ( données perturbées ) deux fois, je ne comprends pas pourquoi torchvision.utils.save_image choisit de soustraire le tenseur de l'image de perturbation la deuxième fois que je l'appelle. Le code pour ce que je décris est ci-dessous, et data est le tenseur de l'image originale.

epsilon = 0.5
# Collect datagrad
data_grad = data.grad.data

# Call FGSM Attack
perturbed_data = fgsm_attack(data, epsilon, data_grad)

# Re-classify the perturbed image
perturbed_output = model(perturbed_data)
perturbed_output = torch.sigmoid(perturbed_output)
perturbed_output = perturbed_output.max(1, keepdim=True)[1]
max_pred  = perturbed_output.item()
final_pred = torch.tensor([0, 0]).to(device)
final_pred[max_pred] = 1

# Store all original and perturbed images, regardless of model prediction
torchvision.utils.save_image(data, "./FOLDER_1/original.jpg")
torchvision.utils.save_image(perturbed_data, "./FOLDER_1/perturbed_image.jpg")

# If the perturbed image fools our classifier, put a copy of it in FOLDER_2
if !torch.all(torch.eq(final_pred, target)):
    torchvision.utils.save_image(perturbed_data, "./FOLDER_2/perturbed_image.jpg")

Je suis presque sûr qu'il s'agit d'un bug de Torchvision, mais je pensais demander ici avant de soumettre un rapport de bug. Peut-être que quelqu'un voit quelque chose que je ne vois pas. J'ai également joint un exemple de (2) y (3) pour la visualisation. La première image est dans le format correct, mais la seconde s'imprime sans le tenseur d'image original.

original_img_tensor + pert_img_tensor pert_img_tensor

2voto

Eduardo Barrera Points 324

Il s'avère que torchvision.utils.save_image modifie le tenseur d'entrée. Une solution à ce problème est d'ajouter une ligne quelque part avant d'appeler torchvision.utils.save_image qui est similaire à ça :

perturbed_data_copy = perturbed_data

Vous pouvez alors sauvegarder deux fois l'image perturbée en toute sécurité si, lors du deuxième appel, vous utilisez données perturbées_copie au lieu de la données perturbées (qui a été modifié par torchvision.utils.save_image). Je vais soumettre un rapport de bogue et taguer ce post. Merci @Mat d'avoir signalé ce problème !

1voto

MLemon03 Points 21

J'ai eu ce problème aussi, et il provenait de torchvision en ne sauvegardant que le second tenseur. J'avais donc deux tenseurs (image) (image1 + image2) additionnés pour former un nouveau tenseur (image3), mais lorsque j'ai enregistré le nouveau tenseur (image3) une deuxième fois, il n'a été enregistré que comme le deuxième tenseur (image2) dans la somme.

PyTorch avait un PR pour corriger cela à la fin de l'année dernière.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X