Banyak ke satu dan banyak hingga banyak contoh LSTM di Keras

108

Saya mencoba untuk memahami LSTM dan bagaimana membangunnya dengan Keras. Saya menemukan, bahwa pada dasarnya ada 4 mode untuk menjalankan RNN (4 mode yang tepat di gambar)

masukkan deskripsi gambar di sini Sumber gambar: Andrej Karpathy

Sekarang saya bertanya-tanya bagaimana cuplikan kode minimalis untuk masing-masing akan terlihat di Keras. Jadi seperti itu

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

untuk masing-masing dari 4 tugas tersebut, mungkin dengan sedikit penjelasan.

Luca Thiede
sumber

Jawaban:

121

Begitu:

  1. Satu-ke-satu : Anda dapat menggunakan Denselapisan karena Anda tidak memproses urutan:

    model.add(Dense(output_size, input_shape=input_shape))
  2. Satu-ke-banyak : opsi ini tidak didukung dengan baik karena model perangkaian tidak mudah digunakan Keras, jadi versi berikut adalah yang termudah:

    model.add(RepeatVector(number_of_times, input_shape=input_shape))
    model.add(LSTM(output_size, return_sequences=True))
    
  3. Many-to-one : sebenarnya, cuplikan kode Anda (hampir) adalah contoh dari pendekatan ini:

    model = Sequential()
    model.add(LSTM(1, input_shape=(timesteps, data_dim)))
    
  4. Many-to-many : Ini adalah cuplikan termudah ketika panjang input dan output sesuai dengan jumlah langkah berulang:

    model = Sequential()
    model.add(LSTM(1, input_shape=(timesteps, data_dim), return_sequences=True))
    
  5. Many-to-many ketika jumlah langkah berbeda dari panjang input / output : ini sangat sulit di Keras. Tidak ada potongan kode yang mudah untuk mengkodekannya.

EDIT: Iklan 5

Di salah satu aplikasi saya baru-baru ini, kami menerapkan sesuatu yang mungkin mirip dengan many-to-many dari gambar ke-4. Jika Anda ingin memiliki jaringan dengan arsitektur berikut (ketika input lebih panjang dari output):

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

Anda dapat mencapai ini dengan cara berikut:

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

Di mana Njumlah langkah terakhir yang ingin Anda tutupi (pada gambar N = 3).

Dari titik ini menuju:

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

adalah sesederhana urutan panjang bantalan buatan Nmenggunakan misalnya dengan 0vektor, untuk menyesuaikannya ke ukuran yang sesuai.

Marcin Możejko
sumber
10
Satu klarifikasi: Misalnya untuk banyak ke satu, Anda menggunakan LSTM (1, input_shape = (timesteps, data_dim))) Saya pikir 1 adalah singkatan dari jumlah sel LSTM / node tersembunyi, tetapi sebenarnya tidak Bagaimana Anda mengkodekan Banyak- ke-satu dengan katakanlah, 512 node daripada? (Karena saya membaca sesuatu yang serupa, saya pikir itu akan dilakukan dengan model.add (LSTM (512, input_shape = ...)) model.add (Dense (1)) untuk apa itu digunakan daripada?)
Luca Thiede
1
Dalam hal ini - kode Anda - setelah mengoreksi kesalahan ketik akan baik-baik saja.
Marcin Możejko
Mengapa kita menggunakan RepeatVector, dan bukan vektor dengan entri pertama 1 = 0 dan semua entri lainnya = 0 (menurut gambar di atas, tidak ada Input sama sekali di status selanjutnya, dan tidak selalu input yang sama, apa yang Repeat Vector akan lakukan dalam pemahaman saya)
Luca Thiede
1
Jika Anda berpikir dengan hati-hati tentang gambar ini - itu hanya presentasi konseptual dari ide satu-ke-banyak . Semua unit tersembunyi ini harus menerima sesuatu sebagai masukan. Jadi - mereka mungkin menerima masukan yang sama serta masukan dengan masukan pertama sama dengan xdan lainnya sama dengan 0. Tapi - di sisi lain - mereka mungkin menerima xpengulangan yang sama berkali-kali juga. Pendekatan yang berbeda adalah model rantai yang sulit masuk Keras. Opsi yang saya berikan adalah kasus termudah dari arsitektur one-to-many di Keras.
Marcin Możejko
Bagus! Saya sedang berpikir untuk menggunakan LSTM N ke N dalam arsitektur GAN. Saya akan memiliki generator berbasis LSTM. Saya akan memberikan generator ini (seperti yang digunakan dalam "variabel laten" di gans) paruh pertama deret waktu dan generator ini akan menghasilkan paruh kedua deret waktu. Kemudian saya akan menggabungkan dua bagian (nyata dan dihasilkan) untuk menghasilkan input "palsu" untuk gan. Menurut Anda apakah menggunakan poin 4 dari penyelesaian Anda akan berhasil? atau, dengan kata lain, apakah ini (solusi 4) cara yang tepat untuk melakukan ini?
rjpg
6

Jawaban Hebat oleh @Marcin Możejko

Saya akan menambahkan yang berikut ini ke NR.5 (banyak ke banyak dengan panjang masuk / keluar berbeda):

A) sebagai Vanilla LSTM

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

B) sebagai Encoder-Decoder 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')) 
gustavz.dll
sumber
1
Bisakah Anda menjelaskan detail B) Encoder-Decoder LSTMarsitekturnya? Saya mengalami masalah dalam memahami peran langkah "RepeatVector" / "TimeDistributed".
Marsellus Wallace