Tutorial

Austricksen eines neuronalen Netzwerks in Python 3

Published on August 6, 2020
Default avatar

By Alvin Wan

AI PhD Student @ UC Berkeley

Deutsch
Austricksen eines neuronalen Netzwerks in Python 3

Der Autor hat Dev Color dazu ausgewählt, im Rahmen des Programms Write for DOnations eine Spende zu erhalten.

Kann ein neuronales Netzwerk zur Klassifizierung von Tieren ausgetrickst werden? Das Austricksen einer solchen Klassifizierung mag vielleicht wenig Konsequenzen haben, doch sieht das bei Gesichtsauthentifizierung schon anders aus. Und was ist mit der Software von Prototypen selbstfahrender Autos? Zum Glück gibt es zahlreiche Ingenieure und Forscher, die bei unseren mobilen Geräten und Autos zwischen einem Computermodell für Prototypen und Modellen mit Produktionsqualität stehen. Dennoch haben diese Risiken erhebliche Auswirkungen und müssen von Benutzern, die maschinelles Lernen anwenden, berücksichtigt werden.

In diesem Tutorial versuchen Sie, eine Klassifizierungsanwendung für Tiere zu täuschen bzw. auszutricksen. Wenn Sie das Tutorial durcharbeiten, verwenden Sie OpenCV, eine Computer-Vision-Bibliothek, und PyTorch, eine Deep Learning Library. Wir werden die folgenden Themen im zugehörigen Bereich des Adversarial Machine Learning behandeln:

  • Erstellen eines gezielten Adversial-Beispiels. Auswählen eines Bilds – etwa eines Hunds. Auswählen einer Zielklasse, z. B. eine Katze. Ihr Ziel besteht darin, das neuronale Netzwerk so zu täuschen, dass es denkt, dass der abgebildete Hund eine Katze sei.
  • Erstellen Sie eine Adversarial-Verteidigung. Kurz gesagt: Schützen Sie Ihr neuronales Netzwerk vor diesen trickreichen Bildern, ohne zu wissen, was der Trick ist.

Am Ende des Tutorials verfügen Sie über ein Werkzeug zum Austricksen neuronaler Netzwerke und ein Verständnis dafür, wie man sich gegen Tricks verteidigen kann.

Voraussetzungen

Um dieses Tutorial zu absolvieren, benötigen Sie Folgendes:

  • Eine lokale Entwicklungsumgebung für Python 3 mit mindestens 1 GB RAM. Unter How to Install and Set Up a Local Programming Environment for Python 3 (Installieren und Einrichten einer lokalen Programmierumgebung für Python 3) finden Sie Informationen darüber, wie Sie die benötigten Konfigurationen vornehmen.
  • Es wird empfohlen, Build an Emotion-Based Dog Filter (Erstellen eines emotionsbasierten Hundefilters) zu konsultieren; dieses Tutorial wird nicht explizit verwendet, führt aber in den Begriff der Klassifizierung ein.

Schritt 1 – Erstellen des Projekts und Installieren von Abhängigkeiten

Wir wollen einen Arbeitsbereich für dieses Projekt erstellen und die Abhängigkeiten installieren, die wir benötigen. Sie nennen Ihren Arbeitsbereich AdversarialML:

  1. mkdir ~/AdversarialML

Navigieren Sie zum Verzeichnis AdversarialML:

  1. cd ~/AdversarialML

Erstellen Sie ein Verzeichnis, das alle Ihre Ressourcen enthält:

  1. mkdir ~/AdversarialML/assets

Erstellen Sie dann eine neue virtuelle Umgebung für das Projekt:

  1. python3 -m venv adversarialml

Aktivieren Sie Ihre Umgebung:

  1. source adversarialml/bin/activate

Installieren Sie anschließend PyTorch, ein Deep-Learning-Framework für Python, das wir in diesem Tutorial verwenden werden.

Auf macOS installieren Sie Pytorch mit dem folgenden Befehl:

  1. python -m pip install torch==1.2.0 torchvision==0.4.0

Auf Linux und Windows verwenden Sie die folgenden Befehle für einen reinen CPU-Build:

  1. pip install torch==1.2.0+cpu torchvision==0.4.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
  2. pip install torchvision

