Примеры от многих к одному и от многих ко многим LSTM в Керасе

108

Я пытаюсь понять LSTM и как их создавать с помощью Keras. Я обнаружил, что в основном есть 4 режима для запуска RNN (4 правые на картинке)

введите описание изображения здесь Источник изображения: Андрей Карпаты

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

model = Sequential()
model.add(LSTM(128, input_shape=(timesteps, data_dim)))
model.add(Dense(1))

для каждой из 4 задач, возможно, с небольшими пояснениями.

Лука Тиде
источник

Ответы:

122

Так:

  1. Один к одному : вы можете использовать Denseслой, поскольку вы не обрабатываете последовательности:

    model.add(Dense(output_size, input_shape=input_shape))
  2. Один ко многим : эта опция плохо поддерживается, так как объединение моделей в цепочку не очень простое дело Keras, поэтому следующая версия является самой простой:

    model.add(RepeatVector(number_of_times, input_shape=input_shape))
    model.add(LSTM(output_size, return_sequences=True))
  3. Многие-к-одному : на самом деле, ваш фрагмент кода является (почти) примером этого подхода:

    model = Sequential()
    model.add(LSTM(1, input_shape=(timesteps, data_dim)))
  4. Многие-ко-многим : это самый простой фрагмент, когда длина ввода и вывода соответствует количеству повторяющихся шагов:

    model = Sequential()
    model.add(LSTM(1, input_shape=(timesteps, data_dim), return_sequences=True))
  5. Многие-ко-многим, когда количество шагов отличается от длины ввода / вывода : в Keras это ужасно сложно. Для этого не существует простых фрагментов кода.

РЕДАКТИРОВАТЬ: Объявление 5

В одном из моих недавних приложений мы реализовали кое-что, что может быть похоже на « многие ко многим» из 4-го изображения. Если вы хотите иметь сеть со следующей архитектурой (когда вход длиннее выхода):

                                        O O O
                                        | | |
                                  O O O O O O
                                  | | | | | | 
                                  O O O O O O

Вы можете добиться этого следующим образом:

    model = Sequential()
    model.add(LSTM(1, input_shape=(timesteps, data_dim), return_sequences=True))
    model.add(Lambda(lambda x: x[:, -N:, :]

Где Nколичество последних шагов, которые вы хотите пройти (на картинке N = 3).

С этого момента переходят к:

                                        O O O
                                        | | |
                                  O O O O O O
                                  | | | 
                                  O O O 

так же просто, как искусственная последовательность заполнения длины Nс использованием, например, 0векторов, чтобы настроить ее до подходящего размера.

Марцин Можейко
источник
10
Одно пояснение: например, для многих к одному вы используете LSTM (1, input_shape = (timesteps, data_dim))) Я думал, что 1 означает количество ячеек LSTM / скрытых узлов, но, по-видимому, не Как бы вы закодировали много- к одному, скажем, 512 узлов, хотя чем? (Поскольку я читал нечто подобное, я думал, что это будет сделано с помощью model.add (LSTM (512, input_shape = ...)) model.add (Dense (1)) для чего это используется?)
Лука Тиде,
1
В этом случае - ваш код - после исправления опечатки все должно быть в порядке.
Marcin Moejko
Почему мы используем RepeatVector, а не вектор с первой записью 1 = 0, а все остальные записи = 0 (согласно рисунку выше, в более поздних состояниях нет ввода вообще, и не всегда тот же ввод, что, в моем понимании, сделает Repeat Vector)
Лука Тиде,
1
Если хорошенько задуматься над этой картинкой - это всего лишь концептуальное представление идеи « один ко многим» . Все эти скрытые блоки должны принимать что-то в качестве входных данных. Итак - они могут принимать тот же ввод, что и ввод с первым вводом, равным, xа другие равными 0. Но - с другой стороны - они могут принять то же самое, xповторяющееся много раз. Другой подход - к цепным моделям, в которых сложно Keras. Предложенный мной вариант - это простейший вариант архитектуры " один ко многим" в Keras.
Marcin Możejko
Ницца ! Я думаю об использовании LSTM от N до N в архитектуре GAN. У меня будет генератор на основе LSTM. Я дам этому генератору (как используется в «Скрытой переменной» в gans) первую половину временного ряда, и этот генератор будет производить вторую половину временного ряда. Затем я объединю две половинки (настоящую и сгенерированную), чтобы получить «фальшивый» ввод для гана. Как вы думаете, сработает ли четвертый пункт вашего решения? или, другими словами, это (решение 4) правильный способ сделать это?
rjpg
6

Отличный ответ @Marcin Możejko

Я бы добавил к NR.5 следующее (многие ко многим с разной длиной входа / выхода):

A) как Vanilla LSTM

model = Sequential()
model.add(LSTM(N_BLOCKS, input_shape=(N_INPUTS, N_FEATURES)))
model.add(Dense(N_OUTPUTS))

Б) как кодировщик-декодер LSTM

model.add(LSTM(N_BLOCKS, input_shape=(N_INPUTS, N_FEATURES))  
model.add(RepeatVector(N_OUTPUTS))
model.add(LSTM(N_BLOCKS, return_sequences=True))  
model.add(TimeDistributed(Dense(1)))
model.add(Activation('linear')) 
Густавз
источник
1
Не могли бы вы объяснить детали B) Encoder-Decoder LSTMархитектуры? У меня возникли проблемы с пониманием роли шагов «RepeatVector» / «TimeDistributed».
Марселлус Уоллес