¿Por Qué Preocuparse Por Las Redes Neuronales Recurrentes Para Obtener Datos Estructurados?


He estado desarrollando redes neuronales feedforward (FNns) y redes neuronales recurrentes (RNNs) en Keras con datos estructurados de la forma [instances, time, features], y el rendimiento de FNns y RNNs ha sido el mismo (excepto que las RNNs requieren más tiempo de cálculo).

También he simulado datos (código a continuación) donde esperaba que un RNN superara a un FNN porque el siguiente valor de la serie depende del valor anterior de la serie; sin embargo, ambas arquitecturas predicen correctamente.

Con datos de PNL, he visto RNNs superar FNns, pero no con datos estructurados. En general, ¿cuándo se espera que un RNN supere a un FNN con datos estructurados? Específicamente, ¿podría alguien publicar código de simulación con datos estructurados que demuestren un RNN que supere a un FNN?

¡Gracias! Si mi código de simulación no es ideal para mi pregunta, por favor adáptalo o comparte uno más ideal! Si un RNN es (generalmente) mejor que un FNN para datos de series de tiempo estructuradas, no debería ser demasiado difícil demostrarlo?

from keras import models
from keras import layers

from keras.layers import Dense, LSTM

import numpy as np
import matplotlib.pyplot as plt

Se simularon dos entidades en 10 pasos de tiempo, donde el valor de la segunda entidad depende del valor de ambas entidades en el paso de tiempo anterior.

## Simulate data.

np.random.seed(20180825)

X = np.random.randint(50, 70, size = (11000, 1)) / 100

X = np.concatenate((X, X), axis = 1)

for i in range(10):

    X_next = np.random.randint(50, 70, size = (11000, 1)) / 100

    X = np.concatenate((X, X_next, (0.50 * X[:, -1].reshape(len(X), 1)) 
        + (0.50 * X[:, -2].reshape(len(X), 1))), axis = 1)

print(X.shape)

## Training and validation data.

split = 10000

Y_train = X[:split, -1:].reshape(split, 1)
Y_valid = X[split:, -1:].reshape(len(X) - split, 1)
X_train = X[:split, :-2]
X_valid = X[split:, :-2]

print(X_train.shape)
print(Y_train.shape)
print(X_valid.shape)
print(Y_valid.shape)

FNN:

## FNN model.

# Define model.

network_fnn = models.Sequential()
network_fnn.add(layers.Dense(64, activation = 'relu', input_shape = (X_train.shape[1],)))
network_fnn.add(Dense(1, activation = None))

# Compile model.

network_fnn.compile(optimizer = 'adam', loss = 'mean_squared_error')

# Fit model.

history_fnn = network_fnn.fit(X_train, Y_train, epochs = 10, batch_size = 32, verbose = False,
    validation_data = (X_valid, Y_valid))

plt.scatter(Y_train, network_fnn.predict(X_train), alpha = 0.1)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.show()

plt.scatter(Y_valid, network_fnn.predict(X_valid), alpha = 0.1)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.show()

LSTM:

## LSTM model.

