Вероятность выигрыша (WP) - это вероятность выигрыша (да) - с учетом определенного контекста (или предшествующего знания, говоря языком статистики). Этот контекст решает все. Например, игроки, делающие ставки, обычно имеют некоторое представление о вероятности выигрыша в предстоящей игре, основываясь на своих предварительных знаниях о сильных и слабых сторонах двух команд в целом и контексте конкретной игры. Это домашняя игра? У игроков выходной день или прощальная неделя? Звездный игрок травмирован?

Вероятность выигрыша в игре - как следует из названия - дополнительно моделирует контекст факторов, влияющих на каждый момент во время хода игры. Это может быть полезно не только для ставок на спорт, но и для болельщиков, которые хотят более активно взаимодействовать со своими командами. Хотя WP можно смоделировать для любого вида спорта, в этом посте я собираюсь сосредоточиться на баскетболе, в частности, на студенческом баскетболе мужского дивизиона I, для которого у меня есть соответствующая база данных игр, которую я начал собирать в этом сезоне. Вот пример того, как выглядит набор данных:

Каждая строка здесь представляет собой момент времени во время игры NCAA, когда произошло событие, изменившее счет или время на часах - попытка броска с игры, отскок, передача и т. Д. Соответствующими функциями для модели, описанной здесь, будут лидерство (домашний рейтинг - оценка посетителя), чистый рейтинг, который представляет собой просто разницу в рейтингах кенпом между двумя командами (дома - посетитель), и время Осталось в игре секунды. Целевая переменная - та, которую мы пытаемся предсказать с помощью нашей модели - это, конечно, результат победа, независимо от того, выиграла ли (1) или проиграла (0) команда хозяев в игре в соответствии с нормативными требованиями. Обратите внимание, что для текущей модели я просто выбрал игры, которые не закончились ничьей - я займусь ничьей… в конечном итоге. Это был просто выбор, который я пока сделал, чтобы упростить и заставить все работать быстро. Еще одно упрощение заключалось в том, чтобы исключить контекст владения мячом - какая команда владеет мячом, что, очевидно, важно знать очень поздно в игре, когда время идет к концу.

Предыдущие модели вероятности победы в баскетболе (и других видах спорта, насколько я могу судить) в основном полагались на ту или иную форму локальной логистической регрессии (здесь и здесь). Я на самом деле пробовал провести чистую логистическую регрессию, и, конечно же, это вообще не сработало. Когда я прочитал, что люди раньше шли по маршруту местной логистической регрессии, часть меня подумала: ну, нет никакого удовольствия делать именно то, что делали раньше! Когда я начал думать об этом, я подумал, может ли нейронная сеть определить тот же тип местности и нелинейности, которые необходимы для моделирования вероятности выигрыша. Как оказалось, я думаю, что ответ на этот вопрос - по крайней мере до некоторой степени однозначный да.

Чтобы помочь мне в этом путешествии, я во многом полагался на одну из цифр из сообщения в блоге Майка Бойя (пожалуйста, прочтите его и подпишитесь на него @ inpredict в Twitter), который показывает вероятность победы (для игр НБА) для команды. опережает на 3 очка, что является либо 5-очковым фаворитом, либо проигравшим в зависимости от времени в течение игры. Сплошные линии представляют собой модель, а точки представляют собой вероятности выигрыша с разделением на интервалы для фактических результатов игры.

Моя цель состояла в том, чтобы построить модель, которая могла бы воспроизвести что-то подобное. Однако перед этим давайте посмотрим, насколько похожи данные NCAA.

Из рисунка видно - если прищуриться - что приблизительные вероятности выигрыша на самом деле не слишком отличаются от данных Майка. Следует отметить, что время на моих графиках идет «вспять» - 0 - это зуммер в конце игры. Хорошо, теперь перейдем к моей модели.

Следует упомянуть, что я пробовал несколько разных вещей, в том числе своего рода «экспоненциальную трансформацию» времени, которая выглядела так:

Как оказалось, мне просто нужно было следовать мантре глубокого обучения, которая заключается в том, чтобы позволить нейронной сети изучить необходимые функции. Поэтому я отказался от преобразования времени и просто сделал свою нейронную сеть на один уровень глубже, и это, похоже, помогло.

В TensorFlow 2.0 простая модель AF на самом деле такова:

model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(12, activation='relu', input_shape=[3,]),
    tf.keras.layers.Dense(12, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer=tf.keras.optimizers.RMSprop(1e-3), loss='binary_crossentropy', metrics=['accuracy', 'AUC'])
model.summary()
model.fit(df[['lead','net','time']].to_numpy(),
          df['win'].to_numpy(),
          verbose=1,
          shuffle=True,
          epochs=50,
          batch_size=512)

Вот и все, только входной слой, 2 скрытых слоя по 12 нейронов в каждом и выходной слой с сигмовидной активацией. И это в основном работает, как вы можете видеть здесь, для команды с преимуществом в 3 очка, которая является либо фаворитом на 5 очков, либо собакой с точки зрения чистого рейтинга:

times = list(range(0,2400,30))
winp_favorite = [model.predict_proba(x=[[3,5,time]])[0][0] for time in times]
winp_underdog = [model.predict_proba(x=[[3,-5,time]])[0][0] for time in times]
plt.plot(times, winp_favorite, 'b-')
plt.plot(times, winp_underdog, 'r-')
plt.title('NCAA Win Probability')
plt.xlabel('Time elapsed (s)')
plt.savefig('ncaa_win_prob.png')

Кстати, если у вас есть только 1 скрытый слой, вы можете получить такие кривые, которые выглядят шатко:

Наконец, чтобы показать вам, как эти функции работают индивидуально, здесь представлены вероятности победы для команды с чистым рейтингом +5 и оставшимися 30 секундами на часах с отрывом от 1 до 5 очков:

model.predict_proba(x=[[1, 5, 30], [2, 5, 30], [3, 5, 30], [4, 5, 30], [5, 5, 30]])
>
array([[0.7975986 ],
       [0.8999447 ],
       [0.95134   ],
       [0.978909  ],
       [0.99045944]], dtype=float32)

Как и ожидалось, вероятность победы резко возрастает с несколькими дополнительными очками, так как команде, которая его отстает, становится очень сложно получить несколько владений за такое короткое время. Наконец, мы видим, что вероятность победы команды с отрывом в 4 очка за 30 секунд до конца практически не зависит от чистого рейтинга (как показал Люк Бенц):

# varying net rating from -5 to +5
model.predict_proba(x=[[4, -5, 30], [4, 0, 30], [4, 5, 30]])
>
array([[0.94858927],
       [0.97111243],
       [0.978909  ]], dtype=float32)

Я рад, что это вообще работает, хотя, думаю, в этом нет ничего удивительного. Но я хотел поделиться этим с надеждой, что другие люди также могут пойти по этому пути и добавить больше функций, улучшенные архитектуры и т. Д. Как я сказал ранее, следующим очевидным шагом будет добавление владения мячом в качестве дополнительной функции. Удачи!