Installieren Sie nun vorgepackte Binaries für OpenCV und numpy; das sind Bibliotheken für Computer-Vision bzw. lineare Algebra. OpenCV bietet Hilfsfunktionen wie Bilddrehung und numpy bietet Hilfsfunktionen für lineare Algebra an, z. B. eine Matrixinversion:

  1. python -m pip install opencv-python==3.4.3.18 numpy==1.14.5

Auf Linux-Distributionen müssen Sie libSM.so installieren:

  1. sudo apt-get install libsm6 libxext6 libxrender-dev

Nach Installation der Abhängigkeiten führen wir eine Tierklassifizierung namens ResNet18 aus, was wir als Nächstes beschreiben werden.

Schritt 2 — Ausführen einer vordefinierten Tierklassifizierung

Die torchvision-Bibliothek, die offizielle Computer-Vision-Bibliothek für PyTorch, enthält vortrainierte Versionen von verbreiteten neuronalen Computer-Vision-Netzwerken. Diese neuronalen Netzwerke werden alle in ImageNet 2012 trainiert, einem Datensatz mit 1,2 Millionen Trainingsbildern und 1.000 Klassen. Diese Klassen umfassen Fahrzeuge, Orte und vor allem Tiere. In diesem Schritt werden Sie eines dieser vortrainierten neuronalen Netzwerke (ResNet18) ausführen. Wir werden ResNet18, trainiert in ImageNet, als „Tierklassifizierung“ bezeichnen.

Was ist ResNet18? ResNet18 ist das kleinste neuronale Netzwerk in einer Familie neuronaler Netzwerke, die Residual Neural Networks genannt werden, entwickelt von MSR (et al.). Kurz gesagt: Er hat herausgefunden, dass ein neuronales Netzwerk (angegeben als Funktion f mit Eingabe x und Ausgabe f(x)) mit einer "residual connection" x + f(x) bessere Ergebnisse liefern würde. Diese Residual Connection wird auch heute noch in hochmodernen neuronalen Netzwerken häufig verwendet. Beispielsweise FBNetV2, FBNetV3.

Laden Sie dieses Bild eines Hundes mit dem folgenden Befehl herunter:

  1. wget -O assets/dog.jpg https://assets.digitalocean.com/articles/trick_neural_network/step2a.png

Bild von Corgi nahe Teich

Laden Sie dann eine JSON-Datei herunter, um die neuronale Netzwerkausgabe in einen menschenlesbaren Klassennamen zu konvertieren:

  1. wget -O assets/imagenet_idx_to_label.json https://raw.githubusercontent.com/do-community/tricking-neural-networks/master/utils/imagenet_idx_to_label.json

Erstellen Sie als Nächstes ein Skript zum Ausführen Ihres vortrainierten Modells für das Hundebild. Erstellen Sie eine neue Datei namens step_2_pretrained.py:

  1. nano step_2_pretrained.py

Fügen Sie zunächst das Python-Boilerplate hinzu, indem Sie die erforderlichen Pakete importieren und eine main-Funktion deklarieren:

step_2_pretrained.py
from PIL import Image
import json
import torchvision.models as models
import torchvision.transforms as transforms
import torch
import sys

def main():
    pass

if __name__ == '__main__':
    main()

Als Nächstes laden Sie das Mapping von neuronaler Netzwerkausgabe zu menschenlesbaren Klassennamen. Fügen Sie dies direkt nach Ihren Importanweisungen und vor Ihrer main-Funktion hinzu:

step_2_pretrained.py
. . .
def get_idx_to_label():
    with open("assets/imagenet_idx_to_label.json") as f:
        return json.load(f)
. . .

Erstellen Sie eine Funktion zur Bildtransformation, die sicherstellt, dass Ihr Eingabebild zum einen die richtigen Dimensionen aufweist und zum anderen richtig normalisiert ist. Fügen Sie direkt nach der letzten Funktion folgende Funktion hinzu:

