Я реализовал эту потерю, ваша реализация была моей первой попыткой, и, как вы говорите, она просто не работает. Я не уверен, почему, но вот правильный способ реализовать эту потерю:
def regression_nll_loss(sigma_sq, epsilon = 1e-6):
def nll_loss(y_true, y_pred):
return 0.5 * K.mean(K.log(sigma_sq + epsilon) + K.square(y_true - y_pred) / (sigma_sq + epsilon))
return nll_loss
Как вы видите, эта потеря принимает только контролируемые метки для среднего значения. Дисперсия должна быть передана непосредственно в убыток как тензор:
inp = Input(shape=(1,))
x = Dense(10, activation="relu")(inp)
x = Dense(20, activation="relu")(x)
x = Dense(30, activation="relu")(x)
mean = Dense(1, activation="linear")(x)
var = Dense(1, activation="softplus")(x)
train_model = Model(inp, mean)
pred_model = Model(inp, [mean, var])
train_model.compile(loss=regression_nll_loss(var), optimizer="adam")
Затем вы можете использовать train_model
для обычного обучения с model.fit
и pred_model
для прогнозирования.
Вы можете увидеть полный пример, используя мою библиотеку, по адресу: https://github.com/mvaldenegro/keras-uncertainty/blob/master/examples/regression_deep-ensemble.py
Я думаю, что также возможно реализовать эту потерю с помощью add_loss
API, но я не пробовал .