spinner

Adversarial Machine Learning (parte VI): tutorial de Adversarial Robustness Toolbox

Sexta parte y última de la serie de Adversarial Machine Learning; en este post veremos un tutorial sobre Adversarial Robustness Toolbox, una herramienta opensource que permite implementar de forma sencilla ataques y defensas de Adversarial Machine Learning. 

Introducción

Adversarial Robustness Toolbox, abreviado como ART, es una librería opensource de Adversarial Machine Learning que permite comprobar la robustez de los modelos de machine learning. Está desarrollada en Python e implementa ataques y defensas de extracción, inversión, envenenamiento y evasión. ART soporta los frameworks más populares: Tensorflow, Keras, PyTorch,MxNet, ScikitLearn, entre muchos otros). Además, no está limitada al uso de modelos que emplean imágenes como entrada, sino que soporta otros tipos de datos como audio, vídeo, datos tabulares, etc.

Logo de Adversarial Robustness Tool.

ART es una librería desarrollada por IBM, y que recientemente ha pasado a formar parte de las herramientas de Linux Foundation AI. ART es un proyecto muy activo que cuenta con amplia documentación y ejemplos para probar de forma sencilla y rápida distintos algoritmos estado del arte en ataque y defensa. En el momento de escribir estas líneas, la última versión estable es la 1.4.1, que empezaremos a lo largo del tutorial.

La librería se organiza en distintos paquetes Python que ordenan los distintos algoritmos implementados. Entre los módulos más empleados se encuentran art.attacks y art.defences, que incluyen la mayoría de ataques y defensas, respectivamente. Estos módulos, a su vez, se subdividen en otros, que ordenan los ataques y defensas por tipo. En el caso art.attacks tiene como súbmodulos art.attacks.{extraction, model_inversion, poisoning, evasion}. De forma similar, se hace con el módulo de defensas. Esto permite localizar fácilmente los ataques y defensas disponibles para cada tipo específico.

Prerrequisitos e instalación

Para instalar ART sólo se requiere tener instalada la versión 3 de Python y pip.

La instalación se realiza a través de pip del siguiente modo.

Se recomienda el uso de GPU para acelerar los cálculos, aunque se puede realizar perfectamente con sólo CPU. En caso de no disponer de GPU propia, se puede utilizar el servicio Colab de Google, que proporciona acceso a GPUs de forma gratuita.

¡Hola, ART! 

A lo largo de todo el tutorial, nos centraremos en ataques de caja blanca que nos permitan robustecer nuestros modelos aplicando defensas, pero ART permite realizar ataques de caja negra sin ningún tipo de limitación.

Para comprobar que la instalación se ha realizado correctamente, vamos a probar un ataque de evasión. En este ejemplo, necesitaremos instalar las dependencias de Keras y Tensorflow, ya que emplearemos Keras para entrenar los modelos y Tensorflow será el backend. Todo el código se encuentra disponible en https://github.com/next-security-lab/art-tutorial.

El ataque que emplearemos será FGSM, un ataque de evasión de caja blanca sobre el conjunto de datos del MNIST. Este conjunto datos permite clasificar dígitos manuscritos del 0 al 9.. Se compone de 60 000 imágenes de 28×28 píxeles que representan dígitos manuscritos, de los que 50 000 se emplean como datos de entrenamiento y los 10 000 como datos de testing.

Algunas muestras del conjunto de datos del MNIST.

Comenzamos importando las dependencias necesarias en un fichero. Las primeras corresponden a Keras, que permiten crear el modelo al que atacar y las últimas corresponden al módulo de ART que nos permitirán generar ejemplos adversario para el modelo.

El siguiente paso es cargar el conjunto de datos y entrenar la arquitectura del modelo. En este ejemplo se usan 3 épocas de entrenamiento que son suficientes para obtener una alta precisión. 

Calculamos la precisión del modelo para ver cómo de bueno fue el entrenamiento. En nuestro caso es del 97.86%. 

Por último, realizamos el ataque FGSM al modelo que acabamos de entrenar. Fijamos el parámetro eps como 0.2 y generamos ejemplos adversarios para el conjunto de test para comprobar cómo varía la precisión con respecto al modelo original, que resulta ser del 39.93%, una bajada bastante significativa.

Veamos algún ejemplo adversario que se genera con este método. En este caso, sólo mostramos la muestra 1234 del conjunto de test, que el modelo original lo clasifica de forma correcta como 8, sin embargo, el ejemplo adversario generado es clasificado como 3.

Ejemplo adversario generado con el método FGSM.

Ataques de evasión

