Tutorial

Cómo engañar a una red neural en Phyton 3

PythonPython FrameworksDevelopmentMachine Learning

El autor seleccionó a Dev Color para recibir una donación como parte del programa Write for DOnations.

¿Sería posible engañar a una red neural para la clasificación de animales? Engañar a un clasificador de animales puede tener algunas consecuencias, ¿pero si pudiésemos engañar a nuestro autenticador facial? ¿O al software del prototipo de un vehículo autónomo? Afortunadamente, legiones de ingenieros e investigaciones están entre un modelo de visión computarizada de un prototipo y los modelos de calidad de producción, en nuestros dispositivos móviles o en nuestros vehículos. Aun así, estos riesgos tienen implicaciones significativas y es importante tenerlos en cuenta como profesional del aprendizaje automático.

En este tutorial, intentará “engañar” a un clasificador de animales. A medida que avanza en este tutorial, usará OpenCV, una biblioteca de visión de computadora, y PyTorch, una biblioteca de aprendizaje profundo. Cubrirá los siguientes temas en el campo asociado de aprendizaje automático contradictorio:

  • Cree un ejemplo contradictorio objetivo. Seleccione una imagen, digamos un perro. Seleccione una clase objetivo, por ejemplo un gato. Su objetivo es engañar a la red neural para que crea que el perro de la imagen es un gato.
  • Cree una defensa contradictoria. En resumen, proteja su red neural contra estas imágenes engañosas, sin que sepa cuál es el truco.

Al final de este tutorial, tendrá una herramienta para engañar a las redes neurales y comprenderá cómo defenderse contra los trucos.

Requisitos previos

Para completar este tutorial, necesitará lo siguiente:

Paso 1: Clonar su proyecto e instalar las dependencias

Vamos a crear un espacio de trabajo para este proyecto e instalaremos las dependencias que va a necesitar. Llamará a su espacio de trabajo AdversarialML:

  • mkdir ~/AdversarialML

Diríjase al directorio AdversarialML:

  • cd ~/AdversarialML

Cree un directorio para albergar sus activos:

  • mkdir ~/AdversarialML/assets

Luego, cree un nuevo entorno virtual para el proyecto:

  • python3 -m venv adversarialml

Active su entorno:

  • source adversarialml/bin/activate

A continuación, instale PyTorch, un marco de trabajo de aprendizaje profundo para Python que utilizaremos en este tutorial.

En macOS, instale Pytorch con el siguiente comando:

  • python -m pip install torch==1.2.0 torchvision==0.4.0

En Linux y Windows, utilice los siguientes comandos para una compilación solo de CPU:

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

Ahora instale los binarios empaquetados previamente para OpenCV y numpy, que son bibliotecas para la visión computarizada y el álgebra lineal, respectivamente. OpenCV ofrece utilidades como las rotaciones de imágenes y numpy ofrece utilidades de álgebra lineal, como la inversión de una matriz:

  • python -m pip install opencv-python==3.4.3.18 numpy==1.14.5

En las distribuciones de Linux, deberá instalar libSM.so:

  • sudo apt-get install libsm6 libxext6 libxrender-dev

Con las dependencias instaladas, vamos a ejecutar y clasificador de animales llamado ResNet18, que describiremos a continuación.

Paso 2: Ejecutar un clasificador de animales preentrenado

La biblioteca torchvision, la biblioteca de visión computarizada oficial para PyTorch, contiene versiones preentrenadas de redes neurales de visión computarizada usadas comúnmente. Estas redes neurales están entrenadas sobre ImageNet 2012, un conjunto de datos de 1,2 millones de imágenes de entrenamiento con 1000 clases. Estas clases incluyen vehículos, lugares y, sobre todo, animales. En este paso, ejecutará una de estas redes neurales preentrenadas, llamada ResNet18. Nos referiremos a ResNet18 entrenado en ImageNet como un “clasificador de animales”.

