Вопрос или проблема
class Net2:
@staticmethod
def build_cat_branch(inputs,category_size):
x = TimeDistributed(Dense(category_size))(inputs)
x = Activation('softmax', name="cat_output")(x)
return x
@staticmethod
def build_t_branch(inputs):
x = TimeDistributed(Dense(1, activation='relu', name="t_output"))(inputs)
return x
@staticmethod
def build_full_model(timestep_len,hidden_size,category_size,num_features,dropout,rec_drop):
inputs = Input(shape=(timestep_len,num_features),name="Input")
bn = BatchNormalization()(inputs)
lstm = LSTM(hidden_size, return_sequences=True, dropout=dropout, recurrent_dropout=rec_drop,name="LSTM")(bn)
bn2 = BatchNormalization()(lstm)
cat_branch = Net2.build_cat_branch(bn2,category_size)
t_branch = Net2.build_t_branch(bn2)
model = Model(inputs=inputs,outputs=[cat_branch,t_branch],name="Net2")
return model
Когда я пытаюсь скомпилировать эту модель, я получаю:
ValueError: Неизвестная запись в словаре потерь: “t_output”. Ожидались следующие ключи: [‘cat_output’, ‘time_distributed_2’]
(в сводке моей модели слой, который я назвал “t_output”, имеет имя “time_distributed_2” вместо этого)
Итак, в основном, мой вопрос в том, что происходит с оберткой TD, которая вызывает то, что атрибут имени не является частью объекта, возвращаемого функцией build_t_branch? Явно, имя “cat_output” сохранено правильно, так как словарь потерь его распознает, но выходной слой, который я имею внутри обертки TimeDistributed, не сохраняет пользовательское имя слоя. Я знаю, что могу обойти это, просто определив все слои в одной функции без функций “ветки”, но это не суть. Это ошибка в Keras? Есть ли способ обойти это без вышеупомянутого исправления?
Причина в том, что вам следует называть TD вместо Dense. Будьте осторожны с открывающей скобкой. Измените это на:
x = TimeDistributed(Dense(1, activation=’relu’), name=”t_output”)(inputs)
Ответ или решение
Проблема: Неправильное наименование слоя с использованием обертки TimeDistributed в Keras
При классическом использовании функционального API Keras возникает ситуация, когда имя слоя, созданного в гимна, не сохраняется должным образом, особенно когда используется обертка TimeDistributed
. В вашем коде, после вызова функции build_t_branch
, слой Dense
, заворачиваемый в TimeDistributed
, не получает ожидаемое имя, что приводит к ошибке во время компиляции модели.
Анализ проблемы
Ваша функция build_t_branch
создает выходной слой (где ожидалось имя "t_output"), но под оберткой TimeDistributed
этот слой переназначается. Это происходит из-за того, что TimeDistributed
создает новый слой, и атрибут name
передается не тому слою, который вы ожидаете. Вместо этого, имя, которое фиксируется в истории модели, определяется самой оберткой, которая присваивает имена на основе структуры своей очереди слоев.
При рассмотрении вашего кода:
x = TimeDistributed(Dense(1, activation='relu', name="t_output"))(inputs)
Имя "t_output" присваивается слою Dense
, но обертка TimeDistributed
создает новый слой, имя которого выступает как time_distributed_2
.
Решение проблемы
Чтобы правильно указать имя для выходного слоя, необходимо перенести атрибут name
в обертку TimeDistributed
. Имя будет применено к TimeDistributed
, а не к внутреннему слою Dense
. Вот исправленный код:
x = TimeDistributed(Dense(1, activation='relu'))(inputs)
#этот слой теперь получит имя от TimeDistributed
x = Activation('linear', name="t_output")(x)
Альтернативный подход
Если вы хотите сохранить структуру своего кода и не вносить много изменений, можно воспользоваться следующим подходом:
-
Создать именованный слой перед применением обертки
TimeDistributed
:dense_layer = Dense(1, activation='relu', name="t_output") x = TimeDistributed(dense_layer)(inputs)
Таким образом, выходной слой будет корректно сохранен с именем в model
и будет доступен для использования.
Заключение
Эта проблема не является ошибкой в самом Keras, но скорее особенностью работы с обертками TimeDistributed
. Используя вышеописанные правильные подходы, вы сможете получить желаемые имена для слоев и избежать конфликта при компиляции модели. Расширенное понимание того, как именуются слои внутри оберток, позволит вам более эффективно строить сложные нейронные сети с использованием Keras.