step_2_pretrained.py
. . .
def get_image_transform():
    transform = transforms.Compose([
      transforms.Resize(224),
      transforms.CenterCrop(224),
      transforms.ToTensor(),
      transforms.Normalize(mean=[0.485, 0.456, 0.406],
                           std=[0.229, 0.224, 0.225])
    ])
    return transform
. . .

In get_image_transform definieren Sie eine Reihe verschiedener Transformationen für die Bilder, die an Ihr neuronales Netzwerk übergeben werden:

  • transforms.Resize(224): Ändert die kleinere Seite des Bildes auf 224. Wenn Ihr Bild beispielsweise 448 x 672 groß ist, würde diese Operation das Bild beispielsweise auf 224 x 336 reduzieren.
  • transforms.CenterCrop(224): Nimmt einen Zuschnitt von der Bildmitte mit der Größe 224 x 224 vor.
  • transforms.ToTensor(): Konvertiert das Bild in einen PyTorch-Tensor. Alle PyTorch-Modelle erfordern PyTorch-Tensoren als Eingabe.
  • transforms.Normalize(mean=..., std=...): Standardisiert Ihre Eingabe, indem der Mittelwert subtrahiert und dann durch die Standardabweichung geteilt wird. Dies wird in der torchvision-Dokumentation genauer beschrieben.

Fügen Sie ein Dienstprogramm hinzu, um die Tierklasse je nach Bild vorherzusagen. Diese Methode verwendet die beiden vorherigen Dienstprogramme zur Durchführung der Tierklassifizierung:

step_2_pretrained.py
. . .
def predict(image):
    model = models.resnet18(pretrained=True)
    model.eval()

    out = model(image)

    _, pred = torch.max(out, 1)  
    idx_to_label = get_idx_to_label()  
    cls = idx_to_label[str(int(pred))]  
    return cls
. . .

Hier klassifiziert die Funktion predict das bereitgestellte Bild mit einem vortrainierten neuronalen Netzwerk:

  • model.resnet18(pretrained=True): Lädt ein vortrainiertes neuronales Netzwerk namens ResNet18.
  • model.eval(): Ändert das vorhandene Modell so, dass es im Modus ‘evaluation’ ausgeführt wird. Der einzige andere Modus ist der Modus ‘training’, doch ist der Trainingsmodus nicht erforderlich, da Sie das Modell in diesem Tutorial nicht trainieren (d. h. die Parameter des Modells nicht aktualisieren).
  • out = model(image): Führt das neuronale Netzwerk für das bereitgestellte, transformierte Bild aus.
  • _, pred = torch.max(out, 1): Das neuronale Netzwerk gibt eine Wahrscheinlichkeit für jede mögliche Klasse aus. Dieser Schritt berechnet den Index der Klasse mit der höchsten Wahrscheinlichkeit. Beispielsweise wenn out = [0.4, 0.1, 0.2], dann pred = 0.
  • idx_to_label = idx_to_label: Erhält ein Mapping vom Klassenindex zu menschenlesbaren Klassennamen. Beispielsweise könnte das Mapping {0: Katze, 1: Hund, 2: Fisch} lauten.
  • cls = idx_to_label[str(int(pred))]: Konvertiert den vorhergesagten Klassenindex in einen Klassennamen. Die in den letzten beiden Punkten genannten Beispiele würden cls = idx_to_label[0] = 'cat' ergeben.

Als Nächstes fügen Sie nach der letzten Funktion ein Dienstprogramm zum Laden von Bildern hinzu:

step_2_pretrained.py
. . .
def load_image():
    assert len(sys.argv) > 1, 'Need to pass path to image'
    image = Image.open(sys.argv[1])

    transform = get_image_transform()
    image = transform(image)[None]
    return image
. . .

Dadurch wird ein Bild aus dem im ersten Argument angegebenen Pfad in das Skript geladen. transform(image)[None] wendet die Reihenfolge der in den vorherigen Zeilen definierten Bildtransformationen an.

Abschließend füllen Sie Ihre main-Funktion mit Folgendem, um Ihr Bild zu laden und das Tier im Bild zu klassifizieren:

step_2_pretrained.py
def main():
    x = load_image()
    print(f'Prediction: {predict(x)}')

