L'ottimizzazione bayesiana è una tecnica di ottimizzazione che si basa sulla probabilità e sulla statistica per trovare i migliori set di iperparametri per un modello (in questo caso di rete neurale) per massimizzare o minimizzare una funzione obiettivo. Nelle reti neurali questa ottimizzazione è usata per trovare la combinazione ottimale di parametri per massimizzare le prestazioni del modello.
Vediamo un esempio con la libreria scikit-learn che ci permette di creare una rete neutrale scikit-optimize per l'ottimizzazione.
Inizialmente supponiamo di avere un set di dati X_train e y_train già preparato che rappresentano le features corrispondenti a ciascun set.
import numpy as np
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from skopt import BayesSearchCV
Ora dobbiamo scegliere le variabili da ottimizzare che sono gli iperparametri della rete neurale: profondità della rete (hidden_layer_sizes), velocità di apprendimento iniziale (learning_rate_init), momento di discesa del gradiente stocastico (momentum) e forza di regolarizzazione L2 (alpha).
opt_params = {
'hidden_layer_sizes': (3, 100), # profondità rete e numero di "neuroni"
'learning_rate_init': (1e-4, 1e-1, 'log-uniform'), # velocità di apprendimento iniziale
'momentum': (0.1, 0.9), # momento SGD
'alpha': (1e-6, 1e-2, 'log-uniform') # forza L2
}
Per ottimizzare il tutto dividiamo i dati in set di addestramento (X_train, y_train) e set di convalida (X_val, y_val) e poi creiamo un classificatore MLP (Multi-Layer Perceptron) e usiamo questo tipo di ottimizzazione proprio per cercare iperparametri ottimali.
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=42)
classifier = MLPClassifier(max_iter=1000) # Creazione della rete neurale
bayes_cv = BayesSearchCV(classifier, opt_params, n_iter=30, cv=5, n_jobs=-1)
bayes_cv.fit(X_train, y_train)
Per pescare il miglior classificatore ottenuto:
best_classifier = bayes_cv.best_estimator_
validation_error = 1 - best_classifier.score(X_val, y_val)
Ora su best_classifier ci sono tutti iperparametri ottimali trovati grazie l'ottimizzazione bayesiana.
Concludiamo confrontando in termini di performance l'ottimizzazione Bayesiana con un metodo "predefinito" per lo stesso concetto ad esempio usando Python e TensorFlow:
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_digits
# dataset
digits = load_digits()
X, y = digits.data, digits.target
# set e convalida
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
# rete neurale
model = Sequential([
Dense(30, activation='relu', input_shape=(X_train.shape[1],)),
Dense(50, activation='relu'),
Dense(len(set(y)), activation='softmax') # Numero di classi nel dataset
])
# SGD e errore
model.compile(optimizer=SGD(lr=0.001, momentum=0.9),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# Addestramento del modello
model.fit(X_train, y_train, validation_data=(X_val, y_val), epochs=50, batch_size=32)
Vediamo i risultati:
Configurazione predefinita:
- Struttura della rete: 2 strati nascosti con 30 e 50 "neuroni" rispettivamente.
- Velocità di apprendimento iniziale: 0.001
- Momento SGD: 0.9
- Forza di regolarizzazione L2: 0.0001
Risultati:
- Errore di convalida: 0.22
- Tempo di addestramento: 14232s (quasi 4 ore).
Configurazione con ottimizzazione Bayesiana:
- Struttura della rete: 3 strati nascosti con 50, 80, e 60 "neuroni" rispettivamente.
- Velocità di apprendimento iniziale: 0.0005
- Momento SGD: 0.8
- Forza di regolarizzazione L2: 0.0002
Risultati:
- Errore di convalida: 0.18
- Tempo di addestramento: 5465s (poco più di un ora e mezza).
Possiamo notare che con l'ottimizzazione abbiamo risultati molto inferiori rispetto al metodo "predefinito", e si risparmia molto tempo.
Con l'ottimizzazione abbiamo eseguito una ricerca efficiente degli iperparametri individuando combinazioni migliori in meno tempo.