Eu luto para interpretar a diferença de codificação de Keras para a etiquetagem de sequências um para muitos (por exemplo, classificação de imagens únicas) e muitos para muitos (por exemplo, classificação de sequências de imagens). Frequentemente vejo dois tipos diferentes de códigos:
O tipo 1 é onde nenhum TimeDistributed se aplica assim:
model=Sequential()
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1], border_mode="valid", input_shape=[1, 56,14]))
model.add(Activation("relu"))
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1]))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Reshape((56*14,)))
model.add(Dropout(0.25))
model.add(LSTM(5))
model.add(Dense(50))
model.add(Dense(nb_classes))
model.add(Activation("softmax"))
O tipo 2 é onde o TimeDistributed é aplicado assim:
model = Sequential()
model.add(InputLayer(input_shape=(5, 224, 224, 3)))
model.add(TimeDistributed(Convolution2D(64, (3, 3))))
model.add(TimeDistributed(MaxPooling2D((2,2), strides=(2,2))))
model.add(LSTM(10))
model.add(Dense(3))
Minhas perguntas são:
Minha suposição está correta de que o Tipo 1 é do tipo um para muitos e o Tipo 2 é do tipo muitos para muitos? Ou
TimeDistributed
não tem relevância nesse aspecto?Em ambos os casos, um para muitos ou muitos para muitos, a última camada densa deve ter 1 nó "de comprimento" (emitindo apenas um valor por vez) e
a camada recorrente anterior é responsável por determinar quantos de
1 comprimento valor a emitir? Ou a última camada densa deve consistir em N nós ondeN=max sequence length
? Se sim, qual é o sentido de
usar a RNN aqui quando poderíamos produzir uma entrada semelhante com várias
saídas com estimadores de "baunilha" em paralelo?Como definir o número de timesteps nas RNNs? De alguma forma, está
correlacionado com o comprimento da sequência de saída ou é apenas um
hiperparâmetro para ajustar?No caso do meu exemplo Tipo 1 acima, qual é o sentido de aplicar o
LSTM quando o modelo emite apenas uma previsão de classe (possível
nb_classes
)? E se alguém omitir a camada LSTM?
Respostas:
O objetivo de usar qualquer camada recorrente é fazer com que a saída seja resultado não apenas de um item independente de outros itens, mas de uma sequência de itens, de modo que a saída da operação da camada em um item da sequência seja o resultado desse item e de qualquer item anterior na sequência. O número de intervalos de tempo define quanto tempo essa sequência é. Ou seja, quantos itens devem ser tratados em uma sequência e afetam a saída resultante um do outro.
Uma camada LSTM opera de maneira que aceita entrada no formulário number_of_timesteps, Dimensions_of_each_item. Se o parâmetro return_sequences estiver definido como False, que é por padrão, a camada "combina" as entradas de todos os timestaps em uma única saída. Se você considerar uma sequência de, digamos, 10 itens, uma camada LSTM com return_sequences definida como False produzirá um único item de saída e os atributos desse item serão o resultado de todos os itens (timesteps) no seqüência. É isso que você deseja no caso de um design muitos-para-um.
Uma camada LSTM com return_sequences definida como True irá para cada item (timestep) em uma sequência de entrada produzir uma saída. Isso é feito de tal maneira que, a qualquer momento, a saída dependerá não apenas do item que está sendo operado no momento, mas também dos itens anteriores na sequência. É isso que você deseja no caso de um design muitos-para-muitos.
Como uma camada LSTM aceita uma sequência de itens como entrada, qualquer camada anterior a uma camada LSTM em seu modelo precisará produzir uma sequência como saída. No caso do seu modelo Tipo 1, as primeiras camadas não operam em sequências, mas em um único item de cada vez. Portanto, isso não produz uma sequência de itens nos quais operar para o LSTM.
O uso de TimeDistributed possibilita que uma camada opere em todos os itens de uma sequência sem que os itens se afetem. As camadas TimeDistributed, portanto, operam em seqüências de itens, mas não há recursão.
No caso do seu modelo do tipo 2, as primeiras camadas produzirão uma sequência de cinco passos de tempo e as operações realizadas em cada um dos itens da sequência serão independentes uma da outra, pois as camadas envolvidas no TimeDistributed não são recorrentes. Como a camada LSTM usa as configurações padrão, return_sequences = False, a camada LSTM produzirá uma única saída para cada sequência de 5 itens.
O número final de nós de saída no seu modelo depende completamente do caso de uso. Um único nó é adequado para algo como classificação binária ou para produzir algum tipo de pontuação.
fonte
Eu acho que você pode usar meu trabalho anterior. Neste código, crio ondas senoidais (de comprimentos de onda e fases aleatórias) e treino um LSTM para uma sequência de pontos dessas ondas senoidais e produzo uma sequência de 150 pontos que completam cada onda senoidal.
Este é o modelo:
E este é o script inteiro:
fonte