Vergewissern Sie sich, dass Ihre Datei mit unserem letzten Schritt 2 bei step_2_pretrained.py in GitHub übereinstimmt. Speichern und beenden Sie Ihr Skript und führen Sie die Tierklassifizierung aus:

  1. python step_2_pretrained.py assets/dog.jpg

Dadurch wird folgende Ausgabe erstellt, was zeigt, dass Ihre Tierklassifizierung wie erwartet funktioniert:

Output
Prediction: Pembroke, Pembroke Welsh corgi

Das beschließt die Ausführung von Inferenz mit Ihrem vortrainierten Modell. Als Nächstes sehen Sie ein Adversarial-Beispiel in der Praxis, bei dem ein neuronales Netzwerk mit unmerklichen Unterschieden im Bild ausgetrickst wird.

Schritt 3 — Ausprobieren eines Adversarial-Beispiels

Jetzt werden Sie ein Adversarial-Beispiel synchronisieren und das neuronale Netzwerk für dieses Beispiel testen. Für dieses Tutorial erstellen Sie verschiedene Adversarial-Beispiele im Format x + r, wobei x das ursprüngliche Bild und r eine „Perturbation“ ist. Sie werden die Perturbation r noch selbst erstellen, doch in diesem Schritt werden Sie eine herunterladen, die wir zuvor für Sie erstellt haben. Starten Sie mit dem Herunterladen der Perturbation r:

  1. wget -O assets/adversarial_r.npy https://github.com/do-community/tricking-neural-networks/blob/master/outputs/adversarial_r.npy?raw=true

Verbinden Sie nun das Bild mit der Perturbation. Erstellen Sie eine neue Datei namens step_3_adversarial.py:

  1. nano step_3_adversarial.py

In dieser Datei führen Sie den folgenden Prozess mit drei Schritten aus, um ein adversarial-Beispiel zu erstellen:

  1. Transformieren eines Bilds
  2. Anwenden der Perturbation r
  3. Inverses Transformieren des pertubierten Bilds

Am Ende von Schritt 3 werden Sie über ein gegensätzliches Bild verfügen. Importieren Sie zunächst die erforderlichen Pakete und deklarieren Sie eine Hauptfunktion:

step_3_adversarial.py
from PIL import Image
import torchvision.transforms as transforms
import torch
import numpy as np
import os
import sys

from step_2_pretrained import get_idx_to_label, get_image_transform, predict, load_image


def main():
    pass


if __name__ == '__main__':
    main()

Erstellen Sie als Nächstes eine “Bildtransformation”, die die frühere Bildtransformation umkehrt. Platzieren Sie dies nach Ihren Importen vor der main-Funktion:

step_3_adversarial.py
. . .
def get_inverse_transform():
    return transforms.Normalize(
        mean=[-0.485/0.229, -0.456/0.224, -0.406/0.255],  # INVERSE normalize images, according to https://pytorch.org/docs/stable/torchvision/models.html
        std=[1/0.229, 1/0.224, 1/0.255])
. . .

Wie zuvor subtrahiert die Funktion transforms.Normalize den Mittelwert und teilt durch die Standardabweichung (d. h. für das ursprüngliche Bild x, y = transforms.Normalize(mean=u, std=o) = (x - u) / o). Sie machen etwas Algebra und definieren eine neue Operation, die diese Normalisierungsfunktion umkehrt (transforms.Normalize(mean=-u/o, std=1/o) = (y - -u/o) / 1/o = (y + u/o) o = yo + u = x).

Fügen Sie im Rahmen der inversen Transformation eine Methode hinzu, die einen PyTorch-Tensor in ein PIL-Bild umwandelt. Fügen Sie dies nach der letzten Funktion hinzu:

step_3_adversarial.py
. . .
def tensor_to_image(tensor):
    x = tensor.data.numpy().transpose(1, 2, 0) * 255.  
    x = np.clip(x, 0, 255)
    return Image.fromarray(x.astype(np.uint8))
