regolarizzazione L1

La regolarizzazione L1 e la selezione delle caratteristiche

In questo nuovo articolo parliamo della selezione delle caratteristiche corrette e come applicare la regolarizzazione L1 su un dataset di dati. Prima di approfondire l’argomento bisogna puntualizzare che nel caso un modello si comporti meglio su un dataset di addestramento che su uno di test significa che molto probabilmente esso si trova in una situazione di overfitting

Tutto ciò, ovviamente, genera il fallimento nella generalizzazione con l’utilizzo dei dati reali essendo, il modello, colpito da una grande varianza. Esistono delle modalità e delle strategia per ridurre l’errore di generalizzazione:

  • raccogliere più dati di addestramento; 
  • introdurre penalità per la complessità tramite regolarizzazione;
  • scegliere modello con minor numero di parametri;
  • ridurre dimensionalità dei dati;

Soluzioni sparse con la regolarizzazione L1

regolarizzazione L1
regolarizzazione L1

A differenza della regolarizzazione L2 che abbiamo studiato negli articoli precedenti, in quella L1 utilizziamo la somma del valore assoluto dei pesi. In questo modo vengono forniti vettori di caratteristiche sparsi. La maggior parte dei pesi delle caratteristiche sarà uguale a 0. La scarsità dei vettori ci risulta utile se abbiamo un dataset a elevata dimensionalità contenente molte caratteristiche irrilevanti, ancor più quando abbiamo più dimensioni rilevanti che campioni. Per questo motivo, la regolarizzazione L1 può essere considerata come una tecnica per la selezione delle caratteristiche. 

Facciamo un passo indietro ...

Dando un’occhiata all’interpretazione geometrica della regolarizzazione, tracciamo i contorni di una funzione di costo convessa per due coefficienti di peso w1 e w2. Consideriamo la somma degli errori al quadrato (SSE) e la funzione di costo di Adaline. 

Il nostro obbiettivo è quello di trovare la combinazione dei coefficienti di peso che minimizza la funzione di costo per i dati di addestramento. Ora possiamo considerare la regolarizzazione sommando una penalità alla funzione costo in modo da incoraggiare l’impiego di pesi più leggeri, penalizzando i pesi maggiori

Leggi articolo   Max di una lista

Incrementando la forza della regolarizzazione tramite il parametro  λ, riduciamo i pesi verso lo zero e la dipendenza del nostro modello dai dati di addestramento. Per la regolarizzazione L2 studiata nei precedenti articoli possiamo illustrare il concetto graficamente in questo modo:

regolarizzazione L1

Il termine di regolarizzazione quadratica L2 viene rappresentato da un cerchio grigio. In questo caso, i coefficienti di peso non possono superare il nostro budget di regolarizzazione (fuoriuscire dalla zona grigia). Però vogliamo anche minimizzare la funzione di costo e quindi il nostro tentativo migliore di minimizzazione risiede nel punto in cui la regolarizzazione L2 interseca i contorni della funzione di costo non penalizzata. Maggiore è λ e più velocemente cresce la funzione penalizzata dei costi, il che porta ad avere un cerchio L2 più ridotto. 

Lo scopo dell’esempio è quello di minimizzare la somma della funzione di costo non penalizzata del termine di penalità, il che significa sommare il bias e preferire un modello più semplice per ridurre la varianza in assenza di dati di addestramento sufficienti per adattare il modello. 

Il concetto di sparsità nella regolarizzazione L1

Poichè la penalità L1 è la somma del valore assoluto dei coefficienti di peso, possiamo rappresentarla come un budget a rombo:

regolarizzazione L1

Il contorno della funzione di costo tocca il rombo L1 nel punto w1=0. Viene incoraggiata la sparsità perchè i contorni di un sistema regolarizzato L1 sono netti e perciò l’intersezione tra le elissi e confini del rombo L1 si situano sugli assi.

Implementando la regolarizzazione L1 su scikit-learn apprendiamo:

				
					from sklearn.linear_model import LogisticRegression

