Я пытаюсь сделать пользовательскую функцию для отклонения в Керасе.
Отклонение рассчитывается как: 2 * (log (yTrue) - log (yPred))
Проблема здесь в том, что мои значения yTrue представляют собой число редких событий и поэтому часто равны 0, что приводит к ошибке -inf.
Вывод отклонения для моего конкретного случая (отклонение по Пуассону без масштабирования) дает решение этой проблемы:
- Если yTrue = 0, то отклонение равно: 2 * D * yPred, где D - особенность моих данных.
- Если yTrue! = 0, то отклонение равно: 2 * D * (yTrue * ln (yTrue) - yTrue * ln (yPred) - yTrue + yPred
Здесь я сталкиваюсь с двумя проблемами:
- Мне нужно выбрать функцию в соответствии со значением yPred
- Мне также нужно передать D в качестве аргумента функции потерь
Я сделал первую итерацию функции потерь перед выводом отклонения, добавив небольшие значения к yTrue, когда оно равно 0, чтобы предотвратить -Inf. проблемы, но это дает неправильные результаты для отклонения, поэтому я должен изменить его.
def DevianceBis(y_true, y_pred):
y_pred = KB.maximum(y_pred, 0.0 + KB.epsilon()) #make sure ypred is positive or ln(-x) = NAN
return (KB.sqrt(KB.square( 2 * KB.log(y_true + KB.epsilon()) - KB.log(y_pred))))
Я хотел бы знать, как передать значения D в функцию потерь и как использовать оператор if, чтобы выбрать правильное выражение для использования.
Заранее спасибо
РЕДАКТИРОВАТЬ:
Пробовал это, но возвращает NaN
def custom_loss(data, y_pred):
y_true = data[:, 0]
d = data[:, 1:]
# condition
mask = keras.backend.equal(y_true, 0) #i.e. y_true != 0
mask = KB.cast(mask, KB.floatx())
# returns 0 when y_true =0, 1 otherwise
#calculate loss using d...
loss_value = mask * (2 * d * y_pred) + (1-mask) * 2 * d * (y_true * KB.log(y_true) - y_true * KB.log(y_pred) - y_true + y_pred)
return loss_value
def baseline_model():
# create model
#building model
model = keras.Sequential()
model.add(Dense(5, input_dim = 26, activation = "relu"))
#model.add(Dense(10, activation = "relu"))
model.add(Dense(1, activation = "exponential"))
model.compile(loss=custom_loss, optimizer='RMSProp')
return model
model = baseline_model()
model.fit(data2, np.append(y2, d, axis = 1), epochs=1, shuffle=True, verbose=1)
РЕДАКТИРОВАТЬ 2:
def custom_loss(data, y_pred):
y_true = data[:, 0]
d = data[:, 1:]
# condition
mask2 = keras.backend.not_equal(y_true, 0) #i.e. y_true != 0
mask2 = KB.cast(mask2, KB.floatx())
# returns 0 when y_true =0, 1 otherwise
#calculate loss using d...
loss_value = 2 * d * y_pred + mask2 * (2 * d * y_true * KB.log(y_true) + 2 * d * y_true * KB.log(y_pred) - 2 * d * y_true)
return loss_value
EDIT 3, кажется, работает без журналов (хотя это не тот результат, который я ищу):
def custom_loss(data, y_pred):
y_true = data[:, 0]
d = data[:, 1]
# condition
mask2 = keras.backend.not_equal(y_true, 0) #i.e. y_true != 0
mask2 = KB.cast(mask2, KB.floatx())
# returns 0 when y_true =0, 1 otherwise
#calculate loss using d...
loss_value = 2 * d * y_pred #+ mask2 * (2 * d * y_true * KB.log(y_true) + 2 * d * y_true * KB.log(y_pred) - 2 * d * y_true)
return loss_value
def baseline_model():
# create model
#building model
model = keras.Sequential()
model.add(Dense(5, input_dim = 26, activation = "relu"))
#model.add(Dense(10, activation = "relu"))
model.add(Dense(1, activation = "exponential"))
model.compile(loss=custom_loss, optimizer='RMSProp')
return model
model = baseline_model()
model.fit(data2, np.append(y2, d, axis = 1), epochs=1, shuffle=True, verbose=1)
Снова отредактируйте:
def custom_loss3(data, y_pred):
y_true = data[:, 0]
d = data[:, 1]
# condition
loss_value = KB.switch(KB.greater(y_true, 0), 2 * d * y_pred, 2 * d * (y_true * KB.log(y_true + KB.epsilon()) - y_true * KB.log(y_pred + KB.epsilon()) - y_true + y_pred))
return loss_value