Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/tutorials/generative/adversarial_fgsm.ipynb
25118 views
Kernel: Python 3

Licensed under the Apache License, Version 2.0 (the "License");

#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

En este tutorial se crea un ejemplo adversario con el ataque FGMS (método del signo de gradiente rápido [Fast Gradient Signed Method]) como se explica en Explicación y aprovechamiento de ejemplos adversarios de Goodfellow et al. Este fue uno de los primeros ataques y uno de los más populares que pudo engañar a una red neuronal.

¿Qué es un ejemplo adversario?

Los ejemplos adversarios son entradas especializadas creadas con el propósito de confundir a una red neuronal, lo que provoca una clasificación errónea de la entrada ingresada. Estas entradas notorias son imperceptibles al ojo humano, pero hacen que la red no pueda identificar el contenido de la imagen. Existen varios tipos de estos ataques, sin embargo, nos enfocaremos en el ataque del método del signo de gradiente rápido, que es un ataque de caja blanca que busca asegurar una clasificación errónea. Un ataque de caja blanca es cuando el atacante tiene acceso total al modelo que se está atacando. A continuación, se muestra uno de los ejemplos más famosos de una imagen adversaria tomado del artículo que se mencionó anteriormente.

Adversarial Example

Aquí, comenzamos con la imagen de un panda, el atacante agrega pequeñas perturbaciones (distorsiones) en la imagen original, lo que hace que el modelo etiquete la imagen como un gibón, con mucha confianza. El proceso de agregar estas perturbaciones se explica a continuación.

Método del signo de gradiente rápido

El método del signo de gradiente rápido funciona mediante el uso de los gradientes de la red neuronal para crear un ejemplo adversario. Para una imagen de entrada, el método usa los gradientes de la pérdida con respecto a la imagen de entrada para crear una imagen nueva que maximice la pérdida. La imagen nueva se llama imagen adversaria. Esto se puede resumir con la siguiente expresión: advx=x+ϵsign(xJ(θ,x,y))adv_x = x + \epsilon*\text{sign}(\nabla_xJ(\theta, x, y))

donde

  • adv_x : Imagen adversaria.

  • x : Imagen de entrada original.

  • y : Etiqueta de la entrada original.

  • ϵ\epsilon : Multiplicador para garantizar que las perturbaciones sean pequeñas.

  • θ\theta : Parámetros del modelo.

  • JJ : Pérdida.

Una propiedad curiosa en este caso, es el hecho de que los gradientes se toman con respecto a la imagen de entrada. Se hace así porque el objetivo es crear una imagen que maximice la pérdida. Un método para lograr esto es averiguar cuántos píxeles de la imagen contribuyen al valor de la pérdida y agregar una perturbación según corresponda. Esto se puede hacer bastante rápido porque es fácil averiguar cuánto contribuye cada píxel a la pérdida mediante el uso de la regla de la cadena y averiguar los gradientes requeridos. Por eso, los gradientes se toman con respecto a la imagen. Además, ya no se está entrenando al modelo (por eso, los gradientes no se toman de las variables entrenables, es decir, los parámetros del modelo) y los parámetros del modelo permanecen constante. El único objetivo es engañar a un modelo ya entrenado.

Ahora lo probaremos nosotros. Vamos a engañar a un modelo preentrenado. En este tutorial, el modelo es el modelo MobileNetV2, preentrenado en ImageNet.

import tensorflow as tf import matplotlib as mpl import matplotlib.pyplot as plt mpl.rcParams['figure.figsize'] = (8, 8) mpl.rcParams['axes.grid'] = False

Carguemos el modelo preentrenado MobileNetV2 y los nombres de clase de ImageNet.

pretrained_model = tf.keras.applications.MobileNetV2(include_top=True, weights='imagenet') pretrained_model.trainable = False # ImageNet labels decode_predictions = tf.keras.applications.mobilenet_v2.decode_predictions
# Helper function to preprocess the image so that it can be inputted in MobileNetV2 def preprocess(image): image = tf.cast(image, tf.float32) image = tf.image.resize(image, (224, 224)) image = tf.keras.applications.mobilenet_v2.preprocess_input(image) image = image[None, ...] return image # Helper function to extract labels from probability vector def get_imagenet_label(probs): return decode_predictions(probs, top=1)[0][0]

