Предсказание следующего члена в последовательности умножения 2 с использованием LSTM - PullRequest
0 голосов
/ 06 мая 2020

Я пытаюсь решить очень простую задачу (якобы простую, мне снятся кошмары).

Мои данные:

   0.64900194,  2.32144675,  4.36117903,  6.8795263 ,  8.70335759,
   10.52469321, 12.50494439, 14.92118469, 16.31657096, 18.69954666,
   20.653336  , 22.08447934, 24.29878371, 26.01567801, 28.3626067 ,
   30.75065028, 32.81166691, 34.52029737, 36.90956918, 38.55743122

, а соответствующая цель для приведенной выше последовательности данных - 40,24253

Как видите, это простая задача прогнозирования последовательности lstm, где входные данные - это последние 20 значений последовательности умножения двойки, а цель - это следующее число в последовательности + некоторое случайное равномерное число (для добавления небольшого шума).

Пример ввода и целевые размеры: (batch_size, 20, 1) и (batch_size,)

Это код, который я использую для прогнозирования:

def univariate_data(dataset, start_index, end_index, history_size, target_size):
    data = []
    labels = []

    start_index = start_index + history_size
    if end_index is None:
        end_index = len(dataset) - target_size

    for i in range(start_index, end_index):
        indices = range(i-history_size, i)
        # Reshape data from (history_size,) to (history_size, 1)
        data.append(np.reshape(dataset[indices], (history_size, 1)))
        labels.append(dataset[i+target_size])
    return np.array(data), np.array(labels)



uni_data = np.array([(i*2)+random.random() for i in range(0,400000)])


TRAIN_SPLIT = 300000

uni_train_mean = uni_data[:TRAIN_SPLIT].mean()
uni_train_std = uni_data[:TRAIN_SPLIT].std()


uni_data = (uni_data-uni_train_mean)/uni_train_std


univariate_past_history = 20
univariate_future_target = 0

x_train_uni, y_train_uni = univariate_data(uni_data, 0, TRAIN_SPLIT,
                                           univariate_past_history,
                                           univariate_future_target)
x_val_uni, y_val_uni = univariate_data(uni_data, TRAIN_SPLIT, None,
                                       univariate_past_history,
                                       univariate_future_target)

print ('Single window of past history')
print (x_train_uni.shape)
print ('\n Target temperature to predict')
print (y_train_uni.shape)

BATCH_SIZE = 256
BUFFER_SIZE = 10000

train_univariate = tf.data.Dataset.from_tensor_slices((x_train_uni, y_train_uni))
train_univariate = train_univariate.cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE).repeat()

val_univariate = tf.data.Dataset.from_tensor_slices((x_val_uni, y_val_uni))
val_univariate = val_univariate.batch(BATCH_SIZE).repeat()



simple_lstm_model = tf.keras.models.Sequential([
    tf.keras.layers.LSTM(8, input_shape=x_train_uni.shape[-2:]),
    tf.keras.layers.Dense(1)
])

simple_lstm_model.compile(optimizer='adam', loss='mae')

for x, y in val_univariate.take(1):
    print(simple_lstm_model.predict(x).shape)

EVALUATION_INTERVAL = 200
EPOCHS = 10

simple_lstm_model.fit(train_univariate, epochs=EPOCHS,
                      steps_per_epoch=EVALUATION_INTERVAL,
                      validation_data=val_univariate, validation_steps=50)

Прогноз для любой данной последовательности далек от фактического значения, любые предложения могут помочь.

Некоторые предыдущие поиски давали предложения по нормализации, стандартизации, я пробовал и то, и другое. Я также пробовал разные уровни LSTM и пробовал с SimpleRNN, GRU. Пробовал с разными функциями активации, 'tanh', 'relu'. Пытался использовать последние 10, 30 и 50 значений вместо прошлых 20. Ни одно из них не помогло. Я считаю, что делаю очень простую ошибку, любое руководство мне очень поможет. Спасибо и будьте в безопасности !!

1 Ответ

0 голосов
/ 09 мая 2020

Итак, я наконец нашел решение.

Проблема в вышеупомянутом подходе заключается в том, что среднее и стандартное значение моих данных поезда и теста сильно различались. Другими словами, я тренировал модель с данными диапазона (0,400000), а мой тестовый набор был диапазоном (400000, 500000). Теперь среднее и стандартное отклонение, которые я получил из данных обучения, сильно отличалось от данных теста, также стандартное отклонение в приведенном выше случае составляет около 173250 (данных обучения). Любой модели очень сложно точно предсказать, когда она обучена с данными, имеющими такое высокое стандартное отклонение.

Решение состоит в том, что вместо того, чтобы напрямую вводить данные в модель, подавать разность последовательных элементов. Например, вместо загрузки данных p = [0, 1, 2, 3, 4, 5, 6] загрузите данные q = [2, 2, 2, 2, 2, 2, 2], где q получается как q[i] = p[i] - p[i-1]. Итак, теперь, если мы введем в модель данные q, из c модель будет предсказывать 2, поскольку модель видела только ввод 2, который мы можем просто добавить к последнему фактическому значению и получить результат.

Итак, основная проблема c модели - это высокое стандартное отклонение обучающих данных и невидимых значений в тесте, и решение состоит в том, чтобы скормить разницу значений.

Но другой вопрос может заключаться в том, как нам это сделать, если мы хотим предсказать следующий элемент 2 ** x, т.е. экспоненту 2, в этом случае модель снова, возможно, изучит тенденцию, учитывая данные типа q, но по-прежнему модель не будет очень точной, поскольку в какой-то момент она снова будет иметь значения с очень высоким средним и стандартным.

Наконец, я где-то читал, что LSTM не предназначен для экстраполяции данных из модели встраиваемого пространства, которой не подвергались, существуют другие модели для экстраполяции данных, но это не LSTM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...