Keras: red neuronal simple con datos simples que no funcionan

Aug 20 2020

Intento crear una red neuronal muy simple: una capa oculta, con 2 neuronas. Para algunos datos muy simples: solo una característica.

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)])

Aqui esta el modelo

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)

En teoría, este modelo debería funcionar. Pero incluso después de 1000 épocas, la precisión sigue siendo 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

Creo que hice algo mal. ¿Podría sugerir alguna modificación?

Parece que hay muchos mínimos locales y la inicialización puede cambiar el modelo final. Es el caso al probar con el paquete nneten R. Tuve que probar muchas semillas, encontré este modelo (entre otros).

Y esta es la estructura que quería crear con keras: una capa oculta con 2 neuronas. La función de activación es sigmoidea.

Entonces me pregunto si keras tiene el mismo problema con la inicialización. Con este paquete nneten R, pensé que no es un paquete "perfecto". Y pensé que keras sería más eficaz. Si la inicialización es importante, ¿Keras prueba una inicialización diferente? Si no, ¿por qué? ¿Quizás porque en general, con más datos (y más funciones), funciona mejor (sin probar muchas inicializaciones)?

Por ejemplo, con kmeans, parece que se prueban diferentes inicializaciones.

Respuestas

3 Mitiku Aug 26 2020 at 16:19

Esta pregunta muestra la importancia de la normalización de datos de entrada para las redes neuronales. Sin normalización, el entrenamiento de las redes neuronales a veces es difícil porque la optimización puede atascarse en algunos mínimos locales.

Quiero comenzar con la visualización del conjunto de datos. El conjunto de datos es 1D y, una vez normalizado con la normalización estándar, tiene el siguiente aspecto.

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()

La mejor manera de separar estos puntos de datos en las clases respectivas es trazando dos líneas en el espacio de entrada. Dado que el espacio de entrada es 1D, los límites de clasificación son solo puntos 1D.

Esto implica que las redes de una sola capa, como la regresión logística, no pueden clasificar este conjunto de datos. Pero una red neuronal con dos capas seguidas de activación no lineal debería poder clasificar el conjunto de datos.

Ahora, con la normalización y el siguiente script de entrenamiento, el modelo puede aprender fácilmente a clasificar los puntos.

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

Dado que el modelo es muy simple, la elección de la tasa de aprendizaje y el optimizador afecta la velocidad del aprendizaje. Con el optimizador SGD y la tasa de aprendizaje 1e-1, el modelo puede tardar más en entrenarse que el optimizador Adam con la misma tasa de aprendizaje.