. . .
  • tensor.data.numpy() konvertiert den PyTorch-Tensor in ein NumPy-Array. .transpose(1, 2, 0) arrangiert (Kanäle, Breite, Höhe) in (Höhe, Breite, Kanäle) um. Dieses NumPy-Array befindet sich etwa im Bereich (0, 1). Abschließend multiplizieren Sie mit 255, um sicherzustellen, dass das Bild nun im Bereich (0, 255) ist.
  • np.clip sorgt dafür, dass alle Werte im Bild zwischen (0, 255) liegen.
  • x.astype(np.uint8) sorgt dafür, dass alle Bildwerte integer sind. Abschließend erstellt Image.fromarray(...) ein PIL-Bildobjekt aus dem NumPy-Array.

Verwenden Sie dann diese Dienstprogramme zum Erstellen des adversarial-Beispiels mit Folgendem:

step_3_adversarial.py
. . .
def get_adversarial_example(x, r):
    y = x + r
    y = get_inverse_transform()(y[0])
    image = tensor_to_image(y)
    return image
. . .

Diese Funktion generiert das adversarial-Beispiel, wie zu Anfang des Abschnitts beschrieben:

  1. y = x + r. Nehmen Sie Ihre Perturbation r und fügen Sie sie dem Originalbild x hinzu.
  2. get_inverse_transform: Erhalten und wenden Sie die umgekehrte Bildtransformation an, die Sie in einigen Zeilen vorher definiert haben.
  3. tensor_to_image: Konvertieren Sie abschließend den PyTorch-Tensor wieder in ein Bildobjekt.

Als Letztes ändern Sie Ihre main-Funktion so, dass sie das Laden des Bilds, das Laden der adversarial-Perturbation r, das Anwenden der Perturbation, das Speichern des adversarial-Beispiels auf Festplatte und das Ausführen der Vorhersage für das adversarial-Beispiel ausführt:

step_3_adversarial.py
def main():
    x = load_image()
    r = torch.Tensor(np.load('assets/adversarial_r.npy'))

    # save perturbed image
    os.makedirs('outputs', exist_ok=True)
    adversarial = get_adversarial_example(x, r)
    adversarial.save('outputs/adversarial.png')

    # check prediction is new class
    print(f'Old prediction: {predict(x)}')
    print(f'New prediction: {predict(x + r)}')

Ihre abgeschlossene Datei sollte mit step_3_adversarial.py in GitHub übereinstimmen. Speichern Sie die Datei, beenden Sie den Editor und starten Sie Ihr Skript mit:

  1. python step_3_adversarial.py assets/dog.jpg

Sie sehen diese Ausgabe:

Output
Old prediction: Pembroke, Pembroke Welsh corgi New prediction: goldfish, Carassius auratus

Sie haben nun ein Adversarial-Beispiel erstellt: Es täuscht das neuronale Netzwerk, sodass es denkt, ein Corgi sei ein Goldfisch. Im nächsten Schritt erstellen Sie tatsächlich die Perturbation r, die Sie hier verwendet haben.

Schritt 4 — Verstehen eines Adversarial-Beispiels

Informationen zur Klassifizierung finden Sie in „How to Build an Emotion-Based Dog Filter“ („Erstellen eines emotionsbasierten Hundefilters“).

Sie erinnern sich bestimmt daran, dass Ihr Klassifizierungsmodell für jede Klasse eine Wahrscheinlichkeit ausgibt. Bei der Inferenz prognostiziert das Modell die Klasse mit der höchsten Wahrscheinlichkeit. Beim Training aktualisieren Sie die Modellparameter t so, dass die Wahrscheinlichkeit der richtigen Klasse y angesichts Ihrer Daten x maximiert wird.

argmax_y P(y|x,t)

Um jedoch Adversarial-Beispiele zu generieren, ändern Sie nun Ihr Ziel. Anstatt eine Klasse zu finden, besteht Ihr Ziel nun darin, ein neues Bild (x) zu finden. Wählen Sie eine beliebige andere Klasse als die richtige Klasse. Wir nennen diese neue Klasse w. Ihr neues Ziel besteht nun darin, die Wahrscheinlichkeit der falschen Klasse zu maximieren.

argmax_x P(w|x)