lr = LogisticRegression(C=0.1, penalty='l1', solver='liblinear')
lr.fit(X_train_std, y_train)
print('Training accuracy:', lr.score(X_train_std, y_train))
print('Test accuracy:', lr.score(X_test_std, y_test))
				
			
				
					>>
Training accuracy: 0.9838709677419355
Test accuracy: 0.9814814814814815
				
			

Sia i dati di test che di addestramento hanno un’alta precisione (98%) e ciò non rileva alcun problema di overfitting

Leggi articolo   I multipli di multiplo

Accedendo ai termini di intercettazione tramite attributo lr.intercept_, l’array ci restituisce tre valori:

				
					lr.intercept_
				
			
				
					>> array([-0.38386646, -0.15807693, -0.70037615])
				
			

Attraverso l’approccio One-vs-Rest (OvR) adattiamo l’oggetto LogisticRegression su un dataset multiclasse. Il risultato fornito ci mostra la prima intercettazione che appartiene al modello adattato alla classe 1 rispetto alla 2 e alla 3. Il secondo valore è l’intercettazione del modello adattato alla classe 2 rispetto a 1 e 3 e l’ultimo valore è l’intercettazione del modello adattato alla classe 3 rispetto alla 1 e alla 2. 

				
					lr.coef_
				
			
				
					array([[ 0.28044829,  0.        ,  0.        , -0.02793319,  0.        ,
         0.        ,  0.71012148,  0.        ,  0.        ,  0.        ,
         0.        ,  0.        ,  1.23604745],
       [-0.64412126, -0.06873072, -0.05723859,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        , -0.9267515 ,
         0.06029599,  0.        , -0.37098418],
       [ 0.        ,  0.06140396,  0.        ,  0.        ,  0.        ,
         0.        , -0.63686744,  0.        ,  0.        ,  0.49845179,
        -0.35819872, -0.57025319,  0.        ]])
				
			

Quest’ultimo non è altro che un array di pesi. Ogni riga è costituita da 13 pesi dove ciascuno è moltiplicato per la rispettiva caratteristica nel dataset Wine a 13 dimensioni. Per calcolare l’input della rete:

regolarizzazione L1

I vettori peso sono sparsi, ovvero hanno solo alcuni elementi diversi da 0. In questo modo abbiamo appena addestrato un modello resistente nei confronti delle caratteristiche irrilevanti. Tracciamo infine il percorso di regolarizzazione costituito dai coefficienti di peso delle varie caratteristiche per le varie intensità di regolarizzazione:

				
					import matplotlib.pyplot as plt

fig = plt.figure()
ax = plt.subplot(111)
    
colors = ['blue', 'green', 'red', 'cyan', 
          'magenta', 'yellow', 'black', 
          'pink', 'lightgreen', 'lightblue', 
          'gray', 'indigo', 'orange']

weights, params = [], []
for c in np.arange(-4., 6.):
    lr = LogisticRegression(penalty='l1', C=10.**c, random_state=0, solver='liblinear')
    lr.fit(X_train_std, y_train)
    weights.append(lr.coef_[1])
    params.append(10.**c)

weights = np.array(weights)

for column, color in zip(range(weights.shape[1]), colors):
    plt.plot(params, weights[:, column],
             label=df_wine.columns[column + 1],
             color=color)
plt.axhline(0, color='black', linestyle='--', linewidth=3)
plt.xlim([10**(-5), 10**5])
plt.ylabel('weight coefficient')
plt.xlabel('C')
plt.xscale('log')
plt.legend(loc='upper left')
ax.legend(loc='upper center', 
          bbox_to_anchor=(1.38, 1.03),
          ncol=1, fancybox=True)
plt.show()
				
			
regolarizzazione L1

Come vediamo, tutti i pesi partono da 0 se utilizziamo C < 0,1 dove C è il parametro di regolarizzazione, ovvero l’inverso di λ. 

Condividi il post

Condividi su facebook
Condividi su google
Condividi su twitter
Condividi su email
Condividi su whatsapp