Багато в одному і багато-багато прикладів LSTM в Керасі


108

Я намагаюся зрозуміти LSTM і як їх побудувати за допомогою Кераса. Я з'ясував, що в основному є 4 режими для запуску RNN (4 правильних на малюнку)

введіть тут опис зображення Джерело зображення: Андрій Карпатій

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

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

для кожного з 4 завдань, можливо, з невеликим поясненням.

Відповіді:


121

Так:

  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. Багато-багато-багато, коли кількість кроків відрізняється від довжини вводу / виводу : це важко важко в Керасі. Немає простих фрагментів коду, щоб кодувати це.

Редагувати: Об'ява 5

В одному з моїх останніх застосувань ми реалізували щось, що може бути подібним багатьом до багатьох із четвертого зображення. Якщо ви хочете мати мережу із такою архітектурою (коли вхід довший, ніж вихід):

                                        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 = (timeteps, data_dim))) Я думав, що 1 означає кількість комірок LSTM / прихованих вузлів, але, як ні, як би ви кодували багато- до одного, що дозволяє сказати, 512 вузлів хоча? (Оскільки я читав щось подібне, я думав, що це буде зроблено з model.add (LSTM (512, input_shape = ...)) model.add (щільний (1)) для чого це використовується?)
Лука Тієде,

1
У цьому випадку - ваш код - після виправлення друкарської помилки повинно бути гаразд.
Marcin Możejko

Чому ми використовуємо RepeatVector, а не векторний з першим записом 1 = 0, а всі інші записи = 0 (згідно з малюнком вище, значення "Введення" взагалі не є в пізніших станах, і не завжди той самий вхід, що робитиме Repeat Vector в моєму розумінні)
Лука Тієд

1
Якщо ви ретельно продумаєте цю картину - це лише концептуальна презентація ідеї одного на багатьох . Усі ці приховані одиниці повинні щось сприймати як вхід. Отже - вони можуть приймати той самий вхід, що і перший вхід, xа другий дорівнює 0. Але, з іншого боку, вони можуть сприймати те саме, що xповторювалося також багато разів. Інший підхід полягає у тому, щоб складно використовувати моделі ланцюгів Keras. Я запропонував цей варіант - найпростіший випадок архітектури, призначеної для багатьохKeras .
Marcin Możejko

Приємно! Я думав про використання LSTM N до N в архітектурі GAN. У мене буде генератор на основі LSTM. Я дам цьому генератору (як він використовується у "Латентній змінній" у ґанах) першу половину часового ряду, і цей генератор видасть другу половину часового ряду. Тоді я з’єднаю дві половини (реальну та генеровану), щоб створити "підроблений" вхід для банди. Як ви думаєте, використання розчинника 4 з вас розчинення спрацює? або, іншими словами, це (рішення 4) правильний спосіб зробити це?
rjpg

6

Чудова відповідь від @Marcin Możejko

Я б додав до NR.5 (багато-багато з різною довжиною / виходом):

А) як ванільний 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".
Марселл Уоллес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.