¿Qué es ResNet18? ResNet18 es la red neural más pequeña en una familia de redes neurales llamada redes neurales residuales, desarrollada por MSR (He et al.). En resumen, He descubrió que una red neural (denominada como una función f, con entrada x, y salida f(x) funcionaría mejor con una “conexión residual” x + f(x). Esta conexión residual se utiliza prolíficamente en redes neurales de última generación, incluso hoy en día. Por ejemplo, FBNetV2, FBNetV3.

Descargue esta imagen de un perro con el siguiente comando:

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

Imagen de un corgi corriendo cerca de un estanque

A continuación, descargue un archivo JSON para convertir el resultado de la red neural a un nombre de clase legible por el ser humano:

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

A continuación, cree una secuencia de comandos para ejecutar su modelo preentrenado sobre la imagen del perro. Cree un nuevo archivo llamado step_2_pretrained.py:

  • nano step_2_pretrained.py

Primero, añada el texto estándar de Python importando los paquetes necesarios y declarando una función main:

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()

A continuación, cargue la asignación desde el resultado de la red neural a nombres de clase legibles por el ser humano. Añada esto directamente tras sus declaraciones de importación y antes de su función main:

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

Cree una función de transformación de imagen que garantizará que primero su imagen de entrada tenga las dimensiones correctas, y segundo que se haya normalizado correctamente. Añada la siguiente función directamente tras la última:

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
. . .

En get_image_transform, define un número de diferentes transformaciones que aplicar a las imágenes que se pasan a su red neural.

  • transforms.Resize(224): cambia el tamaño del lado más pequeño de la imagen a 224. Por ejemplo, si su imagen es 448 x 672, esta operación reduciría la imagen a 224 x 336.
  • transforms.CenterCrop(224): hace un recorte desde el centro de la imagen, de un tamaño de 224 x 224.
  • transforms.ToTensor(): convierte la imagen a un tensor PyTorch. Todos los modelos requieren tensores PyTorch como entrada.
  • transforms.Normalize(mean=..., std=...): normaliza su entrada sustrayendo la media y, luego, dividiendo la desviación estándar. Esto se describe de forma más precisa en la documentación de torchvision.

Añada una utilidad para predecir la clase animal, dada la imagen. Este método usa las utilidades anteriores para realizar la clasificación de animales:

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
. . .

Aquí la función predict clasifica la imagen proporcionada usando una red neural preentrenada:

  • models.resnet18(pretrained=True): carga una red neural preentrenada llamada ResNet18.
  • model.eval(): modifica el modelo implementado para que se ejecute en modo “evaluación”. El único otro modo es el modo “entrenamiento”, pero el modo de entrenamiento no es necesario, ya que no está entrenando el modelo (es decir, actualizando los parámetros del modelo) en este tutorial.
  • out = model(image): ejecuta la red neural sobre la imagen transformada que se proporciona.
  • _, pred = torch.max(out, 1): la red neural da como resultado una probabilidad para cada clase posible. Este paso calcula el índice de la clase con la más alta probabilidad. Por ejemplo, si out = [0.4, 0.1, 0.2], entonces pred = 0.
  • idx_to_label = get_idx_to_label(): obtiene una asignación desde el índice de clase a nombres de clase legibles por el ser humano. Por ejemplo, la asignación podría ser {0: cat, 1: dog, 2: fish}.
  • cls = idx_to_label[str(int(pred))]: convierte el índice de clase predicho a un nombre de clase. Los ejemplos proporcionados en los últimos dos puntos arrojarían cls = idx_to_label[0] = 'cat.

A continuación, tras la última función, añada una utilidad para cargar imágenes:

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
. . .

Esto cargará una imagen desde la ruta proporcionada en el primer argumento a la secuencia de comandos. transform(image)[None] aplica la secuencia de las transformaciones de la imagen definidas en las líneas anteriores.

Finalmente, complete su función main con lo siguiente para cargar su imagen y clasificar el animal de la imagen:

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

Compruebe que su archivo coincida con la secuencia de comandos final del paso 2 en step_2_pretrained.py en GitHub. Guarde y salga de su secuencia de comandos, y ejecute el clasificador de animales.

  • python step_2_pretrained.py assets/dog.jpg

Esto producirá el siguiente resultado, lo que muestra que su clasificador de animales funciona como se espera:

Output
Prediction: Pembroke, Pembroke Welsh corgi

Eso concluye ejecutar la interferencia con su modelo preentrenado. A continuación, verá un ejemplo contradictorio en acción engañando a una red neural con diferencias imperceptibles en la imagen.

Paso 3: Probar un ejemplo contradictorio

Ahora, sintetizará un ejemplo contradictorio, y probará la red neural en ese ejemplo. Para este tutorial, creará ejemplos contradictorios en formato x + r, donde x es la imagen original y r es cierta “perturbación”. Eventualmente creará la perturbación r usted mismo, pero, en este paso, descargará una que hemos creado de antemano. Comience descargando la perturbación r:

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

Ahora componga la imagen con la perturbación. Cree un nuevo archivo llamado step_3_adversarial.py:

  • nano step_3_adversarial.py

En este archivo, realizará el siguiente proceso de tres pasos para producir un ejemplo contradictorio:

  1. Transformar una imagen
  2. Aplicar la perturbación r
  3. Transformar a la inversa la imagen perturbada

Al final del paso 3, tendrá una imagen contradictoria. Primero, importe los paquetes necesarios y declare una función main:

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()

A continuación, cree una “transformación de imagen” que invierta la transformación de la imagen anterior. Ponga esto tras sus importaciones, antes de la función main:

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])
. . .

