Una delle funzionalità più discusse del nuovo iPhone X è il nuovo metodo di sblocco, il successore di TouchID: FaceID. Avendo creato un telefono senza bordi, Apple ha dovuto sviluppare un nuovo metodo per sbloccare il telefono in modo facile e veloce. Mentre alcuni concorrenti hanno continuato a utilizzare un sensore di impronte digitali, collocato in una posizione diversa, Apple ha deciso di innovare e rivoluzionare il modo in cui sblocchiamo un telefono: semplicemente guardandolo. Grazie ad un'avanzata (e straordinariamente piccola) fotocamera frontale, l'iPhone X è in grado di creare una mappa 3D del volto dell'utente. Inoltre, un'immagine del volto dell'utente viene catturata utilizzando una telecamera a infrarossi, che è più robusta alle variazioni di luce e colore dell'ambiente. Usando il deep learning, lo smartphone è in grado di "apprendere" il volto dell'utente in modo molto dettagliato, riconoscendolo così ogni volta che il telefono viene preso dal suo proprietario. Sorprendentemente, Apple ha dichiarato che questo metodo è ancora più sicuro di TouchID, con un tasso di errore eccezionale di 1 : 1.000.000.
Questo articolo è una traduzione italiana dell'originale su Towards Data Science. Potete trovare tutto il codice Python a questo link.
Sono stato molto incuriosito dalle tecniche utilizzate da Apple per realizzare FaceID, in particolare dal fatto che tutto questo viene eseguito "on-device", con poco training iniziale sul viso dell'utente, e poi funziona senza problemi ogni volta che viene preso il telefono. Mi sono focalizzato su come far funzionare questo processo utilizzando il deep learning e su come ottimizzare ogni passaggio. In questo post, mostrerò come ho implementato un algoritmo simile a FaceID usando Keras. Spiegherò le varie decisioni architetturali che ho preso e mostrerò alcuni esperimenti finali, fatti usando una Kinect, una fotocamera RGB e di profondità molto popolare, che ha un output molto simile alle fotocamere anteriori di iPhone X (ma su un dispositivo molto più grande). Mettiti comodo, prendi una tazza di caffè e iniziamo il reverse engineering della nuova rivoluzionaria feature dell'ultimo smartphone Apple.
Analizzare Face ID
Il primo passo è analizzare attentamente come funziona FaceID su iPhone X. Il loro white paper può aiutarci a capire i meccanismi di base di FaceID. Con TouchID, l'utente doveva inizialmente registrare le sue impronte premendo più volte il sensore. Dopo circa 15-20 diversi tocchi, lo smartphone ha completato la registrazione e TouchID era pronto per l'uso. Allo stesso modo, con FaceID l'utente deve registrare la sua faccia. Il processo è molto semplice: l'utente guarda il telefono come farebbe normalmente, quindi ruota lentamente la testa seguendo un cerchio, registrando così la faccia da diverse pose. E questo è tutto, il processo è completo e il telefono è pronto per essere sbloccato. Questa procedura di registrazione estremamente veloce può dirci molto sugli algoritmi di apprendimento sottostanti. Per esempio, le reti neurali che alimentano FaceID non stanno solo eseguendo classificazioni, e spiegherò perché.
Eseguire la classificazione, per una rete neurale, significa imparare a prevedere se la faccia che ha visto è quella degll'utente o meno. Quindi, dovrebbe utilizzare alcuni dati di addestramento per prevedere "vero" o "falso", in pratica, ma a differenza di molti altri casi di utilizzo del deep learning, in questo caso questo approccio non funzionerebbe. In primo luogo, la rete dovrebbe ri-allenarsi da zero utilizzando i nuovi dati ottenuti dal volto dell'utente. Ciò richiederebbe molto tempo, consumo di energia e disponibilità di dati di addestramento di facce diverse per avere esempi negativi (poco cambierebbe in caso di transfer learning e fine-tuning di una rete già allenata). Inoltre, questo metodo non sfrutta la possibilità, per Apple, di allenare molto più a lungo una rete "offline", cioè nei loro laboratori, e quindi di consegnarla già addestrata e pronta all'uso nei loro telefoni. Invece, credo che FaceID sia basato su una rete neurale convoluzionale siamese addestrata "offline" da Apple per mappare i volti in uno spazio latente a bassa dimensione modellato per massimizzare le distanze tra i volti di persone diverse, usando una constrastive loss. Quello che succede è che si ottiene un'architettura capace di fare uno one-shot learning, come hanno brevemente menzionato al loro Keynote. Lo so, ci sono alcuni termini che potrebbero non essere familiari a molti lettori: continua a leggere, e ti spiegherò passo dopo passo cosa intendo.
Da facce a numeri con le reti neurali
Una rete neurale siamese è fondamentalmente composta da due reti neurali identiche che condividono anche tutti i pesi. Questa architettura può imparare a calcolare le distanze tra un particolare tipo di dati, come le immagini. L'idea è che si passino coppie di dati attraverso le reti siamesi (o semplicemente si passino i dati in due passaggi diversi attraverso la stessa rete), la rete la mappa in uno spazio a bassa dimensione, come un vettore n-dimensionale, e poi si addestra la rete a realizzare questa mappatura in modo che i data points di classi diverse siano il più possibile lontani, mentre i punti di dati della stessa classe siano quanto più vicini possibile. A lungo termine, la rete imparerà a estrarre le caratteristiche più significative dai dati e comprimerle in un array, creando una mappatura "intelligente". Per avere una comprensione intuitiva di ciò, immagina come descriveresti le razze canine usando un piccolo vettore, in modo che cani simili abbiano vettori più vicini (matematicamente parlando). Probabilmente useresti un numero per codificare il colore della pelliccia del cane, un altro per indicare la taglia del cane, un altro per la lunghezza della pelliccia, e così via. In questo modo, i cani che sono simili tra loro avranno vettori che sono simili tra loro. Abbastanza furbo, giusto? Bene, una rete neurale siamese può imparare a fare questo per te, in modo simile a ciò che fa un autoencoder.
Con questa tecnica, è possibile utilizzare una grande quantità di facce per addestrare tale architettura per riconoscere quali volti sono più simili. Avendo il budget e la potenza di calcolo adatti (come ha Apple), si possono anche usare esempi sempre più difficili per rendere la rete robusta a cose come gemelli, attacchi adversarial (e.g. maschere) e così via. E qual è il vantaggio finale dell'utilizzo di questo approccio? Che alla fine hai un modello plug and play in grado di riconoscere utenti diversi senza ulteriore addestramento, ma semplicemente calcolando dove si trova il viso dell'utente nella mappa latente dei volti dopo aver scattato alcune foto durante la configurazione iniziale. (Immagina, come detto prima, di annotare il vettore di razze canine per un nuovo cane, e poi di conservarlo da qualche parte). Inoltre, FaceID è in grado di adattarsi ai cambiamenti del tuo aspetto: sia i cambiamenti improvvisi (ad es. occhiali, cappelli, trucco) che quelli lenti (barba, capelli). Questo viene fatto aggiungendo in sostanza i vettori del "nuovo volto" in questa mappa, calcolati in base al nuovo aspetto.
Adesso vediamo come implementare questa architettura in Python usando Keras.
Implementare FaceID in Keras
Come per tutti i progetti di machine learning, la prima cosa di cui abbiamo bisogno sono i dati. Creare il nostro set di dati richiederebbe tempo e la collaborazione di molte persone, e questo può essere piuttosto impegnativo. Così, ho cercato sul web un dataset RGB-D, e ne ho trovato uno che sembrava perfetto. È composto da una serie di immagini RGB-D di persone che guardano in direzioni diverse e che fanno diverse espressioni facciali, come accadrebbe nel caso d'uso di iPhone X.
Per vedere l'implementazione finale, puoi andare sulla mia repository GitHub, dove puoi trovare un notebook Jupyter. Inoltre, ho creato un notebook Colab che puoi provare anche tu, gratuitamente, direttamente in cloud.
Ho creato una rete convoluzionale basata sull'architettura di SqueezeNet. La rete accetta come input coppie di immagini RGB-D di facce, quindi un'immagine a 4 canali, e calcola una distanza tra i due embedding. La rete è addestrata con una contrastive loss, che riduce al minimo le distanze tra le immagini della stessa persona e massimizza la distanza tra le immagini di persone diverse.
Dopo un po' di allenamento, la rete è in grado di mappare i volti in array a 128 dimensioni, in modo tale che le immagini della stessa persona siano raggruppate insieme, mentre siano lontane dalle immagini di altre persone. Ciò significa che, per sbloccare il dispositivo, la rete deve solo calcolare la distanza tra l'immagine scattata durante lo sblocco con le immagini memorizzate durante la fase di registrazione. Se la distanza è inferiore a una certa soglia, (più piccola è, più è sicura) il dispositivo si sblocca.
Ho usato l'algoritmo t-SNE per visualizzare in due dimensioni lo spazio di embedding a 128 dimensioni. Ogni colore corrisponde a una persona diversa: come puoi vedere, la rete ha imparato a raggruppare queste immagini in modo abbastanza preciso. (le distanze tra i cluster non hanno importanza quando si utilizza l'algoritmo t-SNE).
Un grafico interessante viene calcolato anche quando si utilizza l'algoritmo di riduzione della dimensionalità PCA.
Esperimenti!
Ora possiamo provare a vedere questo modello in azione, simulando un normale ciclo FaceID: in primo luogo, la registrazione del volto dell'utente. Quindi, la fase di sblocco, sia da parte dell'utente (che dovrebbe riuscirci) che da altre persone, che non dovrebbero essere in grado di sbloccare il dispositivo. Come accennato in precedenza, la differenza è nella distanza che la rete calcola tra la faccia che sta sbloccando il telefono e le facce registrate, e che sia sotto una certa soglia o meno.
Iniziamo con la registrazione: ho preso una serie di immagini della stessa persona dal set di dati e simulato una fase di registrazione. Il dispositivo sta ora calcolando gli embedding per ognuna di quelle pose e le archivia localmente.
Vediamo ora cosa succede se lo stesso utente tenta di sbloccare il dispositivo. Diverse pose e espressioni facciali dello stesso utente ottengono una distanza bassa, di circa 0,30 in media.
Invece le immagini RGB-D di persone diverse ottengono una distanza media di 1,1.
Pertanto, l'utilizzo di una soglia di circa 0,4 dovrebbe essere sufficiente per impedire agli estranei di sbloccare il dispositivo.
Conclusione
In questo post ho mostrato come implementare un proof-of-concept della tecnica di sblocco FaceID, basata su face embeddings e reti convoluzionali siamesi. Spero che tu l'abbia trovato utile, per qualsiasi domanda puoi metterti in contatto con me. Puoi trovare qui tutto il codice Python relativo.
Qualcosa su di me
Norman Di Palo è uno studente di AI e Robotica alla Sapienza Università di Roma. Ha partecipato al primo batch della Pi School of Artificial Intelligence, dove ora è AI & Robotics Advisor. Lavora nel campo del deep learning da circa un anno, con progetti che vanno dalle self-driving car alla robotica. È co-founder di una startup nel campo AI incubata a LUISS Enlabs. Potete contattarlo via mail (normandipalo@me.com) o su LinkedIn.
Se questo articolo ti è piaciuto e vuoi tenerti aggiornato sulle nostre attività, ricordati che l'iscrizione all'Italian Association for Machine Learning è gratuita! Puoi seguirci anche su Facebook e su LinkedIn.