Come fa il mio iPhone a sapere che sono io?
Articolo in lingua originale di Eeswarez
Vi siete mai chiesti come fa Face Detection di iPhone a sapere che siete voi senza sbagliare mai, ovvero senza mai confondere qualcun altro per voi?
E’ grazie al Machine Leaarning! Beh c’è molto lavoro dietro ad iPhone per permettere di fargli capire che siete voi e non semplicemente una vostra foto.
In questo articolo parlerò di uno di quegli algoritmi e architetture di ML che è molto efficace per il riconoscimento facciale.
Le reti siamesi, ispirate ai gemelli siamesi, sono un tipo di architettura di rete neurale che classifica naturalmente la somiglianza o la dissomiglianza tra gli input. L’architettura prevede l’utilizzo di due o più reti neurali simili, il che significa che hanno la stessa configurazione con gli stessi parametri e pesi, cioè l’addestramento viene eseguito per una sotto-rete e la stessa configurazione viene utilizzata per le altre sotto-reti; queste sotto-reti vengono utilizzate per trovare la somiglianza tra gli input confrontando i loro feature vectors.
Per il riconoscimento facciale che sfrutta la rete siamese, a una delle sottoreti viene passato il volto dell’utente dell’iPhone e viene creata una rappresentazione sotto forma di vettore. La volta successiva, quando sarà necessario autenticare l’identità, l’immagine del volto in questione verrà fatta passare attraverso un’altra sottorete che è esattamente uguale alla configurazione della prima sottorete, ottenendo così una rappresentazione vettoriale.
Utilizzando le due codifiche, la rete confronta i risultati sulla distanza o della funzione di perdita di paragone, una distanza maggiore o minore consente il riconoscimento facciale.
Possiamo aggiungere un layer in più aumentando la complessità in modo da poter utilizzare una funzione di perdita tripla che identifica anche di quanto simili sono gli input.
Come abbiamo ottenuto questo risultato? Continuate a leggere!
Utilizzerà il pachetto tensorflow per la costruzione del modello, utilizzerò una rete neurale convoluzionale come modello per le sottoreti.
Pre elaborazione delle immagini:
def preprocess_image(filename): image_string = tf.io.read_file(filename) image = tf.image.decode_jpeg(image_string, channels=3) image = tf.image.convert_image_dtype(image, tf.float32) image = tf.image.resize(image, target_shape) return image def preprocess_triplets(base, comp_1, comp_2): return ( preprocess_image(base), preprocess_image(comp_1), preprocess_image(comp_2), ) base_images = sorted [str(base_images_path / f) for f in os.listdir(base_images_path)] ) comp_1_images = sorted( [str(comp_1_images_path / f) for f in os.listdir(comp_1_images_path)] ) image_count = len(base_images) base_dataset = tf.data.Dataset.from_tensor_slices(base_images) comp_1_dataset = tf.data.Dataset.from_tensor_slices(comp_1_images) # To generate the list of negative images, let's randomize the list of # available images and concatenate them together. rng = np.random.RandomState(seed=42) rng.shuffle(base_images) rng.shuffle(comp_1_images) comp_2_images = base_images + comp_1_images np.random.RandomState(seed=32).shuffle(comp_2_images) comp_2_dataset = tf.data.Dataset.from_tensor_slices(comp_2_images) comp_2_dataset = comp_2_dataset.shuffle(buffer_size=4096) dataset = tf.data.Dataset.zip((base_dataset, comp_1_dataset, comp_2_dataset)) dataset = dataset.shuffle(buffer_size=1024) dataset = dataset.map(preprocess_triplets) # Let's now split our dataset in train and validation. train = dataset.take(round(image_count * 0.8)) val = dataset.skip(round(image_count * 0.8)) train = train.batch(32, drop_remainder=False) train = train.prefetch(8) val = val.batch(32, drop_remainder=False) val = val.prefetch(8)
Setup del modello:
base_cnn = resnet.ResNet50( weights="imagenet", input_shape=target_shape + (3,), include_top=False ) flatten = layers.Flatten()(base_cnn.output) dense1 = layers.Dense(512, activation="relu")(flatten) dense1 = layers.BatchNormalization()(dense1) dense2 = layers.Dense(256, activation="relu")(dense1) dense2 = layers.BatchNormalization()(dense2) output = layers.Dense(256)(dense2) embedding = Model(base_cnn.input, output, name="Embedding") trainable = False for layer in base_cnn.layers: if layer.name == "conv5_block1_out": trainable = True layer.trainable = trainable Modello di rete Siamese: snm = Model( inputs=[base_input, comp_1_input, comp_2_input], outputs=distances )
Addestramento:
sm = SModel(snm) sm.compile(optimizer=optimizers.Adam(0.0001)) sm.fit(train, epochs=10, validation_data=val)
Pronti a partire!