Como antes, la operación transforms.Normalize sustrae la media y divide por la desviación estándar (es decir, para la imagen original x, y = transforms.Normalize(mean=u, std=o) = (x - u) / o). Haga algo de álgebra y defina una nueva operación que invierta esta función normalizar (transforms.Normalize(mean=-u/o, std=1/o) = (y - -u/o) / 1/o = (y + u/o) o = yo + u = x).

Como parte de la transformación inversa, añada un método que transforme un tensor PyTorch de vuelta a una imagen PIL. Añada esto tras la última función:

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() convierte el tensor PyTorch en una matriz NumPy. .transpose(1, 2, 0) reordena (channels, width, height)en (height, width, channels). Esta matriz NumPy está aproximadamente en el intervalo (0, 1). Finalmente, multiplique por 255 para garantizar que la imagen está ahora en el intervalo (0, 255).
  • np.clip garantiza que todos los valores de la imagen están entre (0, 255).
  • x.asype(np.uint8) garantiza que todos los valores de la imagen sean enteros. Finalmente, Image.fromarray(...) crea un objeto de imagen PIL desde la matriz NumPy.

A continuación, use estas utilidades para crear el ejemplo contradictorio con lo siguiente:

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
. . .

Esta función genera el ejemplo contradictorio descrito al inicio de la sección:

  1. y = x + r. Tome su perturbación r y añádala a la imagen original x.
  2. get_inverse_transform: obtenga y aplique la transformación de imagen inversa que definió hace varias líneas.
  3. tensor_to_image: por último, convierta el tensor PyTorch de vuelta a un objeto de imagen.

Finalmente, modifique su función main para cargar la imagen, cargue la perturbación contradictoria r, aplique la perturbación, guarde el ejemplo contradictorio en el disco y ejecute la predicción sobre el ejemplo contradictorio:

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)}')

Su archivo completado debería coincidir con step_3_adversarial.py en GitHub. Guarde el archivo, salga del editor e inicie su secuencia de comandos con:

  • python step_3_adversarial.py assets/dog.jpg

Verá este resultado:

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

Ahora ha creado un ejemplo contradictorio: engañar a la red neural para que crea que un corgi es un pez dorado. En el siguiente paso, creará la perturbación r que utilizó aquí.

Paso 4: Comprender un ejemplo contradictorio

Para obtener una preparación sobre la clasificación, consulte “Cómo crear un filtro de perro basado en emociones”.