Continuamos con los ataques de evasión viendo algún método más de caja blanca. Aquí, generaremos ejemplos adversarios con los métodos JSMA y C&W L2.

Y de igual forma, que en ejemplo previo, generamos los ejemplos adversarios. En este caso fijamos el parámetro theta=0.1 para JSMA y dejamos los parámetros por defecto en C&W L2. Este proceso tarda bastante tiempo, aún usando GPUs. En este caso, se obtiene una precisión de 0.42% para JSMA y 84.15% para C&W L2. En nuestro caso, JSMA es un ataque muy eficiente, sin embargo C&W L2 no afecta apenas nada a este modelo. Cambiando con los parámetros de los distintos métodos se pueden obtener resultados distintos.


Veamos algunos de los ejemplos generados por cada uno de los métodos, incluido. En el caso de la muestra 1234, el modelo clasifica la entrada del método FGSM como un 3, con JSMA un 5 y con C&W L2 clasifica de forma correcta. Este resultado C&W L2 viene a confirmar los malos resultados sobre el conjunto de test.

Ejemplo de adversarios generados con los métodos FGSM, JSMA y C&W L2.

Más ataques se pueden encontrar en el módulo art.attacks.evasion.

Defensa: entrenamiento adversario

Una defensa sencilla de implementar es el entrenamiento adversario (adversa- rial training en inglés), que consiste en entrenar el modelo empleando ejemplos adversarios generados previamente con alguno de los métodos.

En este caso, generamos ejemplos adversarios sobre los datos de entrenamiento con el método FGSM, que es más rápido, pero se puede usar cualquier otro o incluso una combinación de varios métodos para hacer un modelo más robusto.

Estos nuevos datos se incorporan al conjunto de entrenamiento junto con sus respectivas salidas.

Sólo queda entrenar el modelo desde cero y comprobar cuál es su precisión y compararla con el entrenamiento sin emplear entrenamiento adversario. 

En nuestro caso, se obtiene una precisión del 96.14% utilizando entrenamiento adversario, que no está muy lejos del entrenamiento realizado sin ejemplos ad- versarios, que era de un 97.86% y por muy encima de emplear ejemplos adversa- rios durante la evaluación (39.93%). Esto demuestra que una defensa muy básica como esta puede resultar muy útil en caso de un ataque de evasión.

Otra forma de realizar entrenamiento adversario es hacer uso de la clase nativa de ART llamada AdversarialTrainer del módulo art.defences.trainer. Esta defensa no es exactamente igual al anterior ya que emplea un ensemble de modelos.

En este caso, se obtiene una precisión del 94.39% empleando esta defensa, que no es muy diferente a la obtenida anteriormente con el método anterior.

Los módulos art.defences.detector.evasion y art.defences.trainer contienen muchas más defensas.

Ataques de inversión

ART implementa ataques de inversión en el módulo art.attacks.inference. A su vez, se subdivide en ataques Membership Inference Attacks (MIA) que se encuentran en el módulo art.attacks.inference.membership_inference, Property Inference Attacks (PIA) en el módulo art.attacks.inference.attribute_inference y los ataques de reconstrucción en el módulo art.attacks.inference.model_inversion.

Por brevedad, sólo nos centraremos en el ataque de reconstrucción de Fredikson et al. [1]. ART implementa este ataque a través de la clase MIFace, y aunque el ataque se propuso para explotar sistemas de reconocimiento facial, se ha de- mostrado efectivo como se comenta en la documentación de ART y como veremos a continuación. La mayor parte del código ha sido tomado del ejemplo que proporciona ART en su repositorio de GitHub.

El primer paso, de nuevo, consiste en entrenar un modelo similar a los anteriores empleando los datos del MNIST. Este modelo difiere de los anteriores en los filtros de las capas convolucionales, la capa de Dropout y el número de épocas (de 3 a 10) del entrenamiento.

El clasificador logra una precisión del 98.49% sobre el conjunto de test. El ataque se realiza empleando la clase MIFace, empleando como clasificador el modelo que acabamos de entrenar.

Para favorecer a converger al ataque se puede emplear, de forma opcional, un vector de inicialización. En este caso, empleamos los descritos en el ejemplo de ART. Estos son inicializar la imagen con los píxeles en blanco, en gris, en negro, de forma aletaria y con la media de los valores del conjunto de test.

Sólo queda ver qué ha sido capaz de inferir este ataque para cada vector de inicialización.

La siguiente figura muestra que los mejores vectores de inicialización son el gris y la media. De hecho, en estos últimos, se puede apreciar que las muestras inferidas por el ataque son muy similares a las que proporciona el MNIST.