Beachten Sie, dass die neuronalen Netzwerkgewichtungen t aus dem obigen Ausdruck fehlen. Das liegt daran, dass Sie nun die Rolle des Adversary übernehmen: Jemand anderes hat ein Modell trainiert und bereitgestellt. Sie dürfen nur Adversarial-Eingaben erstellen und dürfen das bereitgestellte Modell nicht ändern. Um das Adversarial-Beispiel x zu generieren, können Sie “training” ausführen. Allerdings aktualisieren Sie nicht die neuronalen Netzwerkgewichtungen, sondern das Eingabebild mit dem neuen Ziel.

Zur Erinnerung: In diesem Tutorial gehen Sie davon aus, dass das Adversarial-Beispiel eine affine Transformation von x ist. Mit anderen Worten: Ihr Adversarial-Beispiel nimmt die Form x + r für einige r an. Im nächsten Schritt schreiben Sie ein Skript zur Generierung dieses r.

Schritt 5 — Erstellen eines Adversarial-Beispiels

In diesem Schritt lernen Sie eine Perturbation r, sodass Ihr Corgi als Goldfisch falsch klassifiziert wird. Erstellen Sie eine neue Datei namens step_5_perturb.py:

  1. nano step_5_perturb.py

Importieren Sie zunächst die erforderlichen Pakete und deklarieren Sie eine main-Funktion:

step_5_perturb.py
from torch.autograd import Variable
import torchvision.models as models
import torch.nn as nn
import torch.optim as optim
import numpy as np
import torch
import os

from step_2_pretrained import get_idx_to_label, get_image_transform, predict, load_image
from step_3_adversarial import get_adversarial_example


def main():
    pass


if __name__ == '__main__':
    main()

Definieren Sie direkt nach Ihren Importen und vor der main-Funktion zwei Konstanten:

step_5_perturb.py
. . .
TARGET_LABEL = 1
EPSILON = 10 / 255.
. . .

Die erste Konstante TARGET_LABEL ist die Klasse, um den Corgi falsch zu klassifizieren. In diesem Fall entspricht der Index 1 „Goldfisch“. Die zweite Konstante EPSILON ist die maximale Perturbation, die für jeden Bildwert erlaubt ist. Diese Grenze wird eingeführt, damit das Bild unmerklich verändert wird.

Fügen Sie nach Ihren beiden Konstanten eine helper-Funktion hinzu, um ein neuronales Netzwerk und den Perturbationsparameter r zu definieren:

step_5_perturb.py
. . .
def get_model():
    net = models.resnet18(pretrained=True).eval()
    r = nn.Parameter(data=torch.zeros(1, 3, 224, 224), requires_grad=True)
    return net, r
. . .
  • model.resnet18(pretrained=True) lädt ein vortrainiertes neuronales Netzwerk namens ResNet18, wie zuvor. Ebenso wie zuvor versetzen Sie das Modell mit .eval in den Evaluierungsmodus.
  • nn.Parameter(...) definiert eine neue Perturbation r, die Größe des Eingabebilds. Das Eingabebild ist auch von der Größe (1, 3, 224, 224). Das Schlüsselwortargument requires_grad=True sorgt dafür, dass Sie diese Perturbation r in dieser Datei in späteren Zeilen aktualisieren können.

Als Nächstes beginnen Sie, Ihre main-Funktion zu ändern. Laden Sie zunächst das Modell net sowie die Eingänge x und definieren die Bezeichnung label:

step_5_perturb.py
. . .
def main():
    print(f'Target class: {get_idx_to_label()[str(TARGET_LABEL)]}')
    net, r = get_model()
    x = load_image()
    labels = Variable(torch.Tensor([TARGET_LABEL])).long()
  . . .

Als Nächstes definieren Sie sowohl das Kriterium als auch den Optimizer in Ihrer main-Funktion. Das Kriterium sagt PyTorch, was das Ziel ist – das heißt, welcher Verlust minimiert werden soll. Der Optimizer sagt PyTorch, wie Ihr Parameter r trainiert werden soll:

step_5_perturb.py
. . .
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.SGD([r], lr=0.1, momentum=0.1)
. . .

Fügen Sie direkt danach die Haupttrainingsschleife für Ihren Parameter r hinzu:

