admin管理员组

文章数量:1125955

I am currently developing a Keras model that can more accurately predict the outcomes of Australian horse races.

The current loss function incorporates a Brier skill score and is consistently more accurate than the bookmakers' predictions by ~2.5%.

In Australian races, there will be a maximum of 24 runners, with the odds in decimal format. y_true has been manipulated to include decimal odds, positive for a win, and negative for a loss. Where there are less than 24 runners, it is represented by a -1.0:

# example with 8 runners, max 12. horse with $9.5 odds wins:
y_true: [-1.0, -5.5, -51.0, -1.0, 9.5, -2.5, -6.5, -31.0, -1.0, -27.0, -8.0, -1.0]

The full loss function with the above example is:

def brier_loss(y_true, y_pred):
    # split out odds
    odds = tf.where(tf.less(y_true, 0.0), tf.multiply(y_true, -1.0), y_true)
    # odds = [1.0, 5.5, 51.0, 1.0, 9.5, 2.5, 6.5, 31.0, 1.0, 27.0, 8.0, 1.0]
    odds = tf.where(tf.equal(odds, 1.0), 0.0, odds)
    # odds = [0.0, 5.5, 51.0, 0.0, 9.5, 2.5, 6.5, 31.0, 0.0, 27.0, 8.0, 0.0]
    y_true = tf.where(tf.greater(y_true, 0.0), 1.0, 0.0)
    # y_true = [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
    
    num_runners = tf.reduce_sum(tf.cast(tf.greater(odds, 0.0), dtype=tf.float32))
    # num_runners = 8.0
    # implied probability from odds = (1 / decimal_odds)
    brier_score = tf.where(tf.greater(odds, 0.0), tf.square(tf.subtract(y_pred, y_true)), 0.0)
    brier_score = tf.divide(tf.reduce_sum(brier_score), num_runners)

    bookie_skill_score = tf.where(tf.greater(odds, 0.0), tf.square(tf.subtract(tf.divide(1.0, odds), y_true)), 0.0)
    bookie_skill_score = tf.divide(tf.reduce_sum(bookie_skill_score), num_runners)

    # predictions compared to bookies
    loss = tf.subtract(1.0, tf.divide(brier_score, bookie_skill_score))
    
    return -loss

It is possible to calculate the implied probability from the bookmakers by calculating (1 / odds), and y_pred gives the probability from the model. The sum of the implied odds will (almost always) be slightly greater than 1 (~1.05) to account for the track take, while y_pred will always sum to 1.

The betting strategy is to bet on horses that have a positive expected value ev = ((y_pred * (odds - 1)) - (1 - y_pred)), though I am looking to change the loss function to one that incorporates profit. I have implemented the top answer from this SO question, though its' performance is low with my model.

Is there a way to incorporate profit into a loss function given the current variables?

本文标签: neural networkKeras loss function for horse racingprofitabilityStack Overflow