Cosa è il backbone in una rete neurale? e cosa è il transfer learning?
In questo articolo affronterò un tema molto utile quando si intende addestrare una rete neurale, partendo da un’altra già pre-addestrata, ovvero, parlerò, della tecnica del transfer learning, del concetto di backbone di una rete neurale e del metodo del freezing. Inoltre in coda all’articolo lascerò un esempio di utilizzo di una rete neurale.
Iniziamo, innanzitutto, a dire che il backbone è in sostanza l’insieme di strati che vengono estratti da un’altra rete pre-addestrata e che saranno inseriti in testa alla rete neurale che progetteremo, con lo scopo di creare un modulo specializzato all’estrazione delle features ( motivo per cui a volte il backbone viene chiamato anche feature-extractor )
L’utilizzo della tecnica del Transfer Learning, ci consente di evitare di intaccare i pesi della rete di testa ( del backbone) attraverso una operazione di freezing degli stessi allo scopo di non modificare il comportamento della rete iniziale e consentirci di addestrare solamente il pezzo della rete di nostro interesse .
Questa tecnica è molto importante in quanto è alquanto evidente che partendo da una rete neurale già pre-addestrata l’operazione di training può convergere più velocemente e può consentire alla rete neurale di avere una risposta migliore rispetto ad una addestrata from scratch con un dataset più piccolo.
In definitiva la pratica del transfer learning consente di riutilizzare parte dei pesi di una rete neurale già addestrata in precedenza e consente di addestrare solo gli ultimi layer, che di solito sono solitamente quelli dedicati alla classificazione e/o alla regressione delle feature ottenute con i layer precedenti.
Questa operazione ci consente di ottenere due risultati:
- riutilizzo di una rete già addestrata e pronta per estrarre efficacemente feature dai dati di input
- limitazione dell’elaborazione ad un numero sensibilmente minore di parametri (corrispondenti agli ultimi layer)
Per capire come procedere nella progettazione ed uso di una rete neurale che implementa la tecnica del transfer learning, facciamo riferimento allo schema seguente:
Come indicato nella figura di cui sopra, quando si procede al riutilizzo di una rete pre addestrata si manterremo di quest’ultima solo gli strati iniziali, andando a ridefinire nella nuova rete solamente gli ultimi livelli che si occuperanno della classificazione.
Il metodo come già detto è abbastanza semplice, sarà sufficiente importare il backbone della rete di interesse, i pesi di testa saranno etichettati come “read-only“ (mediante operazione di freezing) così da consentire alla nostra rete di calcolare in fase di training solo i parametri corrispondenti agli ultimi layer, velocizzando, in tal modo, i tempi di addestramento e diminuendo sensibilmente la potenza di elaborazione richiesta.
In Internet è possibile trovare diversi modelli già pre-addestrati su dataset standardizzati, in ogni caso vi riporto una lista di dataset e di modelli al link si uno dei miei vecchi articoli.
Inoltre vi riporto questa tabella presa dal sito di keras che vi tornerà utile perchè elenca i modelli che potete gestire facilmente.
Model | Size | Top-1 Accuracy | Top-5 Accuracy | Parameters | Depth |
---|---|---|---|---|---|
Xception | 88 MB | 0.790 | 0.945 | 22,910,480 | 126 |
VGG16 | 528 MB | 0.713 | 0.901 | 138,357,544 | 23 |
VGG19 | 549 MB | 0.713 | 0.900 | 143,667,240 | 26 |
ResNet50 | 98 MB | 0.749 | 0.921 | 25,636,712 | – |
ResNet101 | 171 MB | 0.764 | 0.928 | 44,707,176 | – |
ResNet152 | 232 MB | 0.766 | 0.931 | 60,419,944 | – |
ResNet50V2 | 98 MB | 0.760 | 0.930 | 25,613,800 | – |
ResNet101V2 | 171 MB | 0.772 | 0.938 | 44,675,560 | – |
ResNet152V2 | 232 MB | 0.780 | 0.942 | 60,380,648 | – |
InceptionV3 | 92 MB | 0.779 | 0.937 | 23,851,784 | 159 |
InceptionResNetV2 | 215 MB | 0.803 | 0.953 | 55,873,736 | 572 |
MobileNet | 16 MB | 0.704 | 0.895 | 4,253,864 | 88 |
MobileNetV2 | 14 MB | 0.713 | 0.901 | 3,538,984 | 88 |
DenseNet121 | 33 MB | 0.750 | 0.923 | 8,062,504 | 121 |
DenseNet169 | 57 MB | 0.762 | 0.932 | 14,307,880 | 169 |
DenseNet201 | 80 MB | 0.773 | 0.936 | 20,242,984 | 201 |
NASNetMobile | 23 MB | 0.744 | 0.919 | 5,326,716 | – |
NASNetLarge | 343 MB | 0.825 | 0.960 | 88,949,818 | – |
EfficientNetB0 | 29 MB | – | – | 5,330,571 | – |
EfficientNetB1 | 31 MB | – | – | 7,856,239 | – |
EfficientNetB2 | 36 MB | – | – | 9,177,569 | – |
EfficientNetB3 | 48 MB | – | – | 12,320,535 | – |
EfficientNetB4 | 75 MB | – | – | 19,466,823 | – |
EfficientNetB5 | 118 MB | – | – | 30,562,527 | – |
EfficientNetB6 | 166 MB | – | – | 43,265,143 | – |
EfficientNetB7 | 256 MB | – | – | 66,658,687 | – |
A questo punto proviamo a scrivere un esempio funzionante. Innanzi tutto dovete provvedere a crearvi un vostro dataset, inserendo in una directory che chiamerete ad esempio <dataset> le varie cartelle contenti le immagini di cui volete fare la classificazione.
dataset
——–> oggetto1
——–> oggetto2
Per il nostro esempio utilizzeremo come backbone quello di una rete MobileNet pre-addestrata con dataset ImageNet.
Per il progetto di test vi consiglio di usare colab di google in tal caso potrete usare come disco su cui creare i vostri dataset il google google drive.
Vediamo come fare.
Prima di tutto dobbiamo importare le librerie necessarie
from keras.applications import MobileNetV2, mobilenet_v2 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 from google.colab import drive
drive.mount('/content/drive')
backbone = MobileNetV2(weights='imagenet', include_top=False, pooling="avg")
for l in backbone.layers: l.trainable = False
x = backbone.output x = Dense(1024, activation='relu')(x) x = Dense(1024, activation='relu')(x) x = Dense(512, activation='relu')(x)
classificatore = Dense(2, activation='softmax')(x)
model = Model(inputs=backbone.input, outputs=classificatore)
model.summary()
Stampando il sommario del nostro modello otterremo qualcosa del genere :
. . . Total params: 5,145,154 Trainable params: 2,887,170 Non-trainable params: 2,257,984
Come ci si aspettava, abbiamo abbassato notevolmente, in tal caso del 50% il numero di parametri addestrabili.
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 dei due oggetti:
train_dataset_dir = pathlib.Path('drive/MyDrive/DATASET/')
train_datagen = ImageDataGenerator(preprocessing_function=mobilenet_v2.preprocess_input, rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, validation_split=0.2) # set validation split
train_data = train_datagen.flow_from_directory(train_dataset_dir, target_size=(224, 224), color_mode='rgb',batch_size=32, class_mode='categorical',shuffle=True, subset='training') val_data = train_datagen.flow_from_directory(train_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.
model.fit(train_data, steps_per_epoch=math.ceil(train_data.n / train_data.batch_size), epochs=30, verbose=1, validation_data=val_data)
tutto qua.
Sono amante della tecnologia e delle tante sfumature del mondo IT, ho partecipato, sin dai primi anni di università ad importanti progetti in ambito Internet proseguendo, negli anni, allo startup, sviluppo e direzione di diverse aziende; Nei primi anni di carriera ho lavorato come consulente nel mondo dell’IT italiano, partecipando attivamente a progetti nazionali ed internazionali per realtà quali Ericsson, Telecom, Tin.it, Accenture, Tiscali, CNR. Dal 2010 mi occupo di startup mediante una delle mie società techintouch S.r.l che grazie alla collaborazione con la Digital Magics SpA, di cui sono Partner la Campania, mi occupo di supportare ed accelerare aziende del territorio .
Attualmente ricopro le cariche di :
– CTO MareGroup
– CTO Innoida
– Co-CEO in Techintouch s.r.l.
– Board member in StepFund GP SA
Manager ed imprenditore dal 2000 sono stato,
CEO e founder di Eclettica S.r.l. , Società specializzata in sviluppo software e System Integration
Partner per la Campania di Digital Magics S.p.A.
CTO e co-founder di Nexsoft S.p.A, società specializzata nella Consulenza di Servizi in ambito Informatico e sviluppo di soluzioni di System Integration, CTO della ITsys S.r.l. Società specializzata nella gestione di sistemi IT per la quale ho partecipato attivamente alla fase di startup.
Sognatore da sempre, curioso di novità ed alla ricerca di “nuovi mondi da esplorare“.
Comments