step_5_perturb.py
. . .
    for i in range(30):
        r.data.clamp_(-EPSILON, EPSILON)
        optimizer.zero_grad()

        outputs = net(x + r)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        _, pred = torch.max(outputs, 1)
        if i % 5 == 0:
            print(f'Loss: {loss.item():.2f} / Class: {get_idx_to_label()[str(int(pred))]}')
. . .

Bei jeder Iteration dieser Trainingsschleife tun Sie Folgendes:

  • r.data.clamp_(...): Stellen Sie sicher, dass der Parameter r klein ist, innerhalb von EPSILON 0.
  • optimizer.zero_grad(): Löschen Sie alle Gradiente, die Sie in der vorherigen Iteration berechnet haben.
  • model(x + r): Führen Sie Inferenz für das modifizierte Bild x + r aus.
  • Berechnen Sie den loss.
  • Berechnen Sie den Gradienten loss.backward.
  • Nehmen Sie einen Gradientenabstiegsschritt optimizer.step vor.
  • Berechnen Sie die Vorhersage pred.
  • Melden Sie abschließend den Verlust und die prognostizierten Klasse print(...).

Speichern Sie als Nächstes die letzte Perturbation r:

step_5_perturb.py
def main():
    . . .
    for i in range(30):
        . . .
    . . .
    np.save('outputs/adversarial_r.npy', r.data.numpy())

Speichern Sie direkt danach, noch in der main-Funktion, das perturbierte Bild:

step_5_perturb.py
. . .
    os.makedirs('outputs', exist_ok=True)
    adversarial = get_adversarial_example(x, r)

Führen Sie abschließend die Vorhersage sowohl für das Originalbild als auch das Adversarial-Beispiel aus:

step_5_perturb.py
    print(f'Old prediction: {predict(x)}')
    print(f'New prediction: {predict(x + r)}')

Überprüfen Sie sorgfältig Ihre Skriptübereinstimmungen step_5_perturb.py in GitHub. Speichern, beenden und führen Sie das Skript aus:

  1. python step_5_perturb.py assets/dog.jpg

Ihr Skript gibt Folgendes aus.

Output
Target class: goldfish, Carassius auratus Loss: 17.03 / Class: Pembroke, Pembroke Welsh corgi Loss: 8.19 / Class: Pembroke, Pembroke Welsh corgi Loss: 5.56 / Class: Pembroke, Pembroke Welsh corgi Loss: 3.53 / Class: Pembroke, Pembroke Welsh corgi Loss: 1.99 / Class: Pembroke, Pembroke Welsh corgi Loss: 1.00 / Class: goldfish, Carassius auratus Old prediction: Pembroke, Pembroke Welsh corgi New prediction: goldfish, Carassius auratus

Die letzten beiden Zeilen zeigen, dass Sie die Gestaltung eines Adversarial-Beispiels von Grund auf nun abgeschlossen haben. Ihr neuronales Netzwerk klassifiziert nun ein perfekt vernünftiges Corgi-Bild als Goldfisch.

Damit haben Sie gezeigt, dass neuronale Netzwerke leicht getäuscht werden können. Außerdem hat das Fehlen von Robustheit bei Adversarial-Beispielen erhebliche Folgen. Die nächste natürliche Frage ist diese: Wie können Sie Adversarial-Beispiele bekämpfen? Verschiedene Organisationen wie OpenAI haben viel Forschung betrieben. Im nächsten Abschnitt führen Sie eine Verteidigungsmaßnahme aus, um dieses Adversarial-Beispiel zu vereiteln.

Schritt 6 — Verteidigen vor Adversarial-Beispielen

In diesem Schritt werden Sie eine Verteidigung gegen Adversarial-Beispiele implementieren. Die Idee ist folgendermaßen: Sie sind nun Eigentümer der Tierklassifizierung, die in der Produktion bereitgestellt wird. Sie wissen nicht, welche Adversarial-Beispiele generiert werden können. Sie können jedoch das Bild oder das Modell ändern, um sich vor Angriffen zu schützen.

Bevor Sie sich schützen, sollten Sie selbst sehen, wie unmerklich die Bildmanipulation ist. Öffnen Sie die beiden folgenden Bilder:

  1. assets/dog.jpg
  2. outputs/adversarial.png

