Для RNN (например, LSTM и GRU) вход уровня представляет собой список временных шагов, и каждый временной шаг является тензором признаков. Это означает, что вы можете иметь входной тензор, подобный этому (в нотации Pythonic):
# Input tensor to RNN
[
# Timestep 1
[ temperature_in_paris, value_of_nasdaq, unemployment_rate ],
# Timestep 2
[ temperature_in_paris, value_of_nasdaq, unemployment_rate ],
# Timestep 3
[ temperature_in_paris, value_of_nasdaq, unemployment_rate ],
...
]
Таким образом, вы можете иметь несколько функций на каждом временном шаге. На мой взгляд, погода - это особенность временных рядов: там, где я живу, это зависит от времени. Поэтому было бы разумно кодировать информацию о погоде в качестве одной из ваших функций на каждом временном шаге (с соответствующей кодировкой, например, облачно = 0, солнечно = 1 и т. Д.).
Если у вас есть данные, не относящиеся к временным рядам, то, тем не менее, не имеет смысла передавать их через LSTM. Может быть, LSTM будет работать в любом случае, но даже если это произойдет, это, вероятно, будет происходить за счет большей потери / меньшей точности за время обучения.
В качестве альтернативы, вы можете ввести такого рода «дополнительную» информацию в вашу модель вне LSTM с помощью дополнительных слоев. Вы могли бы иметь поток данных как это:
TIME_SERIES_INPUT ------> LSTM -------\
*---> MERGE ---> [more processing]
AUXILIARY_INPUTS --> [do something] --/
Таким образом, вы должны объединить свои вспомогательные входы с выходами LSTM и продолжить свою сеть оттуда. Теперь ваша модель просто мульти-входная.
Например, предположим, что в вашем конкретном приложении вы сохраняете только последний вывод выходной последовательности LSTM. Допустим, это вектор длины 10. Ваш вспомогательный вход может быть вашей закодированной погодой (так что скаляр). Ваш слой слияния может просто добавить вспомогательную информацию о погоде в конец выходного вектора LSTM, чтобы получить один вектор длины 11. Но вам не нужно просто сохранять последний временной выход LSTM: если LSTM выдает 100 временных шагов, каждый Имея 10 векторов функций, вы по-прежнему можете использовать вспомогательную информацию о погоде, в результате чего получается 100 временных шагов, каждый из которых состоит из вектора из 11 точек данных.
Документация Keras о его функциональном API имеет хороший обзор этого.
В других случаях, как указывает @horaceT, вы можете использовать LSTM для невременных данных. Например, предсказать погоду завтрашнего дня, учитывая местоположение. В этом случае вот три предложения, каждое из которых имеет положительные / отрицательные стороны:
Сделайте, чтобы первый временной шаг содержал ваши кондиционирующие данные, так как он эффективно «установит» внутреннее / скрытое состояние вашего RNN. Честно говоря, я бы не стал этого делать по нескольким причинам: ваши данные для согласования должны иметь ту же форму, что и остальные ваши функции, затруднять создание RNN с отслеживанием состояния (с точки зрения того, что вы действительно должны следить за тем, как вы передаете данные в сеть), сеть может «забыть» данные согласования за достаточное время (например, длинные обучающие последовательности или длинные последовательности предсказания) и т. д.
Включите данные как часть самих временных данных. Таким образом, каждый вектор признаков на определенном временном шаге включает «в основном» данные временного ряда, но затем к концу каждого вектора признаков добавляются данные согласования. Научится ли сеть распознавать это? Возможно, но даже тогда вы создаете более сложную задачу обучения, загрязняя данные последовательности непоследовательной информацией. Так что я бы тоже не одобрял это.
Вероятно, лучшим подходом было бы непосредственное влияние на скрытое состояние RNN в нулевой момент времени. Это подход, принятый Карпатами и Фей-Фей, а также Виньялсом и соавт . Вот как это работает:
- Для каждой обучающей выборки возьмите переменные условия .Икс⃗
- Преобразуйте / измените ваши переменные условия с помощью аффинного преобразования, чтобы привести его в правильную форму как внутреннее состояние RNN: (эти и являются обучаемыми весами). Вы можете получить его с плотным слоем в керасе.v⃗ = Ш х⃗ + б⃗ Wб⃗
- Для самого первого временного шага добавьте к скрытому состоянию RNN при расчете его значения.v⃗
Этот подход является наиболее «теоретически» правильным, так как он должным образом обуславливает RNN на ваших невременных входных данных, естественным образом решает проблему формы, а также избегает загрязнения временных интервалов входных данных дополнительной, не временной информацией. Недостатком является то, что этот подход часто требует управления вашей архитектурой на уровне графов, поэтому если вы используете абстракцию более высокого уровня, такую как Keras, вам будет сложно реализовать ее, если вы не добавите свой собственный тип слоя.