Используйте два выхода. Ваша модель должна быть моделью функционального API:
#basic example of the initial part of your model
inputs = Input(input_shape)
intermediate_output = Conv2D(...)(inputs)
intermediate_output = Conv2D(...)(intermediate_output)
В какой-то момент в вашей модели вы разделите две ветви. Может быть, последний слой или немного раньше (поскольку природа двух выходов различна, может быть (требуется тестирование, конечно), для каждого выхода требуется один или два слоя для лучшей адаптации.
output1 = SomeLayer(...)(intermediate_output)
....
output1 = Dense(10, activation='softmax', name='cat_out')(output1)
output2 = SomeLayer(...)(intermediate_output)
....
output2 = SomeLayer(24, name='bound_out')(output2) #maybe choose an activation
Создание моделис двумя выходами:
model = Model(inputs, [output1, output2])
Теперь это позволяет вам иметь разные функции потерь для каждого выхода и разные метрики:
model.compile(loss = [weightedLoss(weights), 'mse'],
metrics = {'cat_out':[metrics1], 'bound_out':[metrics2],
optimizer = ...)
Поезд с двумя выходами:
model.fit(x_train, [y_train[:,:,:,:10], y_train[:,:,:,-24:]], ...)
Я не проверял вашу функцию потерь, но видел, что в ней есть циклы (обычно это плохо для тензорных операций).
Я предлагаю, чтобы ваш список весов был тензором:
weightsTensor = K.constant(listOfWeights)
И когда вы выбираете свои веса, попробуйте использовать tf.gather
или tf.gather_nd
. Я не тратил время на размышления о том, что является правильной функцией и как ее использовать, но как только вы это сделаетеэто, вы просто умножаете свои результаты на веса:
#this may need change and might be a little troublesome to understand
selectedWeights = tf.gather_nd(weightsTensor, classSelectors, ....)
loss = keras.losses.categorical_crossentropy(true, pred)
loss = selectedWeights * loss