Hier sehen Sie beide nebeneinander. Ihr Originalbild wird ein anderes Seitenverhältnis aufweisen. Können Sie sagen, welches das Adversarial-Beispiel ist?

(links) Corgi als Goldfisch, Adversarial, (rechts) Corgi als Hund nicht Adversarial

Beachten Sie, dass das neue Bild genau wie das Original aussieht. Beim linken Bild handelt es sich um Ihr Adversarial-Bild. Laden Sie das Bild zur Sicherheit herunter und führen Sie Ihr Evaluierungsskript aus:

  1. wget -O assets/adversarial.png https://github.com/alvinwan/fooling-neural-network/blob/master/outputs/adversarial.png?raw=true
  2. python step_2_pretrained.py assets/adversarial.png

Dadurch wird die Klasse Goldfisch ausgeben, was als Beleg für das Adversarial-Bild dient:

Output
Prediction: goldfish, Carassius auratus

Sie führen eine ziemlich naive, aber effektive Schutzmaßnahme aus: Komprimieren Sie das Bild durch Schreiben in ein verlustreiches JPEG-Format. Öffnen Sie die interaktive Python-Aufforderung:

  1. python

Laden Sie dann das Adversarial-Bild als PNG und speichern Sie nun als JPG.

  1. from PIL import Image
  2. image = Image.open('assets/adversarial.png')
  3. image.save('outputs/adversarial.jpg')

Geben Sie Strg+D ein, um die interaktive Python-Eingabeaufforderung zu verlassen. Führen Sie als Nächstes Inferenz mit Ihrem Modell für das komprimierte Adversarial-Beispiel aus:

  1. python step_2_pretrained.py outputs/adversarial.jpg

Dadurch wird jetzt die Klasse Corgi ausgegeben, was die Wirksamkeit Ihrer einfachen Verteidigung beweist.

Output
Prediction: Pembroke, Pembroke Welsh corgi

Sie haben nun Ihre erste Adversarial-Verteidigung abgeschlossen. Beachten Sie, dass Sie für diese Verteidigung nicht nicht wissen müssen, wie das Adversarial-Beispiel generiert wurde. Dadurch wird die Verteidigung so effektiv. Außerdem gibt es viele andere Formen der Verteidigung, von denen viele ein Neutrainieren des neuronalen Netzwerks beinhalten. Allerdings sind diese Verfahren zum Neutrainieren ein eigenes Thema, das über den Umfang dieses Tutorials hinausgeht. Damit schließt dieser Leitfaden zum Adversarial Machine Learning ab.

Zusammenfassung

Um die Auswirkungen Ihrer Arbeit in diesem Tutorial zu verstehen, sehen Sie noch einmal die beiden Bilder nebeneinander an: das Original und das Adversarial-Beispiel.

(links) Corgi als Goldfisch, Adversarial, (rechts) Corgi als Hund, nicht Adversarial

Obwohl beide Bilder mit dem menschlichen Auge gleich aussehen, wurde das erste manipuliert, um Ihr Modell zu täuschen. Beide Bilder zeigen eindeutig einen Corgi, doch ist das Modell sehr zuversichtlich, dass das zweite Modell einen Goldfisch enthält. Das sollte Ihnen Sorge bereiten; denken Sie am Ende dieses Tutorial daran, dass Ihr Modell fragil ist. Einfach durch Anwendung einer simplen Transformation können Sie es täuschen. Dies sind reale, plausible Gefahren, denen auch hochmoderne Forschung nicht gewachsen ist. Forschung über Machine-Learning-Sicherheit ist genauso anfällig für diese Fehler; als Benutzer ist es Ihre Aufgabe, maschinelles Lernen sicher anzuwenden. Weiteres Lesematerial finden Sie unter folgenden Links:

Für mehr Informationen über maschinelles Lernen und Tutorials können Sie unsere Themenseite zum maschinellen Lernen besuchen.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Alvin Wan

author

AI PhD Student @ UC Berkeley

I’m a diglot by definition, lactose intolerant by birth but an ice-cream lover at heart. Call me wabbly, witling, whatever you will, but I go by Alvin



Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel