Keras: semplice rete neurale con dati semplici che non funzionano
Cerco di creare una rete neurale molto semplice: uno strato nascosto, con 2 neuroni. Per alcuni dati molto semplici: solo una caratteristica.
import numpy as np
X=np.concatenate([np.linspace(0,10,100),np.linspace(11,20,100),np.linspace(21,30,100)])
y=np.concatenate([np.repeat(0,100),np.repeat(1,100),np.repeat(0,100)])

Ecco il modello
from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense(2, activation='sigmoid'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='sgd', metrics=['accuracy'])
model.fit(X, y, epochs=200)
In teoria, questo modello dovrebbe funzionare. Ma anche dopo 1000 epoche, la precisione è ancora 0,667.
Epoch 999/1000
10/10 [==============================] - 0s 1ms/step - loss: 0.5567 - accuracy: 0.6667
Epoch 1000/1000
10/10 [==============================] - 0s 2ms/step - loss: 0.5566 - accuracy: 0.6667
Penso di aver fatto qualcosa di sbagliato. Potresti suggerire qualche modifica?
Sembra che ci siano molti minimi locali e l' inizializzazione può cambiare il modello finale. È il caso durante il test con il pacchetto nnet
in R. Ho dovuto testare molti semi, ho trovato questo modello (tra gli altri).

E questa è la struttura che volevo creare con keras: uno strato nascosto con 2 neuroni. La funzione di attivazione è sigmoidea.
Quindi mi chiedo se keras abbia lo stesso problema con l'inizializzazione. Con questo pacchetto nnet
in R, ho pensato che non fosse un pacchetto "perfetto". E ho pensato che Keras sarebbe stato più performante. Se l'inizializzazione è importante, keras verifica un'inizializzazione diversa? Se non perché? Forse perché in generale, con più dati (e più funzionalità), funziona meglio (senza testare molte inizializzazioni)?
Ad esempio, con kmeans, sembra che vengano testate diverse inizializzazioni.
Risposte
Questa domanda mostra l'importanza della normalizzazione dei dati di input per le reti neurali. Senza normalizzazione, l'addestramento delle reti neurali a volte è difficile perché l'ottimizzazione potrebbe bloccarsi ad alcuni minimi locali.
Voglio iniziare con la visualizzazione del set di dati. Il set di dati è 1D e dopo che è stato normalizzato con la normalizzazione standard appare come il seguente.
X_original = np.concatenate([np.linspace(0, 10, 100), np.linspace(
11, 20, 100), np.linspace(21, 30, 100)])
X = (X_original - X_original.mean())/X_original.std()
y = np.concatenate(
[np.repeat(0, 100), np.repeat(1, 100), np.repeat(0, 100)])
plt.figure()
plt.scatter(X, np.zeros(X.shape[0]), c=y)
plt.show()

Ciò implica che le reti a livello singolo come la regressione logistica non possono classificare questo set di dati. Ma una rete neurale con due strati seguiti da un'attivazione non lineare dovrebbe essere in grado di classificare il set di dati.
Ora con la normalizzazione e il seguente script di addestramento il modello può facilmente imparare a classificare i punti.
model = Sequential()
model.add(Dense(2, activation='sigmoid'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer=keras.optimizers.Adam(1e-1), metrics=['accuracy'])
model.fit(X, y, epochs=20)
Train on 300 samples
Epoch 1/20
300/300 [==============================] - 1s 2ms/sample - loss: 0.6455 - accuracy: 0.6467
Epoch 2/20
300/300 [==============================] - 0s 79us/sample - loss: 0.6493 - accuracy: 0.6667
Epoch 3/20
300/300 [==============================] - 0s 85us/sample - loss: 0.6397 - accuracy: 0.6667
Epoch 4/20
300/300 [==============================] - 0s 100us/sample - loss: 0.6362 - accuracy: 0.6667
Epoch 5/20
300/300 [==============================] - 0s 115us/sample - loss: 0.6342 - accuracy: 0.6667
Epoch 6/20
300/300 [==============================] - 0s 96us/sample - loss: 0.6317 - accuracy: 0.6667
Epoch 7/20
300/300 [==============================] - 0s 93us/sample - loss: 0.6110 - accuracy: 0.6667
Epoch 8/20
300/300 [==============================] - 0s 110us/sample - loss: 0.5746 - accuracy: 0.6667
Epoch 9/20
300/300 [==============================] - 0s 142us/sample - loss: 0.5103 - accuracy: 0.6900
Epoch 10/20
300/300 [==============================] - 0s 124us/sample - loss: 0.4207 - accuracy: 0.9367
Epoch 11/20
300/300 [==============================] - 0s 124us/sample - loss: 0.3283 - accuracy: 0.9833
Epoch 12/20
300/300 [==============================] - 0s 124us/sample - loss: 0.2553 - accuracy: 0.9800
Epoch 13/20
300/300 [==============================] - 0s 138us/sample - loss: 0.2030 - accuracy: 1.0000
Epoch 14/20
300/300 [==============================] - 0s 124us/sample - loss: 0.1624 - accuracy: 1.0000
Epoch 15/20
300/300 [==============================] - 0s 150us/sample - loss: 0.1375 - accuracy: 1.0000
Epoch 16/20
300/300 [==============================] - 0s 122us/sample - loss: 0.1161 - accuracy: 1.0000
Epoch 17/20
300/300 [==============================] - 0s 115us/sample - loss: 0.1025 - accuracy: 1.0000
Epoch 18/20
300/300 [==============================] - 0s 126us/sample - loss: 0.0893 - accuracy: 1.0000
Epoch 19/20
300/300 [==============================] - 0s 121us/sample - loss: 0.0804 - accuracy: 1.0000
Epoch 20/20
300/300 [==============================] - 0s 132us/sample - loss: 0.0720 - accuracy: 1.0000
Poiché il modello è molto semplice, la scelta del tasso di apprendimento e dell'ottimizzatore influisce sulla velocità di apprendimento. Con l'ottimizzatore SGD e il tasso di apprendimento 1e-1, l'addestramento del modello potrebbe richiedere più tempo rispetto all'ottimizzatore Adam con lo stesso tasso di apprendimento.