Dando un paso atrás, recuerde que su modelo de clasificación produce una probabilidad para cada clase. Durante la inferencia, el modelo predice la clase con la mayor probabilidad. Durante el entrenamiento, actualiza los parámetros del modelo t para maximizar la probabilidad de la clase correcta y, según sus datos x.

argmax_y P(y|x,t)

Sin embargo, para generar ejemplos contradictorios, ahora modifica su objetivo. En vez de encontrar una clase, su objetivo ahora es encontrar una nueva imagen, x. Tome cualquier clase distinta a la correcta. Vamos a llamar a esta nueva clase w. Su nuevo objetivo es maximizar la probabilidad de tener una clase equivocada.

argmax_x P(w|x)

Observe que las ponderaciones t de la red neural faltan de la expresión anterior. Esto es porque ahora asume la función de la contradicción: alguien más ha entrenado e implementado un modelo. Solo se le permite crear entradas contradictorias y no se le permite modificar el modelo implementado. Para generar el ejemplo contradictorio x, puede ejecutar “entrenamiento”, excepto que en vez de actualizar las ponderaciones de la red neural, actualiza la imagen de entrada con el nuevo objetivo.

Como recordatorio, para este tutorial, asume que el ejemplo contradictorio es una transformación afín de x. En otras palabras, su ejemplo contradictorio toma la forma x + r para algunos r. En el siguiente paso, escribirá secuencia de comandos para generar este r.

Paso 5: Crear un ejemplo contradictorio

En este paso, aprenderá una perturbación r, de forma que su corgi esté mal clasificado como un pez dorado. Cree un nuevo archivo llamado step_5_adversarial.py:

  • nano step_5_perturb.py

Importe los paquetes necesarios y declare una función main:

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()

Directamente tras sus importaciones y antes de la función main, defina dos constantes:

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

La primera constante TARGET_LABEL es la clase para clasificar erróneamente al corgi. En este caso, el índice 1 corresponde a “pez dorado”. La segunda constante EPSILON es la cantidad máxima de perturbación permitida para cada valor de imagen. Este límite se introduce de manera que la imagen se altere de forma imperceptible.

Tras sus dos constantes, añada una función helper para definir una red neural y el parámetro perturbación r:

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) carga una red neural preentrenada, llamada ResNet18, como antes. También como antes, establece el modelo para el modo de evaluación usando .eval.
  • nn.Parameter(...) define una nueva perturbación r, el tamaño de la imagen de entrada. La imagen de entrada también es de tamaño (1, 3, 224, 224). El argumento de palabra clave requires_grad=True garantiza que puede actualizar esta perturbación en líneas posteriores, en este archivo.

A continuación, comience a modificar su función main. Comience cargando la red del modelo, cargando las entradas x y definiendo la etiqueta 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()
  . . .

A continuación, defina tanto el criterio como el optimizador de su función main. El primero le indica a PyTorch cuál es el objetivo: es decir, qué pérdida minimizar. Este último le indica a PyTorch cómo entrenar su parámetro r:

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

Justo después, añada el bucle de entrenamiento principal para su parámetro r:

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))]}')
. . .

En cada iteración de este bucle de entrenamiento, usted:

  • r.data.clamp_(...): asegúrese de que el parámetro r es pequeño, dentro de EPSILON de 0.
  • optimizer.zero_grad(): borre cualquier gradiente que haya calculado en la iteración anterior.
  • model(x + r): ejecute la inferencia sobre la imagen modificada x + r.
  • Calcule la pérdida.
  • Calcule el gradiente loss.backward.
  • Tome un paso de descenso de gradiente optimizer.step.
  • Calcule la predicción pred.
  • Finalmente, informe de la pérdida y la clase predicha print(...).

A continuación, guarde la perturbación final r:

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

Justo después, aún en la función main, guarde la imagen perturbada:

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

Finalmente, ejecute la predicción tanto sobre la imagen original como sobre el ejemplo contradictorio:

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

Compruebe que su secuencia de comandos coincide con step_5_perturb.py en GitHub. Guarde, salga y ejecute la secuencia de comandos.

  • python step_5_perturb.py assets/dog.jpg

