Muitos para um e muitos para muitos exemplos de LSTM em Keras


108

Tento entender os LSTMs e como construí-los com Keras. Eu descobri que existem principalmente os 4 modos de executar um RNN (os 4 certos na foto)

insira a descrição da imagem aqui Fonte da imagem: Andrej Karpathy

Agora eu me pergunto como um trecho de código minimalista para cada um deles ficaria em Keras. Então algo como

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

para cada uma das 4 tarefas, talvez com um pouco de explicação.

Respostas:


121

Assim:

  1. Um para um : você pode usar uma Densecamada, pois não está processando sequências:

    model.add(Dense(output_size, input_shape=input_shape))
  2. Um para muitos : esta opção não é bem suportada porque o encadeamento de modelos não é muito fácil Keras, então a seguinte versão é a mais fácil:

    model.add(RepeatVector(number_of_times, input_shape=input_shape))
    model.add(LSTM(output_size, return_sequences=True))
  3. Muitos para um : na verdade, seu snippet de código é (quase) um exemplo dessa abordagem:

    model = Sequential()
    model.add(LSTM(1, input_shape=(timesteps, data_dim)))
  4. Muitos para muitos : este é o snippet mais fácil quando o comprimento da entrada e saída corresponde ao número de etapas recorrentes:

    model = Sequential()
    model.add(LSTM(1, input_shape=(timesteps, data_dim), return_sequences=True))
  5. Muitos-para-muitos quando o número de etapas difere do comprimento de entrada / saída : isso é assustadoramente difícil no Keras. Não há snippets de código fáceis para codificar isso.

EDITAR: Anúncio 5

Em um de meus aplicativos recentes, implementamos algo que pode ser semelhante a muitos para muitos da 4ª imagem. No caso de você desejar ter uma rede com a seguinte arquitetura (quando uma entrada é maior que a saída):

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

Você pode conseguir isso da seguinte maneira:

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

Onde Nestá o número das últimas etapas que você deseja cobrir (na imagem N = 3).

A partir deste ponto, chegando a:

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

é tão simples quanto uma sequência de preenchimento artificial de comprimento Nusando, por exemplo, com 0vetores, para ajustá-la a um tamanho apropriado.


10
Um esclarecimento: por exemplo, para muitos para um, você usa LSTM (1, input_shape = (timesteps, data_dim))) Eu pensei que 1 representa o número de células LSTM / nós ocultos, mas aparentemente não. Como você codificaria um Many- para um com, digamos, 512 nós, embora? (Porque eu li algo semelhante, pensei que seria feito com model.add (LSTM (512, input_shape = ...)) model.add (Dense (1)) para que é usado então?)
Luca Thiede

1
Neste caso - o seu código - depois de corrigir um erro de digitação deve estar ok.
Marcin Możejko

Por que usamos o RepeatVector, e não um vetor com a primeira entrada 1 = 0 e todas as outras entradas = 0 (de acordo com a imagem acima, não é nenhuma entrada nos estados posteriores, e nem sempre a mesma entrada, o que Repeat Vector faria em meu entendimento)
Luca Thiede

1
Se você pensar cuidadosamente sobre esta imagem - é apenas uma apresentação conceitual de uma ideia de um para muitos . Todas essas unidades ocultas devem aceitar algo como uma entrada. Portanto, eles podem aceitar a mesma entrada e também a entrada com a primeira entrada igual a xe a outra igual a 0. Mas - por outro lado - eles podem aceitar o mesmo xrepetido muitas vezes também. Uma abordagem diferente é a de modelos de cadeia que é difícil para Keras. A opção que forneci é o caso mais fácil de arquitetura um-para-muitos em Keras.
Marcin Możejko

Agradável ! Estou pensando em usar LSTM N para N em uma arquitetura GAN. Terei um gerador baseado em LSTM. Darei a esse gerador (como usado em "Variável latente" em gans) a primeira metade da série temporal e esse gerador produzirá a segunda metade da série temporal. Em seguida, combinarei as duas metades (real e gerada) para produzir a entrada "falsa" para o gan. Você acha que usar o ponto 4 de sua solução funcionará? ou, em outras palavras, esta (solução 4) é a maneira certa de fazer isso?
rjpg

6

Ótima resposta de @Marcin Możejko

Eu adicionaria o seguinte ao NR.5 (muitos para muitos com diferentes comprimentos de entrada / saída):

A) como Vanilla LSTM

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

B) como codificador-decodificador 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
Você poderia explicar os detalhes da B) Encoder-Decoder LSTMarquitetura? Estou tendo problemas para entender as funções das etapas "RepeatVector" / "TimeDistributed".
Marsellus Wallace
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.