Wiele do jednego i wiele do wielu przykładów LSTM w Keras

108

Próbuję zrozumieć LSTM i jak je zbudować za pomocą Keras. Dowiedziałem się, że są zasadniczo 4 tryby do uruchomienia RNN (4 właściwe na zdjęciu)

wprowadź opis obrazu tutaj Źródło obrazu: Andrej Karpathy

Teraz zastanawiam się, jak wyglądałby minimalistyczny fragment kodu dla każdego z nich w Keras. Więc coś w stylu

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

dla każdego z 4 zadań, może z niewielkim wyjaśnieniem.

Luca Thiede
źródło

Odpowiedzi:

121

Więc:

  1. Jeden do jednego : możesz użyć Densewarstwy, ponieważ nie przetwarzasz sekwencji:

    model.add(Dense(output_size, input_shape=input_shape))
  2. Jeden do wielu : ta opcja nie jest obsługiwana dobrze, ponieważ łączenie modeli w łańcuchy nie jest łatwe Keras, więc poniższa wersja jest najłatwiejsza:

    model.add(RepeatVector(number_of_times, input_shape=input_shape))
    model.add(LSTM(output_size, return_sequences=True))
  3. Wiele do jednego : w rzeczywistości fragment kodu jest (prawie) przykładem takiego podejścia:

    model = Sequential()
    model.add(LSTM(1, input_shape=(timesteps, data_dim)))
  4. Wiele do wielu : jest to najłatwiejszy fragment kodu, gdy długość danych wejściowych i wyjściowych odpowiada liczbie powtarzających się kroków:

    model = Sequential()
    model.add(LSTM(1, input_shape=(timesteps, data_dim), return_sequences=True))
  5. Wiele do wielu, gdy liczba kroków różni się od długości wejścia / wyjścia : w Keras jest to bardzo trudne. Nie ma łatwych fragmentów kodu, które to zakodowały.

EDYCJA: Ad 5

W jednej z moich ostatnich aplikacji zaimplementowaliśmy coś, co może być podobne do wielu do wielu z czwartego obrazu. W przypadku, gdy chcesz mieć sieć o następującej architekturze (gdy wejście jest dłuższe niż wyjście):

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

Możesz to osiągnąć w następujący sposób:

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

Gdzie Njest liczba ostatnich kroków, które chcesz wykonać (na obrazku N = 3).

Od tego momentu dotarcie do:

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

jest tak prosta, jak sztuczna sekwencja długości wypełnienia Nprzy użyciu np. 0wektorów, w celu dostosowania jej do odpowiedniego rozmiaru.

Marcin Możejko
źródło
10
Jedno wyjaśnienie: na przykład dla wielu do jednego używasz LSTM (1, input_shape = (timesteps, data_dim))) Myślałem, że 1 oznacza liczbę komórek LSTM / ukrytych węzłów, ale najwyraźniej nie Jak zakodowałbyś wiele- do jednego z powiedzmy 512 węzłami niż? (Ponieważ czytałem coś podobnego, myślałem, że zostanie to zrobione z model.add (LSTM (512, input_shape = ...)) model.add (Dense (1)) po co to jest używane?)
Luca Thiede
1
W tym przypadku - Twój kod - po poprawieniu literówki powinien być ok.
Marcin Możejko
Dlaczego używamy RepeatVector, a nie wektora z pierwszym wpisem 1 = 0 i wszystkimi innymi wpisami = 0 (zgodnie z powyższym obrazkiem, w późniejszych stanach nie ma żadnego wejścia i nie zawsze to samo wejście, co Repeat Vector zrobiłby w moim rozumieniu)
Luca Thiede
1
Jeśli dobrze się zastanowisz nad tym obrazem - to tylko koncepcyjna prezentacja pomysłu jeden do wielu . Wszystkie te ukryte jednostki muszą przyjąć coś jako dane wejściowe. Tak więc - mogą zaakceptować te same dane wejściowe, jak również dane wejściowe z pierwszym wejściem równym, xa innym równym 0. Ale - z drugiej strony - mogliby zaakceptować to samo, xpowtarzane wielokrotnie. Inne podejście to tworzenie łańcuchów modeli, które są trudne Keras. Opcja, którą podałem, jest najłatwiejszym przypadkiem architektury jeden do wielu w Keras.
Marcin Możejko
Miły ! Myślę o użyciu LSTM N do N w architekturze GAN. Będę miał generator oparty na LSTM. Dam temu generetorowi (używanemu w „Zmiennej ukrytej” w ganach) pierwszą połowę szeregu czasowego, a ten generator wyprodukuje drugą połowę szeregu czasowego. Następnie połączę dwie połowy (rzeczywistą i wygenerowaną), aby wyprodukować „fałszywe” dane wejściowe dla gan. Czy myślisz, że użycie punktu 4 twojego rozwiązania zadziała? lub, innymi słowy, czy to (rozwiązanie 4) jest właściwą drogą do zrobienia tego?
rjpg
6

Świetna odpowiedź @Marcin Możejko

Dodałbym do NR.5 (wiele do wielu z różną długością wejścia / wyjścia):

A) jako Vanilla LSTM

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

B) jako koder-dekoder 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
źródło
1
Czy mógłbyś wyjaśnić szczegóły B) Encoder-Decoder LSTMarchitektury? Mam problemy ze zrozumieniem ról kroków „RepeatVector” / „TimeDistributed”.
Marsellus Wallace