Filtrado de información del conjunto de entrenamiento con distintos vectores de inicialización.

A fecha de escribir de escribir este tutorial no existen defensas implementadas en ataques de inversión, pero es esperable que en el futuro no muy lejano se implementen en ART.

Ataques de envenenamiento

El módulo art.attacks.poisoning de ART implementa algunos ataques de envenenamiento, que permite introducir una puerta trasera en un modelo, construyendo una BadNet [2] y por último, cómo es posible defenderse frente a este tipo de ataques.

En este caso, necesitamos instalar versiones específicas de Tensorflow y Keras para que funcione correctamente los ejemplos.

Con todo lo anterior instalado, podemos comenzar a crear una puerta trasera sobre el conjunto de datos del MNIST. De nuevo, nos basamos en el ejemplo de envenenamiento que se encuentra en el repositorio de ART en GitHub. Crearemos una puerta trasera, que al detectar un patrón de píxeles en la esquina superior derecha,clasifique cada dígito como el  dígito siguiente, es decir, el 0 como 1, el 1 como 2, hasta el 9 como 0.

Lo primero de todo es cargar el conjunto de datos del MNIST. En esta ocasión,cargamos los datos en crudo empleando el parámetro raw = True.

De todos los datos, seleccionamos 7500 de forma aleatoria, en los que se producirá el envenenamiento. Un adversario intentaría envenenar la menor cantidad de datos posibles para evitar ser detectado.

Definimos la función que se encargará de introducir el patrón de píxeles en la esquina inferior derecha de la imagen, que se encuentra implementada ya en ART.

El patrón se puede ver en la imagen siguiente.

Patrón de píxeles introducida en distintas imágenes.

La función más importante es la que envenena el conjunto de datos seleccionado, introduciendo la puerta trasera llamada poison_dataset. En ella, se emplea la clase PoisoningAttackBackdoor, que implementa el ataque de BadNets.

Se aplica la función anterior sobre los conjuntos de entrenamiento y test para evaluar (reintroduciendo los nuevos datos envenenados de forma aleatoria). Ya sólo queda entrenar el modelo y evaluar cómo se comporta el modelo.

El modelo entrenado tiene una precisión sobre el conjunto de test sin envenenar del 96.75% y la puerta trasera funciona en el 95.01% de los casos, por lo que se ha conseguido introducir la BadNet de forma satisfactoria.

Representamos cómo se comporta la puerta trasera sobre una imagen legítima y sobre una imagen con el disparador de la puerta trasera (el patrón de píxeles en la esquina inferior izquierda). En la imagen siguiente se puede ver una instancia quees clasificada por el modelo (izquierda), pero que al introducir una muestra que contiene el disparador se clasifica como el número siguiente del que debería ser, esto es, 2 en este caso (derecha).

Ejemplo del correcto funcionamiento de la puerta trasera. A la izquierda se muestra una muestra que es clasificada correctamente por el modelo y, a la derecha, una muestra que se clasifica de acuerdo a la puerta trasera resultado de envenenar el conjunto de datos.

Defensa: Neural Cleanse

Neural Cleanse es una defensa que permite identificar puertas traseras, reconstruir disparadores e incluye distintas mitigaciones. ART implementa esta defensa en la clase Neural Cleanse del módulo art.defences.transformer.poisoning.

A fecha de escribir este tutorial, Neural Cleanse sólo soporta la versión 2.2.4 de Keras, por lo que esto explica por qué había que instalar versiones específicas de Keras y Tensorflow.

Lo primero es crear una instancia de esta clase para crear la defensa y pasar el clasificador que queremos defender.

Con Neural Cleanse, se puede detectar la puerta trasera para cada una de las clases, aunque sólo la aplicaremos en la clase 1 por brevedad.

Detección del patrón de la puerta trasera para la clase 1 con Neural Cleanse.

En la imagen superior  se puede ver cómo este método detecta la puerta trasera en la esquina inferior derecha. Habiendo visto que se detecta la puerta trasera se pueden aplicar mitigaciones como filtrado, desaprendizaje y poda.

  • Filtrado (filtering en inglés) que detecta y bloquea instancias consideradas amenazas durante la fase de inferencia.
  • Desaprendizaje (unlearning en inglés), que consiste en reentrenar las puertas traseras con las etiquetas legítimas.
  • Poda (pruning en inglés), que consiste en eliminar las neuronas asociadas a la puerta trasera.

