Как мне представить данные в Keras LSTM? - PullRequest
0 голосов
/ 04 апреля 2020

Я хочу использовать LSTM для прогнозирования следующего элемента в последовательности, но у меня возникают проблемы, когда я не могу понять, как сформулировать проблему и, в частности, как структурировать данные и представить их mdel. Я должен сказать, что я довольно новичок в LSTM - я некоторое время проходил курс Coursera по моделям последовательностей go, но кроме упражнений там никогда не удавалось опробовать вещи. В качестве переподготовки я читал некоторые (как правило, очень полезные) сообщения блога Machine Learning Mastery, такие как этот , этот и этот - но они только добавили моего замешательства. Кажется, этот вопрос относится к моему, но то же самое относится: я все время путаюсь, когда пытаюсь перевести его на свою проблему.

Позвольте мне начать с описания моей проблемы. У меня 150 последовательностей предметов разной длины (самая короткая последовательность содержит около 100 предметов; самая длинная около 700). Каждый элемент может быть представлен до четырех функций. Я хочу поэкспериментировать, какие функции будут работать лучше всего; для примера, скажем, у меня есть две особенности, представляющие каждый элемент.

Что я хочу сделать, это предсказать следующий элемент, учитывая n длинную последовательность предыдущих элементов: т. е. прогнозировать элемент на временном шаге t , учитывая элементы на временных шагах [ t - n , ..., t - 2, t -1].

Как уже упоминалось, есть две (связанные) вещи, с которыми я борюсь:

  1. Как структурировать данные.
  2. Как передать данные в LSTM.

Давайте начнем с пункта 1. Как упоминалось выше, мои исходные данные состоят из 150 последовательностей различной длины. Каждый элемент i в каждой последовательности представлен двумя функциями: [f0_i, f1_i]. Допустим, первая последовательность содержит 100 элементов; это дает следующую картину:

[[f0_0, f1_0], [f0_1, f1_1], [f0_2, f1_2], [f0_3, f1_3], [f0_4, f1_4], ... [f0_99, f1_99]] 

Пока все хорошо. Теперь предположим, что я хочу использовать историю трех временных шагов (предыдущие элементы), чтобы предсказать следующий элемент - означает ли это, что я должен реструктурировать свои тренировочные данные, чтобы приспособиться к этому? То есть, нужно ли разбивать каждую из 150 последовательностей на несколько подпоследовательностей размером с временные шаги, которые я затем собираю в одном суперсписке, например так (пример для первой последовательности):

X = [
     # sequence 0, cut up
     [[f0_0, f1_0], [f0_1, f1_1], [f0_2, f1_2]], # items 0-2 = training sample 0 
     [[f0_1, f1_1], [f0_2, f1_2], [f0_3, f1_3]], # items 1-3 = training sample 1 
     [[f0_2, f1_2], [f0_3, f1_3], [f0_4, f1_4]], # items 2-4 = training sample 2 
     ...
     [[f0_96, f1_96], [f0_97, f1_97], [f0_98, f1_98]] # items 96-98 = training sample 99
     # sequence 1, cut up
     ...
     # sequence 149, cut up 
]

y = [
     # labels for sequence 0, cut up
     [f0_3, f1_3], # item 3 = target for training sample 0
     [f0_4, f1_4], # item 4 = target for training sample 1
     [f0_5, f1_5], # item 5 = target for training sample 2
     ...
     [f0_99, f1_99] # item 99 = target for training sample 96 
     # labels for sequence 1, cut up
     ...
     # labels for sequence 49, cut up
] 

.. где каждый элемент в X является образцом, а каждый элемент в y является его целью? (Позднее весь список разбивается на обучающие и тестовые наборы.)

Или я могу просто добавить каждую полную последовательность сразу в этот суперсписок и передать ее в качестве входных данных (пропуская последний элемент в * 1048) * поскольку у него нет y), вот так (пример для первой последовательности):

X = [
     # sequence 0 = training sample 0 
     [[f0_0, f1_0], [f0_1, f1_1], [f0_2, f1_2], ..., [f0_98, f1_98]]  
     # sequence 1 = training sample 1
     # sequence 2 = training sample 2
     ...
     # sequence 149 = training sample 149
]

y = [
     # sequence 0 = targets 0
     [[f0_1, f1_1], [f0_2, f1_2], [f0_3, f1_3], ..., [f0_99, f1_99]] 
     # sequence 1 = targets 1
     # sequence 2 = targets 2
     ...
     # sequence 149 = targets 149
] 

Во втором случае я, конечно, получаю гораздо меньше выборочных последовательностей (150), но они длиннее. Однако во втором случае код нарушается (см. Ниже), так как model.fit() ожидает двумерный массив для данных y. Но как здесь y быть двумерным массивом?

Теперь перейдем к пункту 2. Вот мой код, использующий X и y, как описано выше (этот случай для модели с состоянием, поэтому for l oop вокруг вызова fit()):

batch_size = 1
time_steps = 3
num_features = len(train_X[0][0]) # = 2
epochs = 50

model = Sequential() 
model.add(LSTM(10, batch_input_shape=(batch_size, time_steps, num_features), stateful=True))
model.add(Dropout(dropout, seed=1))
model.add(Dense(num_features))

model.compile(loss='mean_squared_error', optimizer='Adam', metrics=['MSE'])
for i in range(epochs):
    history = model.fit(X, y, epochs=1, validation_split=0.2, batch_size=batch_size, verbose=2, shuffle=False)
    model.reset_states()

Кажется очевидным, что я просто установил time_steps и num_features на 3 и 2 соответственно. Но что я даю как X и y?

  • Должен ли я использовать предварительно отформатированные данные, в которых «закодированы» временные шаги и где X имеет форму (total_num_subsamples, time_steps, num_features) и y shape (total_num_subsamples, num_features)?
  • Или я должен использовать более простой формат, где X имеет форму (150, sequence_length, 2) и y некоторую 2D-форму? Будет ли настройка параметра time_steps в слое LSTM позаботиться о просмотре указанного количества временных шагов здесь?

Или ... я все делаю неправильно?

Наконец, предположим, что в основном меня интересует прогнозирование функции 0 на временном шаге t . Эта функция имеет ограниченное количество значений, т.е. Это один из нескольких классов. В этом случае, имеет ли смысл представлять каждый элемент y как горячий вектор, кодирующий класс? Или же LSTM не сможет это узнать (поскольку для элемента на временном шаге t используется другой формат, чем для элементов на предыдущих временных шагах), и мне придется представлять все элементы , также в X, в виде векторов с одним горячим вектором?

...