Как объединить два слоя LSTM с разными размерами ввода в Керасе? - PullRequest
1 голос
/ 14 марта 2020

У меня есть два типа входных последовательностей, где input1 содержит 50 значений, а input2 содержит 25 значений. Я попытался объединить эти два типа последовательностей, используя модель LSTM в функциональном API. Однако, поскольку длина двух моих входных последовательностей различна, мне интересно, правильно ли я сейчас делаю. Мой код выглядит следующим образом:

input1 = Input(shape=(50,1))
x1 = LSTM(100)(input1)
input2 = Input(shape=(25,1))
x2 = LSTM(50)(input2)

x = concatenate([x1,x2])
x = Dense(200)(x)
output = Dense(1, activation='sigmoid')(x)

model = Model(inputs=[input1,input2], outputs=output)

Более конкретно, я хочу знать, как объединить два слоя LSTM, которые имеют разную длину ввода (то есть 50 и 25 в моем случае). Я рад предоставить более подробную информацию, если это необходимо.

1 Ответ

1 голос
/ 17 марта 2020

На самом деле ваша проблема довольно обычна в задачах типа НЛП, где у вас разная длина последовательности. В своем комментарии вы отбрасываете весь предыдущий вывод, используя return_sequences=False, что не распространено в нашей практике и обычно приводит к низкоэффективной модели.

Примечание: Не существует окончательного решения для проектирования архитектуры нейронной сети

Вот что я могу предложить.

Метод 1 (Нет требуется пользовательский слой)

Вы можете использовать одинаковое скрытое измерение в обоих LSTM, складывать их в 2 измерения и рассматривать их как один большой тензор скрытого слоя.

input1 = Input(shape=(50,1))
x1 = LSTM(100, return_sequences=True)(input1)
input2 = Input(shape=(25,1))
x2 = LSTM(100, return_sequences=True)(input2)
x = concatenate([x1,x2], axis=1)

# output dimension = (None, 75, 100)

Если вы Я не хочу иметь такое же скрытое измерение, что делают другие, добавляя еще 1 часть, которую мы обычно называем слоем отображения, состоящим из сложенного плотного слоя. Этот подход имеет большую вариабельность, что означает, что модель сложнее обучить.

input1 = Input(shape=(50,1))
x1 = LSTM(100, return_sequences=True)(input1)
input2 = Input(shape=(25,1))
x2 = LSTM(50, return_sequences=True)(input2)

# normally we have more than 1 hidden layer
Map_x1 = Dense(75)(x1)
Map_x2 = Dense(75)(x2)
x = concatenate([Map_x1 ,Map_x2 ], axis=1)

# output dimension = (None, 75, 75)

Или сгладить вывод (оба)

input1 = Input(shape=(50,1))
x1 = LSTM(100, return_sequences=True)(input1)
input2 = Input(shape=(25,1))
x2 = LSTM(50, return_sequences=True)(input2)

# normally we have more than 1 hidden layer
flat_x1 = Flatten()(x1)
flat_x2 = Flatten()(x2)
x = concatenate([flat_x1 ,flat_x2 ], axis=1)

# output (None, 2650)

Метод 2 (требуется пользовательский слой)

создайте свой пользовательский слой и используйте механизм внимания, который создает вектор внимания, и используйте этот вектор внимания как представление выходного тензора LSTM. То, что делают другие и достигают лучшей производительности, - это использовать последнее скрытое состояние LSTM (которое вы используете только в своей модели) с вектором внимания в качестве представления.

Примечание: Согласно исследованиям, разные типы внимания дают почти одинаковую производительность, поэтому я рекомендую "Scaled Dot-Product Attention", потому что он быстрее вычисляется.

input1 = Input(shape=(50,1))
x1 = LSTM(100, return_sequences=True)(input1)
input2 = Input(shape=(25,1))
x2 = LSTM(50, return_sequences=True)(input2)

rep_x1 = custom_layer()(x1)
rep_x2 = custom_layer()(x2)
x = concatenate([rep_x1 ,rep_x2], axis=1)

# output (None, (length rep_x1+length rep_x2))
...