X_lstm_train = X_train.reshape(X_train.shape[0], X_train.shape[1] // 2, 2)
X_lstm_valid = X_valid.reshape(X_valid.shape[0], X_valid.shape[1] // 2, 2)

# Define model.

network_lstm = models.Sequential()
network_lstm.add(layers.LSTM(64, activation = 'relu', input_shape = (X_lstm_train.shape[1], 2)))
network_lstm.add(layers.Dense(1, activation = None))

# Compile model.

network_lstm.compile(optimizer = 'adam', loss = 'mean_squared_error')

# Fit model.

history_lstm = network_lstm.fit(X_lstm_train, Y_train, epochs = 10, batch_size = 32, verbose = False,
    validation_data = (X_lstm_valid, Y_valid))

plt.scatter(Y_train, network_lstm.predict(X_lstm_train), alpha = 0.1)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.show()

plt.scatter(Y_valid, network_lstm.predict(X_lstm_valid), alpha = 0.1)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.show()
Author: from keras import michael, 2018-08-25

1 answers

En la práctica, incluso en la PNL, se ve que las RNN y las CNN a menudo son competitivas. Aquí está un artículo de revisión de 2017 que muestra esto con más detalle. En teoría podría ser el caso de que RNNs puede manejar la complejidad completa y la naturaleza secuencial del lenguaje mejor, pero en la práctica el obstáculo más grande suele ser la formación adecuada de la red y RNNs son quisquillosos.

Otro problema que podría tener una oportunidad de funcionar sería mirar un problema como el problema de paréntesis balanceados (ya sea con solo paréntesis en las cadenas o paréntesis junto con otros caracteres distractores). Esto requiere procesar las entradas secuencialmente y rastrear algún estado y podría ser más fácil de aprender con un LSTM que con un FFN.

Actualizar: Algunos datos que parecen secuenciales podrían no tener que ser tratados secuencialmente. Por ejemplo, incluso si proporciona una secuencia de números para agregar, ya que la suma es conmutativa, un FFN funcionará tan bien como un RNN. Esto también podría ser cierto para muchos problemas donde la información dominante no es de naturaleza secuencial. Supongamos que cada año se miden los hábitos de fumar de un paciente. Desde un punto de vista conductual, la trayectoria es importante, pero si está prediciendo si el paciente desarrollará cáncer de pulmón, la predicción estará dominada solo por el número de años que el paciente fumó (tal vez restringido a los últimos 10 años para el FFN).

Así que desea hacer el problema del juguete más complejo y requerir tener en cuenta el ordenación de los datos. Tal vez algún tipo de serie temporal simulada, donde quieres predecir si hubo un pico en los datos, pero no te importan los valores absolutos solo la naturaleza relativa del pico.

Update2

Modifiqué su código para mostrar un caso donde las RNNs funcionan mejor. El truco era usar una lógica condicional más compleja que se modela de forma más natural en LSTMs que en FFNs. El código está abajo. Para 8 columnas vemos que los trenes FFN en 1 minuto y alcanza una pérdida de validación de 6.3. El LSTM tarda 3 veces más en entrenar, pero su pérdida de validación final es 6 veces menor en 1.06.

A medida que aumentamos el número de columnas, el LSTM tiene una ventaja cada vez mayor, especialmente si agregamos condiciones más complicadas. Para 16 columnas, la pérdida de validación FFNs es 19 (y puede ver más claramente la curva de entrenamiento ya que el modelo no puede ajustar instantáneamente los datos). En comparación, el LSTM tarda 11 veces más en entrenar, pero tiene una pérdida de validación de 0,31, 30 veces más pequeño que el FFN! Puede jugar con matrices aún más grandes para ver hasta dónde se extenderá esta tendencia.

from keras import models
from keras import layers

from keras.layers import Dense, LSTM

import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import time

matplotlib.use('Agg')

np.random.seed(20180908)

rows = 20500
cols = 10

# Randomly generate Z
Z = 100*np.random.uniform(0.05, 1.0, size = (rows, cols))

larger = np.max(Z[:, :cols/2], axis=1).reshape((rows, 1))
larger2 = np.max(Z[:, cols/2:], axis=1).reshape((rows, 1))
smaller = np.min((larger, larger2), axis=0)
# Z is now the max of the first half of the array.
Z = np.append(Z, larger, axis=1)
# Z is now the min of the max of each half of the array.
# Z = np.append(Z, smaller, axis=1)

# Combine and shuffle.

#Z = np.concatenate((Z_sum, Z_avg), axis = 0)

np.random.shuffle(Z)

## Training and validation data.

split = 10000

X_train = Z[:split, :-1]
X_valid = Z[split:, :-1]
Y_train = Z[:split, -1:].reshape(split, 1)
Y_valid = Z[split:, -1:].reshape(rows - split, 1)

print(X_train.shape)
print(Y_train.shape)
print(X_valid.shape)
print(Y_valid.shape)

print("Now setting up the FNN")

## FNN model.

tick = time.time()

# Define model.

network_fnn = models.Sequential()
network_fnn.add(layers.Dense(32, activation = 'relu', input_shape = (X_train.shape[1],)))
network_fnn.add(Dense(1, activation = None))

# Compile model.

network_fnn.compile(optimizer = 'adam', loss = 'mean_squared_error')

# Fit model.

history_fnn = network_fnn.fit(X_train, Y_train, epochs = 500, batch_size = 128, verbose = False,
    validation_data = (X_valid, Y_valid))

tock = time.time()

print()
print(str('%.2f' % ((tock - tick) / 60)) + ' minutes.')

print("Now evaluating the FNN")

loss_fnn = history_fnn.history['loss']
val_loss_fnn = history_fnn.history['val_loss']
epochs_fnn = range(1, len(loss_fnn) + 1)
print("train loss: ", loss_fnn[-1])
print("validation loss: ", val_loss_fnn[-1])

plt.plot(epochs_fnn, loss_fnn, 'black', label = 'Training Loss')
plt.plot(epochs_fnn, val_loss_fnn, 'red', label = 'Validation Loss')
plt.title('FNN: Training and Validation Loss')
plt.legend()
plt.show()

plt.scatter(Y_train, network_fnn.predict(X_train), alpha = 0.1)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.title('training points')
plt.show()

plt.scatter(Y_valid, network_fnn.predict(X_valid), alpha = 0.1)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.title('valid points')
plt.show()

print("LSTM")

## LSTM model.

X_lstm_train = X_train.reshape(X_train.shape[0], X_train.shape[1], 1)
X_lstm_valid = X_valid.reshape(X_valid.shape[0], X_valid.shape[1], 1)

tick = time.time()

# Define model.

network_lstm = models.Sequential()
network_lstm.add(layers.LSTM(32, activation = 'relu', input_shape = (X_lstm_train.shape[1], 1)))
network_lstm.add(layers.Dense(1, activation = None))

# Compile model.

network_lstm.compile(optimizer = 'adam', loss = 'mean_squared_error')

# Fit model.

history_lstm = network_lstm.fit(X_lstm_train, Y_train, epochs = 500, batch_size = 128, verbose = False,
    validation_data = (X_lstm_valid, Y_valid))

tock = time.time()

print()
print(str('%.2f' % ((tock - tick) / 60)) + ' minutes.')

print("now eval")

loss_lstm = history_lstm.history['loss']
val_loss_lstm = history_lstm.history['val_loss']
epochs_lstm = range(1, len(loss_lstm) + 1)
print("train loss: ", loss_lstm[-1])
print("validation loss: ", val_loss_lstm[-1])

plt.plot(epochs_lstm, loss_lstm, 'black', label = 'Training Loss')
plt.plot(epochs_lstm, val_loss_lstm, 'red', label = 'Validation Loss')
plt.title('LSTM: Training and Validation Loss')
plt.legend()
plt.show()

plt.scatter(Y_train, network_lstm.predict(X_lstm_train), alpha = 0.1)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.title('training')
plt.show()

plt.scatter(Y_valid, network_lstm.predict(X_lstm_valid), alpha = 0.1)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.title("validation")
plt.show()
 7
Author: emschorsch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-17 01:35:55