@Alex R equation in Keras,
def splitter(y_true):
payoffs = y_true[:, 1]
payoffs = K.expand_dims(payoffs, 1)
y_true = y_true[:, 0]
y_true = K.expand_dims(y_true, 1)
return y_true, payoffs
def custom_odds_loss(y_true, y_pred):
y_true, payoffs = splitter(y_true)
# https://github.com/tensorflow/tensorflow/blob/v2.3.1/tensorflow/python/keras/backend.py#L4826
y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon())
term_0 = K.sum((1 - y_true) * K.abs(payoffs) * (1 - y_pred), axis=1) # Cancels out when target is 1
term_1 = K.sum(y_true * K.abs(payoffs) * y_pred, axis=1) # Cancels out when target is 0
return K.square(K.abs(K.max(payoffs) - term_1 - term_0))
My variation to the above equation,
Useful if every batch resembles an independent event of observations and that the designated payoff is one observation per batch
def custom_odds_loss(y_true, y_pred):
"""
K.max(payoffs * y_true) - ... ensures higher penalty where the **winner** observation has higher payoff
"""
y_true, payoffs = splitter(y_true)
# https://github.com/tensorflow/tensorflow/blob/v2.3.1/tensorflow/python/keras/backend.py#L4826
y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon())
term_0 = K.sum((1 - y_true) * K.abs(payoffs) * (1 - y_pred), axis=1) # Cancels out when target is 1
term_1 = K.sum(y_true * K.abs(payoffs) * y_pred, axis=1) # Cancels out when target is 0
return K.square(K.abs(K.max(payoffs * y_true) - term_1 - term_0))