En nuestro caso, se obtiene que el filtrado consigue filtrar un 40.89% de las muestras maliciosas, el desaprendizaje rebaja hasta el 30.03% la efectividad de envenenamiento, mientras que la poda hace que la efectividad sea del 0.00%, pero hace que la precisión del modelo sea del 46.30%.

Las mitigaciones también se pueden aplicar de forma conjunta.

Neural Cleanse es una medida defensiva que implementa ART, pero otras defensas se pueden encontrar en el módulo art.defences.transformer.poisoning.

Ataques de extracción

ART implementa ataques de extracción en el módulo art.attacks.extraction. Todos los ataques son ataques de caja negra que emplean la técnica del modelo sustituto. Esta consiste en entrenar un modelo similar al modelo objetivo haciendo peticiones a este. ART implementa ataques como Copycat CNN o Knockoff Nets, entre otros. El adversario debe definir un modelo que pueda imitar el modelo objetivo y debe crear una instancia del ataque que quiera llevar a cabo. Aquí, victim es el modelo objetivo y classifier es el modelo sustituto y nb_stolen es el número de peticiones al modelo objetivo.

Este tipo de ataques no tienen sentido en modelos de caja blanca (conocemos todos los parámetros e hiperparámetros) como los que hemos visto hasta ahora, pero pueden servir para comprobar cómo de robustos son nuestros modelos frente a estos ataques. Por ello,nos centraremos en las defensas que proporciona ART para ataques de extracción.

ART implementa defensas a través del módulo art.defences.postprocessor, que se encargan de modificar la salida del modelo. Entre ellas, se encuentran el redondeo (fijar un número de decimales para las salidas del modelo) y el ruido gaussiano (que añade ruido a la salida del modelo). Aplicar este tipo de defensas a un modelo antes de entrenar es muy sencillo. Sólo hay que crear una instancia o instancias de las defensas que queremos aplicar e indicarlo en la clase Keras-Classifier mediante el parámetro postprocessing_defences.

Futuro y conclusiones finales

Como hemos visto a lo largo de este post, ART permite realizar tanto ataques como aplicar defensas de los cuatro tipos de ataques que define el Adversarial Machine Learning ART permite comprobar la robustez de nuestros modelos de machine learning frente a este tipo de ataques y protegerlos (si fuera necesario) antes de desplegarlos en producción. ART no es la única herramienta opensource que permite hacer esto, pero sí que es la más completa con respecto al número de ataques y defensas implementados, cubriendo todos los tipos (extracción, inversión, envenenamiento y evasión) ,así como los tipos de datos (imágenes, audio, vídeos,…). Su gran documentación y número de ejemplos permiten probar y testar nuestros modelos sin requerir gran esfuerzo. Como desventaja, algunos ataques/defensas no están disponibles para todos los frameworks o versiones del mismo, aunque es de esperar que esto se solucione en futuras versiones de la librería.

Actualmente, nos encontramos en un punto en el aparecen defensas como nuevos ataques que evaden estas medidas, ya que no existe un consenso sobre cuáles son las medidas de evaluación que permitan a un modelo como seguro. Importante es mencionar que los ataques del futuro serán adaptativos en distintos escenarios y no sólo aplicable en un determinado entorno, ya que siempre existirán defensas que protejan frente a este ataque específico [3]. 

A modo de conclusión final, los despliegues de modelos de machine learning son cada vez más comunes y estos se pueden convertir en un nuevo vector de ataque por parte de adversarios, por lo que conocer tanto las posibles vulnerabilidades como sus posibles remediaciones permiten y permitirán en el futuro proteger (junto con el uso de herramientas opensource) a una organización de manera efectiva frente a esta nueva amenaza.

Referencias

[1] Fredrikson, M., Jha, S., & Ristenpart, T. (2015). Model inversion attacks that exploit confidence information and basic countermeasures. Proceedings of the ACM Conference on Computer and Communications Security, 2015Octob, 1322–1333. https://doi.org/10.1145/2810103.2813677

[2] Gu, T., Dolan-Gavitt, B., & Garg, S. (2017). BadNets: Identifying Vulnerabilities in the Machine Learning Model Supply Chain. Retrieved from http://arxiv.org/abs/1708.06733 

[3] Tramer, F., Carlini, N., Brendel, W., & Madry, A. (2020). On Adaptive Attacks to Adversarial Example Defenses. Retrieved from http://arxiv.org/abs/2002.08347 

 

Fuente Imagen destacada: Unsplash

Las opiniones vertidas por el autor son enteramente suyas y no siempre representan la opinión de BBVA Next Technologies.

¿Quieres saber que más cosas hacemos en BBVA Next Technologies?