Сделать фиксированную длину временного шага LSTM Keras модель свободная длина временного шага - PullRequest
0 голосов
/ 01 декабря 2018

У меня есть многозадачная модель Keras LSTM, которая выполняет две задачи.Одним из них является задача тегирования последовательности (поэтому я предсказываю метку для каждого токена).Другой - глобальная классификационная задача по всей последовательности с использованием CNN, которая сложена в скрытых состояниях LSTM.

В моей настройке (не спрашивайте, почему) мне нужно только задание CNN во время обучения,но метки, которые он предсказывает, бесполезны для конечного продукта.Таким образом, на Keras можно обучить модель LSTM без указания длины входной последовательности.как это:

l_input = Input(shape=(None,), dtype="int32", name=input_name)

Однако, если я добавлю CNN, сложенный в скрытых состояниях LSTM, мне нужно будет установить фиксированную длину последовательности для модели.

l_input = Input(shape=(timesteps_size,), dtype="int32", name=input_name)

Проблема в том, чтокак только я обучил модель с фиксированным значением timestep_size, я больше не могу использовать ее для прогнозирования более длинных последовательностей.

В других средах это не проблема.Но в Керасе я не могу избавиться от CNN и изменить ожидаемую форму ввода модели после ее обучения.

Вот упрощенная версия модели

l_input = Input(shape=(timesteps_size,), dtype="int32")
l_embs  = Embedding(len(input.keys()), 100)(l_input)
l_blstm = Bidirectional(GRU(300, return_sequences=True))(l_embs)

# Sequential output
l_out1  = TimeDistributed(Dense(len(labels.keys()),
                                activation="softmax"))(l_blstm)


# Global output
conv1  = Conv1D( filters=5 , kernel_size=10 )( l_embs )
conv1  = Flatten()(MaxPooling1D(pool_size=2)( conv1 ))

conv2  = Conv1D( filters=5 , kernel_size=8 )( l_embs )
conv2  = Flatten()(MaxPooling1D(pool_size=2)( conv2 ))

conv   = Concatenate()( [conv1,conv2] )
conv   = Dense(50, activation="relu")(conv)

l_out2 = Dense( len(global_labels.keys()) ,activation='softmax')(conv)

model  = Model(input=input, output=[l_out1, l_out2])
optimizer = Adam()

model.compile(optimizer=optimizer,
              loss="categorical_crossentropy",
              metrics=["accuracy"])

IХотелось бы узнать, сталкивался ли кто-нибудь здесь с этой проблемой, и есть ли какие-либо решения для удаления слоев из модели после обучения и, что более важно, как изменить размеры входных слоев после обучения.

Спасибо

1 Ответ

0 голосов
/ 01 декабря 2018

Переменная длина временного шага создает проблему не из-за использования сверточных слоев (на самом деле хорошо в сверточных слоях является то, что они не зависят от размера ввода).Скорее, проблема заключается в использовании Flatten слоев, так как им требуется ввод с указанным размеромВместо этого вы можете использовать слои Global Pooling.Кроме того, я думаю, что наложение слоев свертки и объединение слоев друг на друге может дать лучший результат вместо использования двух отдельных слоев свертки и их объединения (хотя это зависит от конкретной проблемы и набора данных, над которым вы работаете).Поэтому, учитывая эти два момента, было бы лучше написать вашу модель следующим образом:

# Global output
conv1 = Conv1D(filters=16, kernel_size=5)(l_embs)
conv1 = MaxPooling1D(pool_size=2)(conv1)

conv2 = Conv1D(filters=32, kernel_size=5)(conv1)
conv2 = MaxPooling1D(pool_size=2)(conv2)

gpool = GlobalAveragePooling1D()(conv2)

x = Dense(50, activation="relu")(gpool)
l_out2 = Dense(len(global_labels.keys()), activation='softmax')(x)

model  = Model(inputs=l_input, outputs=[l_out1, l_out2])

Возможно, вам придется настроить количество слоев conv + maxpool, количество фильтров, размер ядра и даже добавить выпадение или пакетслои нормализации.

В качестве примечания, использование TimeDistributed на слое Dense является избыточным, поскольку Плотный слой применяется на последней оси .

...