Keras è una libreria Python per il deep learning che racchiude le efficienti librerie numeriche TensorFlow e Theano.
Keras ti consente di progettare e addestrare in modo rapido e semplice reti neurali e modelli di deep learning.
In questo post scoprirai come utilizzare in modo efficace la libreria Keras nel tuo progetto di machine learning lavorando passo dopo passo attraverso un progetto di classificazione binaria.
Dopo aver completato questo tutorial, saprai:
Come caricare i dati di allenamento e renderli disponibili a Keras
Come progettare e addestrare una rete neurale per dati tabulari
Come valutare le prestazioni di un modello di rete neurale in Keras su dati invisibili
Come eseguire la preparazione dei dati per migliorare le capacità quando si utilizzano le reti neurali
Come ottimizzare la topologia e la configurazione delle reti neurali in Keras
Cosa è la classificazione binaria ?
La classificazione binaria è un metodo per l'apprendimento automatico che essenzialmente prende un insieme di dati e li classifica in base a due categorie. Ad esempio, se si dispone di un set di dati costituito da valori che sono 0 o 1, potrebbe trattarsi di una classificazione binaria. Questo metodo di apprendimento automatico viene solitamente utilizzato nel deep learning. Allora, cos'è la classificazione binaria? Si tratta di un processo che accetta un insieme di dati di input e gli assegna una categoria. Le etichette sono 0 o 1, che sono le due categorie. Le uscite sono le stesse.
Applicazioni della classificazione binaria
La classificazione binaria è un metodo di riconoscimento dei pattern utilizzato nel deep learning. È una tecnica di apprendimento statistico che viene utilizzata per determinare se un dato input ha un'appartenenza a una classe specifica. Il metodo è un'operazione fondamentale nell'apprendimento automatico. L'algoritmo di classificazione binaria viene utilizzato in un'ampia varietà di applicazioni di apprendimento automatico in cui le classi sono note. Ad esempio
Rilevamento dello spam e-mail (spam o meno).
Previsione di abbandono (abbandono o meno).
Previsione di conversione (acquista o meno).
Classificazione binaria con python 1.
Descrizione del Dataset
Il set di dati che utilizzerai in questo tutorial è il set di dati Sonar .
Questo è un set di dati che descrive i ritorni dei segnali acustici del sonar che rimbalzano su diversi servizi. Le 60 variabili di input sono la forza dei rendimenti a diverse angolazioni. È un problema di classificazione binaria che richiede un modello per differenziare le rocce dai cilindri metallici.
Puoi saperne di più su questo set di dati nel repository UCI Machine Learning . Puoi scaricare il set di dati gratuitamente e inserirlo nella tua directory di lavoro con il nome del file sonar.csv .
È un set di dati ben compreso. Tutte le variabili sono continue e generalmente nell'intervallo da 0 a 1. La variabile di output è una stringa "M" per la mia e "R" per rock, che dovrà essere convertita in numeri interi 1 e 0.
Un vantaggio dell'utilizzo di questo set di dati è che si tratta di un problema di benchmark standard. Ciò significa che abbiamo un'idea delle capacità attese di un buon modello. Utilizzando la convalida incrociata, una rete neurale dovrebbe essere in grado di ottenere prestazioni di circa l'84% con un limite superiore di precisione per i modelli personalizzati di circa l'88%.
Classificazione binaria con python 2.
Prestazioni del modello di rete neurale di base
Creiamo un modello di base e un risultato per questo problema.
Inizierai importando tutte le classi e le funzioni di cui avrai bisogno.
import pandas as pd
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from scikeras.wrappers import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
...
Ora puoi caricare il set di dati usando i panda e dividere le colonne in 60 variabili di input (X) e una variabile di output (Y). Usa i panda per caricare i dati perché gestisce facilmente le stringhe (la variabile di output), mentre tentare di caricare i dati direttamente usando NumPy sarebbe più difficile.
# Carichiamo i dati
dataframe = pd.read_csv("sonar.csv", header=None)
dataset = dataframe.values
# dividiamoli in input (X) e output (Y)
X = dataset[:,0:60].astype(float)
Y = dataset[:,60]
La variabile di output è valori stringa. Devi convertirli in valori interi 0 e 1.
Puoi farlo usando la classe LabelEncoder di scikit-learn. Questa classe modellerà la codifica richiesta utilizzando l'intero set di dati tramite la funzione fit(), quindi applicherà la codifica per creare una nuova variabile di output utilizzando la funzione transform().
# Trasformiamo le variabili categoriche
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)
Ora sei pronto per creare il tuo modello di rete neurale usando Keras.
Utilizzerai scikit-learn per valutare il modello utilizzando la convalida incrociata k-fold stratificata. Questa è una tecnica di ricampionamento che fornirà una stima delle prestazioni del modello. Lo fa suddividendo i dati in k-parti e addestrando il modello su tutte le parti tranne una, che viene presentata come un set di test per valutare le prestazioni del modello. Questo processo viene ripetuto k volte e il punteggio medio di tutti i modelli costruiti viene utilizzato come stima affidabile delle prestazioni. È stratificato, il che significa che esaminerà i valori di output e tenterà di bilanciare il numero di istanze che appartengono a ciascuna classe nei k-split dei dati.
Per utilizzare i modelli Keras con scikit-learn, devi utilizzare il wrapper KerasClassifier dal modulo SciKeras. Questa classe accetta una funzione che crea e restituisce il nostro modello di rete neurale. Richiede anche argomenti che passerà alla chiamata a fit(), come il numero di epoche e la dimensione del batch.
Iniziamo definendo la funzione che crea il tuo modello di base. Il tuo modello avrà un unico livello nascosto completamente connesso con lo stesso numero di neuroni delle variabili di input. Questo è un buon punto di partenza predefinito durante la creazione di reti neurali.
I pesi vengono inizializzati utilizzando un piccolo numero casuale gaussiano. Viene utilizzata la funzione di attivazione del raddrizzatore. Il livello di output contiene un singolo neurone per fare previsioni. Utilizza la funzione di attivazione sigmoidea per produrre un output di probabilità nell'intervallo da 0 a 1 che può essere convertito facilmente e automaticamente in valori di classe nitidi.
Infine, durante l'allenamento utilizzerai la funzione di perdita logaritmica (binary_crossentropy), la funzione di perdita preferita per i problemi di classificazione binaria. Il modello utilizza anche l'efficiente algoritmo di ottimizzazione Adam per la discesa del gradiente e le metriche di precisione verranno raccolte quando il modello viene addestrato.
# modello base
def create_baseline():
# creiamo il modello
model = Sequential()
model.add(Dense(60, input_shape=(60,), activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# Compiliamo il modello
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
Ora è il momento di valutare questo modello utilizzando la convalida incrociata stratificata nel framework scikit-learn.
Passa il numero di epoche di addestramento al KerasClassifier, usando ancora valori predefiniti ragionevoli. Anche l'output dettagliato è disattivato, dato che il modello verrà creato dieci volte per la convalida incrociata 10 volte eseguita.
# valutiamolo
estimator = KerasClassifier(model=create_baseline, epochs=100, batch_size=5, verbose=0)
kfold = StratifiedKFold(n_splits=10, shuffle=True)
results = cross_val_score(estimator, X, encoded_Y, cv=kfold)
print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
Dopo aver collegato questo insieme, l'esempio completo è elencato di seguito.
from pandas import read_csv
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from scikeras.wrappers import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
dataframe = read_csv("sonar.csv", header=None)
dataset = dataframe.values
X = dataset[:,0:60].astype(float)
Y = dataset[:,60]
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)
def create_baseline():
model = Sequential()
model.add(Dense(60, input_shape=(60,), activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
estimator = KerasClassifier(model=create_baseline, epochs=100, batch_size=5, verbose=0)
kfold = StratifiedKFold(n_splits=10, shuffle=True)
results = cross_val_score(estimator, X, encoded_Y, cv=kfold)
print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
Nota : i risultati possono variare a causa della natura stocastica dell'algoritmo o della procedura di valutazione, o delle differenze nella precisione numerica. Considera di eseguire l'esempio alcune volte e confrontare il risultato medio.
L'esecuzione di questo codice produce l'output seguente che mostra la media e la deviazione standard dell'accuratezza stimata del modello su dati invisibili.
Baseline: 81.68% (7.26%)
Questo è un punteggio eccellente senza fare alcun duro lavoro.ù
Classificazione binaria con python 3.
Eseguire nuovamente il modello di base con la preparazione dei dati
È buona norma preparare i dati prima della modellazione.
I modelli di rete neurale sono particolarmente adatti per avere valori di input coerenti, sia in scala che in distribuzione.
La standardizzazione è un efficace schema di preparazione dei dati per i dati tabulari durante la creazione di modelli di reti neurali. È qui che i dati vengono ridimensionati in modo tale che il valore medio per ciascun attributo sia 0 e la deviazione standard sia 1. Ciò preserva le distribuzioni gaussiane e di tipo gaussiano mentre normalizza le tendenze centrali per ciascun attributo.
Puoi usare scikit-learn per eseguire la standardizzazione del tuo set di dati sonar usando la classe StandardScaler .
Anziché eseguire la standardizzazione sull'intero set di dati, è buona norma addestrare la procedura di standardizzazione sui dati di addestramento durante il passaggio di un'esecuzione di convalida incrociata e utilizzare la standardizzazione addestrata per preparare la piega di prova "non vista". Ciò rende la standardizzazione un passaggio nella preparazione del modello nel processo di convalida incrociata. Impedisce all'algoritmo di avere conoscenza dei dati "invisibili" durante la valutazione, conoscenza che potrebbe essere trasmessa dallo schema di preparazione dei dati come una distribuzione più nitida.
Puoi ottenerlo in scikit-learn usando un Pipeline . La pipeline è un wrapper che esegue uno o più modelli all'interno di un passaggio della procedura di convalida incrociata. Qui puoi definire una pipeline con StandardScaler seguito dal tuo modello di rete neurale.
# valutiamo il modello su un dataset standardizzato
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasClassifier(model=create_baseline, epochs=100, batch_size=5, verbose=0)))
pipeline = Pipeline(estimators)
kfold = StratifiedKFold(n_splits=10, shuffle=True)
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold)
print("Standardized: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
Dopo aver collegato questo insieme, l'esempio completo è elencato di seguito.
# Binary Classification con Standardized
from pandas import read_csv
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from scikeras.wrappers import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# dataset
dataframe = read_csv("sonar.csv", header=None)
dataset = dataframe.values
# input (X) e output (Y)
X = dataset[:,0:60].astype(float)
Y = dataset[:,60]
# encode
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)
# baseline model
def create_baseline():
# creazione modello
model = Sequential()
model.add(Dense(60, input_shape=(60,), activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# compilazione model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
# valutazione modello con standardized dataset
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasClassifier(model=create_baseline, epochs=100, batch_size=5, verbose=0)))
pipeline = Pipeline(estimators)
kfold = StratifiedKFold(n_splits=10, shuffle=True)
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold)
print("Standardized: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
L'esecuzione di questo esempio fornisce i risultati seguenti.
Nota : i risultati possono variare a causa della natura stocastica dell'algoritmo o della procedura di valutazione, o delle differenze nella precisione numerica. Considera di eseguire l'esempio alcune volte e confrontare il risultato medio.
Ora vedi un piccolo ma molto bello aumento della precisione media.
Standardized: 84.56% (5.74%)
Classificazione binaria con python 4.
Ottimizzazione dei livelli e del numero di neuroni nel modello
Ci sono molte cose da mettere a punto su una rete neurale, come l'inizializzazione del peso, le funzioni di attivazione, la procedura di ottimizzazione e così via.
Un aspetto che potrebbe avere un effetto fuori misura è la struttura della rete stessa, chiamata topologia di rete. In questa sezione, esaminerai due esperimenti sulla struttura della rete: rimpicciolirla e ingrandirla.
Questi sono buoni esperimenti da eseguire quando si sintonizza una rete neurale sul proprio problema.
4.1. Valuta una rete più piccola
Si noti che è probabile che vi sia molta ridondanza nelle variabili di input per questo problema.
I dati descrivono lo stesso segnale da diverse angolazioni. Forse alcuni di questi angoli sono più rilevanti di altri. Quindi puoi forzare un tipo di estrazione di funzionalità dalla rete limitando lo spazio di rappresentazione nel primo livello nascosto.
In questo esperimento, prenderai il tuo modello di base con 60 neuroni nello strato nascosto e lo ridurrai della metà a 30. Ciò farà pressione sulla rete durante l'allenamento per selezionare la struttura più importante nei dati di input da modellare.
Standardizzerai anche i dati come nell'esperimento precedente con la preparazione dei dati e cercherai di sfruttare il leggero aumento delle prestazioni.
# modello più piccolo
def create_smaller():
# creazione modello
model = Sequential()
model.add(Dense(30, input_shape=(60,), activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# compilazione modello
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasClassifier(model=create_smaller, epochs=100, batch_size=5, verbose=0)))
pipeline = Pipeline(estimators)
kfold = StratifiedKFold(n_splits=10, shuffle=True)
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold)
print("Smaller: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
Dopo aver collegato questo insieme, l'esempio completo è elencato di seguito.
# Binary Classification con Standardized Smaller
from pandas import read_csv
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from scikeras.wrappers import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# dataset
dataframe = read_csv("sonar.csv", header=None)
dataset = dataframe.values
#input (X) e output (Y)
X = dataset[:,0:60].astype(float)
Y = dataset[:,60]
# encode
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)
# modello più piccolo
def create_smaller():
# creiamo modello
model = Sequential()
model.add(Dense(30, input_shape=(60,), activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# compiliamo modello
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasClassifier(model=create_smaller, epochs=100, batch_size=5, verbose=0)))
pipeline = Pipeline(estimators)
kfold = StratifiedKFold(n_splits=10, shuffle=True)
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold)
print("Smaller: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
L'esecuzione di questo esempio fornisce il seguente risultato. Puoi vedere che hai un leggero aumento dell'accuratezza media stimata e un'importante riduzione della deviazione standard (spread medio) dei punteggi di accuratezza per il modello.
Nota : i risultati possono variare a causa della natura stocastica dell'algoritmo o della procedura di valutazione, o delle differenze nella precisione numerica. Considera di eseguire l'esempio alcune volte e confrontare il risultato medio.
Questo è un ottimo risultato perché stai andando leggermente meglio con una rete grande la metà, che, a sua volta, richiede metà del tempo per allenarti.
Smaller: 86.04% (4.00%)
4.2. Valuta una rete più ampia
Una topologia di rete neurale con più livelli offre maggiori opportunità alla rete di estrarre funzionalità chiave e ricombinarle in utili modi non lineari.
Puoi facilmente valutare se l'aggiunta di più livelli alla rete migliora le prestazioni apportando un'altra piccola modifica alla funzione utilizzata per creare il nostro modello. Qui aggiungi un nuovo livello (una linea) alla rete che introduce un altro livello nascosto con 30 neuroni dopo il primo livello nascosto.
La tua rete ora ha la topologia:
60 inputs -> [60 -> 30] -> 1 output
L'idea qui è che alla rete viene data l'opportunità di modellare tutte le variabili di input prima di essere bloccata e costretta a dimezzare la capacità di rappresentazione, proprio come hai fatto nell'esperimento sopra con la rete più piccola.
Invece di comprimere la rappresentazione degli input stessi, hai un livello nascosto aggiuntivo per aiutare nel processo.
# modello più grande
def create_larger():
# creiamo il modello
model = Sequential()
model.add(Dense(60, input_shape=(60,), activation='relu'))
model.add(Dense(30, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# compiliamo il model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasClassifier(model=create_larger, epochs=100, batch_size=5, verbose=0)))
pipeline = Pipeline(estimators)
kfold = StratifiedKFold(n_splits=10, shuffle=True)
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold)
print("Larger: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
Dopo aver collegato questo insieme, l'esempio completo è elencato di seguito.
# Binary Classification con Standardized Larger
from pandas import read_csv
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from scikeras.wrappers import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# dataset
dataframe = read_csv("sonar.csv", header=None)
dataset = dataframe.values
# input (X) e output (Y)
X = dataset[:,0:60].astype(float)
Y = dataset[:,60]
# encode
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)
# modello più grande
def create_larger():
# crezione modello
model = Sequential()
model.add(Dense(60, input_shape=(60,), activation='relu'))
model.add(Dense(30, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# compilazione modello
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasClassifier(model=create_larger, epochs=100, batch_size=5, verbose=0)))
pipeline = Pipeline(estimators)
kfold = StratifiedKFold(n_splits=10, shuffle=True)
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold)
print("Larger: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
L'esecuzione di questo esempio produce i risultati seguenti.
Nota : i risultati possono variare a causa della natura stocastica dell'algoritmo o della procedura di valutazione, o delle differenze nella precisione numerica. Considera di eseguire l'esempio alcune volte e confrontare il risultato medio.
Puoi vedere che non ottieni un aumento delle prestazioni del modello. Questo potrebbe essere un rumore statistico o un segno che è necessaria ulteriore formazione.
Larger: 83.14% (4.52%)
Con un'ulteriore messa a punto di aspetti come l'algoritmo di ottimizzazione e il numero di epoche di addestramento, si prevede che siano possibili ulteriori miglioramenti. Qual è il miglior punteggio che puoi ottenere su questo set di dati?
Riepilogo
In questo post, hai scoperto la libreria Keras deep Learning in Python.
Hai imparato passo dopo passo come risolvere un problema di classificazione binaria con Keras, in particolare:
Come caricare e preparare i dati per l'uso in Keras
Come creare un modello di rete neurale di base
Come valutare un modello Keras utilizzando scikit-learn e la convalida incrociata k-fold stratificata
In che modo gli schemi di preparazione dei dati possono migliorare le prestazioni dei tuoi modelli
In che modo gli esperimenti che regolano la topologia di rete possono migliorare le prestazioni del modello
Comments