Red neuronal sinusoidal aproximación

Después de pasar días sin utilizar la neural network para el aprendizaje de Q, decidí volver a lo básico y hacer una aproximación de función simple para ver si todo funcionaba correctamente y ver cómo algunos parámetros afectaban el proceso de aprendizaje. Aquí está el código que se me ocurrió

from keras.models import Sequential from keras.layers import Dense import matplotlib.pyplot as plt import random import numpy from sklearn.preprocessing import MinMaxScaler regressor = Sequential() regressor.add(Dense(units=20, activation='sigmoid', kernel_initializer='uniform', input_dim=1)) regressor.add(Dense(units=20, activation='sigmoid', kernel_initializer='uniform')) regressor.add(Dense(units=20, activation='sigmoid', kernel_initializer='uniform')) regressor.add(Dense(units=1)) regressor.compile(loss='mean_squared_error', optimizer='sgd') #regressor = ExtraTreesRegressor() N = 5000 X = numpy.empty((N,)) Y = numpy.empty((N,)) for i in range(N): X[i] = random.uniform(-10, 10) X = numpy.sort(X).reshape(-1, 1) for i in range(N): Y[i] = numpy.sin(X[i]) Y = Y.reshape(-1, 1) X_scaler = MinMaxScaler() Y_scaler = MinMaxScaler() X = X_scaler.fit_transform(X) Y = Y_scaler.fit_transform(Y) regressor.fit(X, Y, epochs=2, verbose=1, batch_size=32) #regressor.fit(X, Y.reshape(5000,)) x = numpy.mgrid[-10:10:100*1j] x = x.reshape(-1, 1) y = numpy.mgrid[-10:10:100*1j] y = y.reshape(-1, 1) x = X_scaler.fit_transform(x) for i in range(len(x)): y[i] = regressor.predict(numpy.array([x[i]])) plt.figure() plt.plot(X_scaler.inverse_transform(x), Y_scaler.inverse_transform(y)) plt.plot(X_scaler.inverse_transform(X), Y_scaler.inverse_transform(Y)) 

El problema es que todas mis predicciones tienen un valor de alrededor de 0. Como puede ver, utilicé un ExtraTreesRegressor de sklearn (líneas comentadas) para verificar que el protocolo sea realmente correcto. Entonces, ¿qué está mal con mi neural network? ¿Por qué no funciona?

(El problema real que estoy tratando de resolver es calcular la función Q para el problema del auto de montaña usando una neural network. ¿En qué se diferencia de este aproximador de función?)

Con estos cambios:

  • Activaciones a relu
  • Eliminar kernel_initializer (es decir, dejar el valor predeterminado 'glorot_uniform' )
  • Optimizador de adam
  • 100 épocas

es decir

 regressor = Sequential() regressor.add(Dense(units=20, activation='relu', input_dim=1)) regressor.add(Dense(units=20, activation='relu')) regressor.add(Dense(units=20, activation='relu')) regressor.add(Dense(units=1)) regressor.compile(loss='mean_squared_error', optimizer='adam') regressor.fit(X, Y, epochs=100, verbose=1, batch_size=32) 

y el rest de su código sin cambios, aquí está el resultado:

introduzca la descripción de la imagen aquí

Tinker, una y otra vez …

Una versión más concisa de su código que funciona:

 def data_gen(): while True: x = (np.random.random([1024])-0.5) * 10 y = np.sin(x) yield (x,y) regressor = Sequential() regressor.add(Dense(units=20, activation='tanh', input_dim=1)) regressor.add(Dense(units=20, activation='tanh')) regressor.add(Dense(units=20, activation='tanh')) regressor.add(Dense(units=1, activation='linear')) regressor.compile(loss='mse', optimizer='adam') regressor.fit_generator(data_gen(), epochs=3, steps_per_epoch=128) x = (np.random.random([1024])-0.5)*10 x = np.sort(x) y = np.sin(x) plt.plot(x, y) plt.plot(x, regressor.predict(x)) plt.show() 

Cambios realizados: reemplazo de activaciones de capa baja con tangentes hiperbólicas, reemplazo del conjunto de datos estático con un generador aleatorio, reemplazo de sgd con adam. Dicho esto, todavía hay problemas con otras partes de tu código que aún no he podido localizar (probablemente tu escalador y proceso aleatorio).

Logré obtener una buena aproximación cambiando la architecture y la capacitación como se indica en el siguiente código. Es un poco excesivo, pero al menos sé de dónde viene el problema.

 from keras.models import Sequential from keras.layers import Dense import matplotlib.pyplot as plt import random import numpy from sklearn.preprocessing import MinMaxScaler from sklearn.ensemble import ExtraTreesRegressor from keras import optimizers regressor = Sequential() regressor.add(Dense(units=500, activation='sigmoid', kernel_initializer='uniform', input_dim=1)) regressor.add(Dense(units=500, activation='sigmoid', kernel_initializer='uniform')) regressor.add(Dense(units=1, activation='sigmoid')) regressor.compile(loss='mean_squared_error', optimizer='adam') #regressor = ExtraTreesRegressor() N = 5000 X = numpy.empty((N,)) Y = numpy.empty((N,)) for i in range(N): X[i] = random.uniform(-10, 10) X = numpy.sort(X).reshape(-1, 1) for i in range(N): Y[i] = numpy.sin(X[i]) Y = Y.reshape(-1, 1) X_scaler = MinMaxScaler() Y_scaler = MinMaxScaler() X = X_scaler.fit_transform(X) Y = Y_scaler.fit_transform(Y) regressor.fit(X, Y, epochs=50, verbose=1, batch_size=2) #regressor.fit(X, Y.reshape(5000,)) x = numpy.mgrid[-10:10:100*1j] x = x.reshape(-1, 1) y = numpy.mgrid[-10:10:100*1j] y = y.reshape(-1, 1) x = X_scaler.fit_transform(x) for i in range(len(x)): y[i] = regressor.predict(numpy.array([x[i]])) plt.figure() plt.plot(X_scaler.inverse_transform(x), Y_scaler.inverse_transform(y)) plt.plot(X_scaler.inverse_transform(X), Y_scaler.inverse_transform(Y)) 

Sin embargo, todavía estoy desconcertado por haber encontrado artículos que dicen que solo usaban dos capas ocultas de cinco neuronas para aproximarse a la función Q del problema del auto de montaña y que estaban entrenando su red durante unos minutos y obteniendo buenos resultados. Intentaré cambiar el tamaño de mi lote en mi problema original para ver qué resultados puedo obtener, pero no soy muy optimista