Ответ 1
На практике даже в НЛП вы видите, что RNN и CNN часто конкурируют. Вот обзорный обзор 2017 года, который показывает это более подробно. Теоретически это может быть так, что RNN могут справиться с полной сложностью и последовательным характером языка лучше, но на практике более серьезное препятствие, как правило, правильно обучает сеть, а RNN - изящно.
Другая проблема, которая может иметь возможность работать, - это рассмотреть проблему, такую как проблема с сбалансированными скобками (либо с помощью скобок или скобок, либо с помощью других символов-искажений). Это требует последовательной обработки входных данных и отслеживания состояния и может быть легче изучить с помощью LSTM, а затем FFN.
Обновление. Некоторые данные, которые выглядят последовательно, на самом деле не могут обрабатываться последовательно. Например, даже если вы предоставляете последовательность чисел для добавления, поскольку добавление является коммутативным, FFN будет делать так же, как и RNN. Это также может быть справедливо для многих проблем со здоровьем, где доминирующая информация не имеет последовательного характера. Предположим, что каждый год измеряются привычки к курению пациентов. С поведенческой точки зрения траектория важна, но если вы прогнозируете, будет ли у пациента развиваться рак легких, в прогнозировании будет доминировать только количество лет, в течение которых пациент курил (возможно, ограниченный последними 10 годами для FFN).
Поэтому вы хотите сделать игрушку более сложной и потребовать учета порядка данных. Может быть, какой-то симулированный временной ряд, где вы хотите предсказать, был ли всплеск данных, но вы не заботитесь об абсолютных значениях относительно относительной природы всплеска.
Update2
Я изменил ваш код, чтобы показать случай, когда RNN работают лучше. Хитрость заключалась в использовании более сложной условной логики, которая более естественно моделируется в LSTM, чем FFN. Код ниже. Для 8 столбцов мы видим, что FFN тренируется за 1 минуту и достигает потери на проверку 6.3. LSTM занимает 3 раза дольше, чтобы тренироваться, но окончательная потеря проверки в 6 раз ниже на 1,06.
Поскольку мы увеличиваем количество столбцов, LSTM имеет большее и большее преимущество, особенно если мы добавили более сложные условия. Для 16 столбцов потери проверки FFNs равны 19 (и вы можете более четко видеть кривую обучения, поскольку модель не является способный мгновенно соответствовать данным). В сравнении LSTM занимает 11 раз дольше, чтобы тренироваться, но имеет потерю валидации 0,31, в 30 раз меньше, чем FFN! Вы можете поиграть с еще более крупными матрицами, чтобы увидеть, как далеко эта тенденция будет расширяться.
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()