Molti li hanno già chiamati le illusioni ottiche delle reti neurali. In realtà, gli adversarial examples (che potremmo tradurre come "esempi antagonistici") sono un problema esistente per qualsiasi tecnica di machine learning: tramite modifiche impercettibili all'occhio umano, è possibile generare esempi in grado di confondere qualsiasi classificatore, indipendentemente dalla sua accuratezza in fase di training e con altissima probabilità. In pochissimi anni, questi attacchi sono risultati essere molto più semplici da applicare di quanto creduto inizialmente, e difendersi sembra di conseguenza tanto più complesso, con una vera e propria corsa agli armamenti tra ricercatori che inventano nuovi attacchi ed altri che provano ad evitarli. In questo post vediamo cosa sono gli adversarial example (con particolare attenzione ai classificatori di immagini), una selezione di lavori sul tema, e come generare esempi di questo tipo in poche righe di codice.
Come ingannare una rete neurale
Partiamo dall'inizio: corre l'anno 2013, e le reti neurali hanno ormai raggiunto un'accuratezza nel riconoscere oggetti prossima a quella umana, prestazioni che negli anni a seguire non faranno che aumentare e che si estenderanno a numerosi altri campi, dando vita al fenomeno del deep learning così come lo conosciamo oggi. Ma come abbiamo già discusso in passato l'accuratezza non è tutto, ed in molti cominciano a chiedersi quanto robusti siano questi modelli: quanto realmente "capiscono" (se ci passate il termine) le reti neurali di quanto vedono?
Nel tentativo di rispondere (anche) a questa domanda, in un articolo caricato su arXiv a fine 2013 [1] alcuni ricercatori descrivono due aspetti interessanti di queste nuove reti neurali "profonde". Il primo di questi aspetti riguarda il modo in cui le reti memorizzano l'informazione, ma è il secondo ad attirare da subito l'attenzione della comunità scientifica: data un'immagine qualunque, anche classificata correttamente, è possibile aggiungerle del rumore impercettibile all'occhio umano e dare vita ad una seconda immagine in grado di confondere quasi sempre la rete neurale. L'anno dopo, questo fenomeno viene popolarizzato da Andrej Karpathy sul suo blog (Breaking Linear Classifiers on ImageNet):
Il modo in cui ottenere questi "adversarial examples" (AE nel seguito) descritto dai ricercatori è anche piuttosto semplice ed elegante. Supponiamo che $x$ sia l'immagine (classificata correttamente), ed $f(x)$ la classe predetta dalla rete neurale. Vogliamo trovare una distorsione $r$ tale per cui la predizione $f(x+r)$ diventi $l$, dove ovviamente $l \neq f(x)$. Questo è banale se scegliamo $r$ sufficientemente grande, ma è possibile invece trovare una distorsione impercettibile? Per farlo, possiamo provare trovando la distorsione più piccola tra tutte quelle possibili tramite un problema di ottimizzazione:
$$ \begin{align} \underset{r}{\text{min}} & \,\, \lVert r \rVert_2 \,,\\ \text{tale che} & \,\, \begin{cases} \,\, f(x+r) = l & \\ \,\, x+r \text{ rimanga un'immagine valida} & \end{cases} \,. \end{align}$$
Per risolvere esattamente questo problema abbiamo bisogno di tecniche di ottimizzazione leggermente più sofisticate di quelle classiche (a causa dei vincoli imposti): in particolare, i ricercatori adottano una variante di L-BFGS, un algoritmo piuttosto oneroso che limita molto le dimensioni dei problemi a cui questo attacco può essere applicato.
Per i curiosi, la sigla L-BFGS sta per "Limited-memory Broyden–Fletcher–Goldfarb–Shanno", dove gli ultimi quattro nomi sono gli autori dell'algoritmo originale BFGS. La versione usata nell'articolo, "Box-constrained L-BFGS", permette di gestire anche vincoli sul range delle variabili. Trovate una spiegazione piuttosto approfondita su Wikipedia.
Nonostante la relativa complessità del metodo, la tecnica riesce su problemi di medie dimensioni, generando distorsioni effettivamente impercettibili e dando vita al primo adversarial attack nella storia del deep learning, che in seguito prenderà il nome dalla tecnica di ottimizzazione usata: L-BFGS. La conclusione è chiara: le reti neurali sembrano a prima vista molto meno robuste di quanto si poteva pensare (si inizia ad usare il termine "brittle"). Questo risultato va di pari passo con un risultato complementare ottenuto pochi mesi dopo da OpenAI, che mostra come immagini totalmente irriconoscibili siano invece classificate con grande confidenza dalla rete neurale:
Ad attirare ulteriormente l'attenzione della communità scientifica concorrono altri due fenomeni:
- La popolarità del deep learning è dovuta soprattutto a librerie software molto semplici da usare, come TensorFlow, PyTorch, o (nell'ormai lontano 2013) Theano. Proprio questi strumenti rendono altrettanto facile generare attacchi: è sufficiente ottimizzare una rete neurale non rispetto ai suoi pesi, ma rispetto all'immagine di input, e le due operazioni sono concettualmente uguali a livello del software. Questo vuol dire che l'implementazione, una volta allenata la rete, è minima (si veda in particolare la prossima sezione).
- A peggiorare le cose, le distorsioni trovate - oltre ad essere indistinguibili all'occhio umano se comparate con l'immagine originaria - vengono trovate quasi sempre (come nell'immagine di cui sopra).
Una volta osservati i primi AE, le domande erano molte: quanto è generale il problema? Possiamo generare AE anche senza la conoscenza del modello della rete neurale? Ed in questo caso, possiamo difendercene? Per cominciare, il passo immediatamente successivo è stato quello di trovare metodi più semplici per generarli che non richiedessero la complessità di L-BFGS. Non troppo a sorpresa, c'è voluto pochissimo.
Da L-BFGS al fast gradient sign method
Il secondo tassello essenziale nella teoria degli AE arriva esattamente un anno dopo, in un secondo articolo [2] pubblicato da due degli autori originali insieme a Jonathon Shlens. Nel tentativo di dare una spiegazione a questo fenomeno (spiegazione su cui torniamo subito sotto), scoprono anche una tecnica incredibilmente semplice per generarli. In poche parole, al posto di risolvere in maniera ottimale il problema di ottimizzazione di prima gli autori ottengono degli AE aggiungendo all'immagine del rumore che dipende solo dal gradiente della rete neurale e da un parametro scelto dall'utente:
\[ \widetilde{x} = x + \varepsilon \cdot \text{sign}\left(\nabla_x c(f(x),y) \right) \,.\]
Nell'equazione di prima, $\varepsilon$ determina quanto rumore viene aggiunto, e $c(f(x),y)$ è la funzione costo usata (es., cross-entropia). A differenza di L-BFGS, non dobbiamo ottimizzare nulla: una volta scelto $\varepsilon$ possiamo generare centinaia di immagini con (in pratica) una sola riga di codice. Stranamente, questa tecnica permette di raggiungere errori fino al 90% sui principali dataset di image classification! Per la sua semplicità, questo attacco è stato soprannominato Fast Gradient Sign Method (FGSM). Vale la pena fare una piccola pausa per apprezzare quanto semplice è questo metodo: vediamo quindi come implementarlo in pratica, prima di continuare la nostra panoramica sugli AE.
Adversarial examples in pratica (Python)
Questa sezione describe l'implementazione di FGSM in Python. Se siete interessati solo alla teoria degli AE, saltate pure oltre fino alla prossima sezione.
Ci sono tantissime librerie per sperimentare attacchi di questo tipo, tra cui cleverhans (rilasciata dagli autori degli articoli citati prima) e foolbox. Possiamo installare la seconda direttamente con pip:
pip install foolbox
Sul tutorial è disponibile un esempio già funzionante che riprendiamo qui. Per eseguirlo possiamo caricare un modello pre-allenato da Keras:
import keras
import numpy as np
from keras.applications.resnet50 import ResNet50
keras.backend.set_learning_phase(0)
kmodel = ResNet50(weights='imagenet')
Per chi non l'avesse mai incontrata, la ResNet-50 è un modello estremamente competitivo di image recognition. Per eseguire un attacco, dobbiamo prima trasformare il modello di Keras in un modello di foolbox con un wrapper (ne esistono di appositi per tutte le principali librerie):
import foolbox
preprocessing = (np.array([104, 116, 123]), 1)
fmodel = foolbox.models.KerasModel(kmodel, bounds=(0, 255), preprocessing=preprocessing)
Carichiamo un'immagine (nemmeno a dirlo - un gattino!):
image, label = foolbox.utils.imagenet_example()
Possiamo verificare che l'immagine sia correttamente classificata dalla rete in questa fase:
np.argmax(fmodel.predictions(image[:, :, ::-1])) # Ritorna 282 (tiger cat)
La rete neurale ritorna 282 come indice di classe, che nella tassonomia di ImageNet corrisponde effettivamente ad un tiger cat. Generiamo un attacco modificando l'immagine con il FGSM:
attack = foolbox.attacks.FGSM(fmodel)
adversarial = attack(image[:, :, ::-1], label)
Riproviamo la classificazione con la nuova immagine:
np.argmax(fmodel.predictions(adversarial[:, :, ::-1])) # Ritorna 287 (lynx, catamount)
Il gatto è misteriosamente diventato una lince! (O un puma, che non è meno preoccupante per chi legge la predizione.) Questo genere di attacco richiede peraltro un tempo infinitesimo su una qualsiasi macchina di buone prestazioni. Per curiosità, possiamo anche analizzare il codice del toolbox per vedere l'implementazione dell'attacco (leggermente semplificata nella versione che riportiamo qui):
perturbed = image + gradient_sign * np.sign(a.gradient())
Il tutto si può esprimere facilmente in una sola riga, grazie all'uso di a.gradient()
, che permette di calcolare $\nabla_x c(f(x),y)$ automaticamente a partire da qualsiasi modello.
Oltre gli attacchi white-box
L-BFGS e FGSM, come dicevamo prima, sono solo la punta dell'iceberg, e di attacchi ne esistono ormai un'infinità. Ad esempio, con il saliency map attack [3] potete generare rapidamente adversarial examples in base ad una classe scelta da voi come nel caso di L-BFGS, ma in maniera molto più efficiente.
Inoltre, finora abbiamo visto solo attacchi che supponevano che il modello della rete neurale fosse disponibile, il che sembra limitare di molto la loro pericolosità effettiva. Come vediamo ora, però, questo non è strettamente necessario: è possibile avere attacchi completamente black-box, ovvero che non richiedono nessuna informazione sulla struttura interna del modello che stiamo attaccando. Esplorarli ci porta nel terreno più recente della ricerca sugli AE.
Attacchi black-box e perturbazioni universali
L-BFGS e FGSM, nella loro stranezza, sono poco più di una curiosità accademica: dover aver accesso al modello della rete neurale preclude, ad esempio, la possibilità di attaccare modelli in cloud o (ancora peggio) modelli già in produzione negli oggetti che ci circondano. Due anni esatti dopo la pubblicazione del primo articolo sugli AE, però, ecco arrivare una scoperta ben peggiore [3]: non solo è possibile attaccare qualsiasi modello di machine learning (e quindi non solo reti neurali), ma gli attacchi sono trasferibili. Se siamo in possesso di un buon numero di predizioni di un modello, possiamo allenare un altro modello ad imitazione del primo, ed usare quello per generare gli AE. Gli autori del nuovo articolo testano con successo questo nuovo attacco contro modelli in cloud di vari provider, ottenendo performance elevatissime.
A questo punto, l'unico limite alla sofisticazione degli attacchi diventa la fantasia dei ricercatori. Le "perturbazioni universali" [4], ad esempio, permettono di generare attacchi validi per quasi ogni classificatore simultaneamente:
Ancora più strane, le "perturbazioni ad un pixel" permettono di attaccare un modello modificando un singolo pixel dell'immagine :
E come se non bastasse, ecco infine le "adversarial patch", dei bottoni che permettono di ingannare quasi tutti i classificatori anche nel mondo reale:
Ovviamente il problema non si limita alle immagini. Possiamo creare AE per sistemi di NLP o anche (seppur in maniera preliminare) per i più avanzati sistemi di text-to-speech, facendogli trascrivere qualsiasi cosa desideriamo.
Ma perché questi AE funzionano così bene? E come possiamo difendercene?
Teoria e difesa dagli adversarial examples
Il motivo del perché gli AE esistono ha (ovviamente) attirato molta attenzione e non si può dire sia stato ancora risolto in maniera soddisfacente. Una delle spiegazioni più note è stata introdotta in [2] e si fonda (contro-intuitivamente) sulla linearità delle reti neurali in pratica. Per spiegare questa linea di pensiero, supponiamo che il modello $f(x)$ sia effettivamente lineare: in questo caso, il cambiamento dato dalla perturbazione si può esprimere immediatamente come:
\[ w^T\widetilde{x} = w^T x + w^T r \,.\]
Un semplice ragionamento mostra inoltre come la perturbazione ottimale con norma $\lVert r \rVert_2 = \varepsilon$ è proprio $r = \varepsilon \cdot \text{sign}(w)$ (vi ricorda qualcosa?). Se $w$ ha $n$ elementi e ciascuno di essi in media vale $m$, la perturbazione complessiva media è data da $\varepsilon m n$. Quindi, anche mantendendo $\varepsilon$ molto piccolo, su problemi sufficientemente complessi (dove $n$ è molto grande) la perturbazione complessiva può diventare enorme. La giustificazione data da [2] per gli AE è che le reti neurali esibiscono questo comportamento lineare in pratica, ed anzi è qualcosa di voluto: modificare di poco l'input varia (proporzionalmente) di poco la predizione. Da questa assunzione nasce il FGSM.
Detto questo, come difendersi dagli AE? La verità è che attualmente stiamo assistendo ad una corsa agli armamenti nel quale gli attaccanti sono in vantaggio: per ogni difesa trovata, nuovi modi di aggirarla e nuovi attacchi vengono inventati ogni mese. Vediamo una rapidssima selezione di difese possibili:
-
L'idea più semplice è di aggiungere AE in fase di training (data augmentation). Questo rende il modello parzialmente più robusto, ma richiede una conoscenza di tutti i possibili attacchi a cui il sistema sarà soggetto, può aumentare la complessità dell'allenamento, ed in alcuni casi fallisce completamente.
-
[6] introduce la tecnica di defensive distillation, una procedura a due fasi che cerca di evitare che la rete neurale si adatti in maniera troppo stringente ai propri dati allenandola due volte tramite un processo chiamato distillation. Questo metodo sembra resistente ad alcuni tipi di attacco (tra cui L-BFGS e FGSM), ma molto meno ad altri.
- Una delle difese più note al momento, introdotta in [7], allena un secondo modello sulle rappresentazioni interne della rete neurale a predire se l'esempio processato in quel momento è adversarial oppure no. Anche questa difesa potrebbe fallire (ad esempio nel caso di universal perturbations), ma sembra essere più robusta di altre.
E questa è (ovviamente) solo una lista parziale di alcuni lavori particolarmente influenti, che conclude la nostra breve panoramica sull'affascinante problema degli AE.
E quindi?
La realtà è che gli AE rappresentano un problema critico per qualsiasi modello (sia esso una rete neurale o meno) le cui predizioni sono direttamente esposte al pubblico; un problema che deve essere assolutamente tenuto in conto nella fase di progettazione e controllato in quella di deployment, nella stessa maniera in cui di qualsiasi sistema informatico viene sempre valutata la sicurezza. Non farlo (e non tenersi costantemente aggiornati sui nuovi sviluppi del campo) apre falle enormi nella progettazione di sistemi di machine learning, falle che rischiano di portare ad ingenti danni, sia monetari che sociali.
E questo apre una riflessione più generale: per quanto intelligenti sembrino questi sistemi, nel mondo reale persone che vogliano sfruttare il vostro sistema e siano dotate di sufficiente ingegno possono quasi sicuramente riuscirci. Nel campo più generale del data mining, questo problema è stato parallelamente studiato come adversarial machine learning: per chi fosse interessato, rimandiamo al bellissimo blog del PRA Lab di Cagliari, dove trovate una timeline molto dettagliata dei principali lavori nel campo.
Per concludere, come scrive questo articolo del MIT Technology Review, "gli hacker sono il vero ostacolo per le macchine che si guidano da sole" e non solo: come ci ricorda anche David Silver, cartelli stradali che cercano di ingannarvi sono dietro l'angolo!
Riferimenti
[1] Szegedy, C., Zaremba, W., Sutskever, I., Bruna, J., Erhan, D., Goodfellow, I. and Fergus, R., 2013. Intriguing properties of neural networks. arXiv preprint arXiv:1312.6199.
[2] Goodfellow, I.J., Shlens, J. and Szegedy, C., 2014. Explaining and harnessing adversarial examples. arXiv preprint arXiv:1412.6572.
[3] Papernot, N., McDaniel, P., Jha, S., Fredrikson, M., Celik, Z.B. and Swami, A., 2016. The limitations of deep learning in adversarial settings. In 2016 IEEE European Symposium on Security and Privacy (EuroS&P), (pp. 372-387). IEEE.
[3] Papernot, N., McDaniel, P., Goodfellow, I., Jha, S., Celik, Z.B. and Swami, A., 2017. Practical black-box attacks against machine learning. In Proceedings of the 2017 ACM on Asia Conference on Computer and Communications Security (pp. 506-519). ACM.
[4] Moosavi-Dezfooli, S.M., Fawzi, A., Fawzi, O. and Frossard, P., 2017. Universal adversarial perturbations. In IEEE Conference on Computer Vision and Pattern Recognition (CVPR). IEEE.
[5] Su, J., Vargas, D.V. and Kouichi, S., 2017. One pixel attack for fooling deep neural networks. arXiv preprint arXiv:1710.08864.
[6] Papernot, N., McDaniel, P., Wu, X., Jha, S. and Swami, A., 2016. Distillation as a defense to adversarial perturbations against deep neural networks. In 2016 IEEE Symposium on Security and Privacy (SP) (pp. 582-597). IEEE.
[7] Metzen, J.H., Genewein, T., Fischer, V. and Bischoff, B., 2017. On detecting adversarial perturbations. arXiv preprint arXiv:1702.04267.
Se questo articolo ti è piaciuto e vuoi tenerti aggiornato sulle nostre attività, ricordati che l'iscrizione all'Italian Association for Machine Learning è completamente gratuita e permette di ricevere la nostra newsletter mensile con una selezione di eventi, articoli e notizie di interesse. Puoi seguirci anche su Facebook o su LinkedIn.