Imagen original

Usaremos una imagen de muestra de un Labrador Retriever de Mirko CC-BY-SA 3.0 de Wikimedia Common y crearemos ejemplos adversarios con ella. El primer paso es preprocesarlas para poder ingresarlas como entrada en el modelo MobileNetV2.

image_path = tf.keras.utils.get_file('YellowLabradorLooking_new.jpg', 'https://storage.googleapis.com/download.tensorflow.org/example_images/YellowLabradorLooking_new.jpg') image_raw = tf.io.read_file(image_path) image = tf.image.decode_image(image_raw) image = preprocess(image) image_probs = pretrained_model.predict(image)

Observemos la imagen.

plt.figure() plt.imshow(image[0] * 0.5 + 0.5) # To change [-1, 1] to [0,1] _, image_class, class_confidence = get_imagenet_label(image_probs) plt.title('{} : {:.2f}% Confidence'.format(image_class, class_confidence*100)) plt.show()

Crear la imagen adversaria

Implementación del método del signo de gradiente rápido

El primer paso es crear perturbaciones que se usarán para distorsionar la imagen original que resultará en una imagen adversaria. Como ya mencionamos, para esta tarea, los gradientes se toman con respecto a la imagen.

loss_object = tf.keras.losses.CategoricalCrossentropy() def create_adversarial_pattern(input_image, input_label): with tf.GradientTape() as tape: tape.watch(input_image) prediction = pretrained_model(input_image) loss = loss_object(input_label, prediction) # Get the gradients of the loss w.r.t to the input image. gradient = tape.gradient(loss, input_image) # Get the sign of the gradients to create the perturbation signed_grad = tf.sign(gradient) return signed_grad

También se pueden visualizar las perturbaciones resultantes.

# Get the input label of the image. labrador_retriever_index = 208 label = tf.one_hot(labrador_retriever_index, image_probs.shape[-1]) label = tf.reshape(label, (1, image_probs.shape[-1])) perturbations = create_adversarial_pattern(image, label) plt.imshow(perturbations[0] * 0.5 + 0.5); # To change [-1, 1] to [0,1]

Probémoslo para diferentes valores de la épsilon y observemos la imagen resultante. Notará que a medida que aumenta el valor de la épsilon, resulta más fácil engañar a la red. Sin embargo, esto supone una compensación que causa que las perturbaciones sean más identificables.

def display_images(image, description): _, label, confidence = get_imagenet_label(pretrained_model.predict(image)) plt.figure() plt.imshow(image[0]*0.5+0.5) plt.title('{} \n {} : {:.2f}% Confidence'.format(description, label, confidence*100)) plt.show()
epsilons = [0, 0.01, 0.1, 0.15] descriptions = [('Epsilon = {:0.3f}'.format(eps) if eps else 'Input') for eps in epsilons] for i, eps in enumerate(epsilons): adv_x = image + eps*perturbations adv_x = tf.clip_by_value(adv_x, -1, 1) display_images(adv_x, descriptions[i])

Próximos pasos

Ahora que conoce los ataques adversarios, pruebe hacerlo con diferentes conjuntos de datos y en diferentes arquitecturas. También puede crear y entrenar su propio modelo y luego intentar engañarlo con el mismo método. También puede probar ver como varía la confianza en las predicciones al cambiar la épsilon.

Aunque el ataque que se presenta en este tutorial es poderoso, fue tan solo el comienzo de una investigación de ataques adversario. Han surgido muchos artículos que crearon ataques más poderosos después de este. Además de los ataques adversarios, gracias a las investigaciones también se crearon defensas, que buscan crear modelos de aprendizaje automático más sólidos. Revise este documento donde encontrará una lista completa de ataques adversarios y defensas.

Para ver más implementaciones de ataques adversarios y defensas, puede ver la biblioteca de ejemplos adversarios CleverHans.