Come addestrare una rete neurale per classificare oggetti partendo da una rete pre addestrata. Esempio per il riconoscimento di volti con mascherina e senza mascherina.

AI, INTELLIGENZA ARTIFICIALE

In questo articolo farò vedere come usare una rete neurale convoluzionale preaddestrata per classificare e riconoscere dei volti di persone con mascherina e senza mascherina.

L’esempio è stato scritto per essere eseguito  in colab o su Jupiter notebook, qui potete trovare l’esempio su colab.

Il rimo passo e recuperare un dataset idoneo allo scopo. Nella fattispecie sarà necessario recuperare una serie di immagini di persone con mascherina ed una seria di immagini di persone senza mascherina.

Per comodità lascio il link di un dataset di prova al seguente link.

Il dataset è organizzato in due directory :

——–> con_mask

——–> senza_mask

Dato che utilizzeremo una rete preaddestrata, per il nostro esempio utilizzeremo come backbone quello di una rete  InceptionV3  pre-addestrata con dataset ImageNet. Vediamo come fare.

Prima di tutto dobbiamo importare le librerie necessarie:

from keras.applications import InceptionV3, inception_v3
from keras.layers import Dense
from keras.models import Model
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
import pathlib
import math
import tensorflow as tf
import matplotlib.pyplot as plt
importiamo il backbone della rete InceptionV3
backbone = InceptionV3(weights='imagenet', include_top=False, pooling="avg")
a questo punto  freeziamo i pesi  o meglio rendiamo  i livelli del backbone non trainable, attraverso  il ciclo for che va ad impostare a False la proprietà trainable di ogni layer del backbone. Questa operazione  rende read-only i parametri dei livelli del backbone e  non verranno modificati durante l’addestramento, in altri termini viene evitata la back propagation per questi layer.
for l in backbone.layers:
  l.trainable = False
nel caso in cui volessimo addestrare anche il top basterà non eseguire il pezzo precedente o semplicemente porre a true i livelli l.trainable.
for l in backbone.layers: 
 l.trainable = True
Facendo un pò di esperimenti, in questo caso,   in realtà ho notato che ottengo risultati migliori addestrando anche il top.
A questo punto creiamo il pezzo della rete  dense che imparerà a classificare utilizzando come input della rete di coda l’output del backbone, nel nostro caso utilizziamo un rete dense a 3 livelli hidden con 2 livelli da 1024 neuroni ed una da 512
x = backbone.output
x = Dense(1024, activation='relu')(x)
x = Dense(1024, activation='relu')(x)
x = Dense(512, activation='relu')(x)
inseriamo in coda una  softmax che restituisce la valutazione della classificazione in termini di probabilità in questo caso tra due classi
classificatore = Dense(2, activation='softmax')(x)
a questo punto creiamo il modello globale:
model = Model(inputs=backbone.input, outputs=classificatore)
e se mi va provo ad analizzarne  la struttura esaminando il sommario della composizione della rete
 model.summary()

oppure posso esaminare graficamente i blocchi:

tf.keras.utils.plot_model(model,show_layer_names=True)

A questo punto compiliamo  il modello indicando la loss function e l’ottimizzatore da utilizzare:

model.compile(loss="categorical_crossentropy", optimizer=Adam(lr=0.0001), metrics=["accuracy"])

e generiamo i dataset di traning e di validation a partire dalla nostra dir in cui abbiamo inserito le immagini categorizzate. Per fare ciò, prima tutto scarichiamo il dataset al path di cui sopra:

!wget https://www.domsoria.com/download/DATASET/MASKNOMASK/datasetMaskNoMask.zip
Decomprimo il file  e rimuovo le cartelle inutili ( create automaticamente dal MAC)
!unzip -a datasetMaskNoMask.zip  -d "dataset"
!rm -rf dataset/__MACOSX # rimuovo una cartella inutile creata con lo zip
a questo punto inizializzo il path del dataset che ho scaricato
dataset_dir = pathlib.Path('drive/MyDrive/DATASET/')
creo i dataset di train e di validation utilizzando ImageDataGenerator . In questo caso  ho indicato di fare anche un pò di augmetation attraverso l’uso di zoom e flip e di dividere  il dataset in uno di training ed uno di validation con un rapporto 80% – 20% attraverso l’uso del parametro validation_split=0.2;
datagen = ImageDataGenerator(preprocessing_function=inception_v3.preprocess_input,
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
validation_split=0.2) # set validation split
costruisco il train_data ed il validation_data da utilizzare per il fitting della rete:
train_data = datagen.flow_from_directory(dataset_dir, 
                                         target_size=(224, 224),
                                         color_mode='rgb',
                                         batch_size=32, 
                                         class_mode='categorical',
                                         shuffle=True, 
                                         subset='training')

val_data = datagen.flow_from_directory(dataset_dir, 
                                       target_size=(224, 224),
                                       color_mode='rgb',
                                       batch_size=32, 
                                       class_mode='categorical',
                                       shuffle=True, 
                                       subset='validation')

Per l’addestramento provate ad utilizzare  10 epoche e vedrete che probabilmente otterrete una accuracy molto elevata.

hist = model.fit(train_data, steps_per_epoch=math.ceil(train_data.n / train_data.batch_size), epochs=10, verbose=1, validation_data=val_data)

Al termine dell’addestramento eseguiamo la seguente riga di codice per salvare il modello :

model.save_weights('model.h5')

attenzione se usate colab il modello salvato alla fine della sessione verrà cancellato.

In tal caso vi consiglio di salvare il modello ad esempio sul vostro drive google.

from google.colab import drive
drive.mount('/content/drive')
model.save_weights('drive/MyDrive/<Path su drive google>/model.h5')

Nel prossimo articolo farò vedere come fare la predict e quindi come utilizzare il modello salvato.

Qui potete trovare il link del progetto completo su github.

 

Seconda parte in progress >>

Comments