El resultado de su secuencia de comandos será la siguiente.

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

Las últimas dos líneas indican que ahora ha completado la construcción de un ejemplo contradictorio desde cero. Su red neural ahora clasifica una imagen de corgi perfectamente razonable como un pez dorado.

Ahora ha demostrado que las redes neurales pueden ser engañadas fácilmente; además, la falta de robustez para los ejemplos contradictorios tiene consecuencias significativas. Una pregunta natural es esta: ¿cómo puede combatir los ejemplos contradictorios? Varias organizaciones han llevado a cabo extensas investigaciones, incluyendo OpenAI. En la siguiente sección, ejecutará una defensa para frustrar este ejemplo contradictorio.

Paso 6: Defenderse contra ejemplos contradictorios

En este paso, implementará una defensa contra ejemplos contradictorios. La idea es la siguiente: ahora es el propietario del clasificador de animales implementado a producción. No sabe qué ejemplos contradictorios pueden generarse, pero puede modificar la imagen o el modelo para protegerse contra ataques.

Antes de defender, debería ver por sí que la manipulación de imágenes es imperceptible. Abra las dos imágenes siguientes:

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

Aquí, muestra ambas juntas. Su imagen original tendrá una relación de aspecto diferente. ¿Sabe cuál es el ejemplo contradictorio?

(izquierda) Corgi como pez dorado, contradictoria; (derecha) Corgi como sí mismo, no contradictoria

Observe que la nueva imagen parece idéntica a la original. En realidad, la imagen izquierda es su imagen contradictoria. Para estar seguro, descargue la imagen y ejecute su secuencia de comandos de evaluación:

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

Esto dará como resultado la clase goldfish para demostrar su naturaleza contradictoria:

Output
Prediction: goldfish, Carassius auratus

Ejecutará una defensa bastante ingenua, pero eficaz: comprima la imagen escribiendo a un formato JPEG. Abra la instrucción interactiva Python:

  • python

A continuación, cargue la imagen contradictoria como PNG y guárdela como JPEG.

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

Escriba CTRL + D para dejar la instrucción interactiva Python. A continuación, ejecute la inferencia con su modelo en el ejemplo contradictorio comprimido:

  • python step_2_pretrained.py outputs/adversarial.jpg

Ahora dará como resultado la clase corgi, demostrando la eficacia de su defensa ingenua.

Output
Prediction: Pembroke, Pembroke Welsh corgi

Ahora ha completado su primera defensa contradictoria. Observe que esta defensa no requiere saber cómo se generó el ejemplo contradictorio. Esto es lo que hace que una defensa sea efectiva. Existen también muchas otras formas de defensa, muchas de las cuales implican volver a entrenar la red neural. Sin embargo, estos procedimientos de entrenamiento son un tema en sí mismos y están más allá del ámbito de este tutorial. Con esto, concluye su guía sobre el aprendizaje automático contradictorio.

Conclusión

Para comprender las implicaciones de su trabajo en este tutorial, vuelva a ver las dos imágenes lado a lado: la original y el ejemplo contradictorio.

(izquierda) Corgi como pez dorado, contradictoria, (derecha) Corgi como sí mismo, no contradictoria

A pesar de que ambas imágenes parecen idénticas al ojo humano, la primera ha sido manipulada para engañar a su modelo. Ambas imágenes claramente muestran un corgi, y aun así el modelo tiene total confianza de que el segundo modelo contiene un pez dorado. Esto debería preocuparle y, a medida que finaliza este tutorial, tenga en cuenta la fragilidad de su modelo. Solo aplicando una transformación simple, puede engañarlo. Estos son peligros reales y plausibles que evaden incluso con investigación de vanguardia. La investigación más allá de la seguridad del aprendizaje automático es igual de susceptible a estos defectos, como profesional, depende de usted aplicar el aprendizaje automático de forma segura. Para obtener más información, eche un vistazo a los siguientes enlaces:

Para obtener más contenido sobre el aprendizaje automático, puede visitar nuestra página Tema de aprendizaje automático.

Creative Commons License