Простой подход регрессии Пуассона для прогнозирования результатов футбольных матчей с точностью 70%.

Что ожидать?

  • В этой статье я расскажу вам, как прогнозировать результаты футбольных матчей с помощью двух регрессий Пуассона с одной прогностической переменной с точностью более 70%. Это впечатляет, если учесть, что мы используем очень простую модель и только одну прогнозирующую переменную (рейтинг команды FIFA).
  • Регрессия Пуассона будет сравниваться с базовой линейной регрессией и регрессией случайного леса.
  • Вы узнаете, почему регрессия Пуассона является хорошим инструментом для этой задачи.
  • Мы будем искать способы повысить точность / оценку f1 прогнозируемых результатов с помощью специального этапа постобработки.

Данные

Этот метод использует два набора данных, которые можно найти на Kaggle:

Обучение разделению тестовых данных и разработке функций

При создании наших данных тренировок я рассматривал матчи только после 2019 года (так как более старые, возможно, больше не отражают текущие результаты команд), а затем объединял результаты матчей с рейтингом ФИФА для каждого команда.

И последнее, но не менее важное, я создал новую переменную «rank_diff», которая представляет собой разницу в рейтинге ФИФА между домашней и гостевой командами. Позже эта переменная будет нашей единственной прогнозной переменной для наших моделей.

Мои тестовые данные включают все до сих пор матчи группового этапа Евро-2020.

Обратите внимание: чтобы сделать эту статью более читаемой, я пропускаю большую часть кода. Однако, если вас интересует сквозной конвейер, посетите мой GitHub.

Вот как выглядят данные обучения после короткой предварительной обработки (обратите внимание на объединенные столбцы рейтинга рейтинга FIFA и недавно созданный столбец rank_diff):

date home_team away_team home_score away_score tournament home_team_ranking away_team_ranking ranking_diff

2019–01–08 Finland Sweden 1 0 Friendly 1410 1569 -159
2019–01–11 Estonia Finland 2 1 Friendly 1161 1410 -249
2019–01–11 Iceland Sweden 2 2 Friendly 1415 1569 -154
2019–03–20 Germany Serbia 1 1 Friendly 1609 1512 97
2019–03–20 Wales Trinidad and Tobago 1 0 Friendly 1570 1201 369
2019–03–21 Kosovo Denmark 2 2 Friendly 1151 1631 -480
...

Исследовательский анализ данных

Давайте изучим данные Kaggle и посмотрим на забитые голы:

Графики выше на Рисунке 1 дают некоторое представление о данных:

  • Слева мы видим график, который показывает, сколько голов забила команда хозяев поля за матч. Среднее значение за матч составляет 1,8 гола (красная линия), а максимальное количество голов, забитых командой хозяев поля - 9!
  • Посередине мы видим такую ​​же визуализацию для команд на выезде. Мы видим, что среднее количество голов, забитых командой гостей, ниже и составляет всего 1,2 гола за матч. Максимальное количество голов за матч - 7 (что опять же меньше по сравнению с 9 головами хозяев поля). Таким образом, мы можем ясно видеть, что существует довольно существенная разница в количестве забитых голов в зависимости от того, играла ли команда дома или на выезде.
  • Справа мы можем видеть соотношение забитых голов домашней командой (ось Y) и разницы в рейтингах FIFA конкурирующих команд (ось X). В нижнем левом углу графика мы видим, что если разница в рейтинге ФИФА сильно отрицательна (команда хозяев имеет гораздо более низкий рейтинг ФИФА, чем команда гостей), голы, забитые командой хозяев, очень низкие (0–1 гол). . Если команда является настоящим аутсайдером (по показателям ФИФА), то вряд ли она забьет больше 2 голов! С другой стороны, если разница в рейтинге ФИФА обеих команд имеет большое положительное значение (домашняя команда имеет гораздо более высокий рейтинг ФИФА, чем команда гостей), то среднее количество забитых голов будет очень высоким. Гораздо более сильная домашняя команда на самом деле никогда не забивает меньше 2 голов и потенциально может забивать больше 7+ (например, Испания против Сан-Марино).

Метод

Из графиков на Рисунке 1 выше мы можем вывести два важных сообщения из наших данных:

  1. Существует существенная взаимосвязь между разницей в рейтингах ФИФА между двумя соревнующимися командами и количеством забитых мячей!
  2. Тот факт, что команда играет дома или на выезде, сильно влияет на количество забитых мячей. Хозяева забивают в среднем 1,8 гола, а команда гостей забивает в среднем лишь 1,2 гола.

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

Когда использовать Пуассон?

Литература предполагает, что использование регрессии Пуассона для этой цели - лучший способ. Но что такое регрессия Пуассона и почему бы просто не использовать линейную регрессию или другой метод, например, метод регрессии случайного леса?

  • Вообще говоря, регрессия Пуассона используется, когда мы прогнозируем количество на единицу времени или пространства. Например, забитые голы за игру! Поскольку количество не может быть отрицательным, минимальное значение модели Пуассона - ноль (невозможно забить меньше нуля голов!), Теоретически максимальное значение неограничено - хотя редко бывает, что команда забивает больше 5 голов :)
  • Давайте снова посмотрим на рисунок 1 (слева). Как и многие другие распределения Пуассона, это распределение имеет наклон вправо. Это явно не означает, что количество голов, забитых за игру, распределяется нормально. Однако предположения о нормальном распределении являются ключевым предположением для линейной регрессии!

Проблема с линейной регрессией

  • Простая модель линейной регрессии представлена ​​прямой линией, и это определенно дает отрицательные значения для определенных комбинаций переменных (например, отрицательного количества голов). В нашем случае использования, например, когда у нас очень слабая команда (низкий рейтинг FIFA), которая играет против очень сильной команды (высокий рейтинг FIFA), может случиться так, что модель линейной регрессии будет предсказывать отрицательный результат для более слабой команды (для пример -2,4 гола). Это определенно то, чего мы хотим избежать.
  • Кроме того, предположение о равной дисперсии (нормальное распределение) линейных регрессий нарушается нашими данными! Вы можете видеть на правом графике выше, что, когда разница в рейтинге ФИФА становится более положительной, дисперсия забитых голов также увеличивается! Следующее изображение еще раз резюмирует это графически:

1. График на Рисунке 2, отображающий линейную модель, изображен слева. Он показывает, что для каждого значения X ответы y приблизительно нормально распределены. График справа показывает, как выглядит модель Пуассона. Для каждого значения X ответы y подчиняются распределению Пуассона: для регрессии Пуассона небольшие значения X связаны с распределением, которое заметно искажено из-за большого количества маленьких значений и только нескольких больших. По мере увеличения X распределение ответов начинает все больше и больше походить на нормальное распределение.

2. В линейной модели (слева) изменение Y при каждом значении X одинаково. Для регрессии Пуассона ответы на каждом уровне X становятся более вариабельными с увеличением средних.

3. В случае линейной регрессии средние отклики для каждого значения X попадают в линию. В случае регрессии Пуассона средние значения Y при каждом значении X попадают на кривую, а не на линию.

адаптировано из книги За пределами множественной линейной регрессии Пола Робака и Джули Леглер

Сравнение моделей

В этом разделе мы немного подробнее рассмотрим часть прогнозирования, связанную с моделированием, и сравним модель Пуассона с линейной моделью и более мощной регрессией случайного леса.

Установочные модели

Теперь мы готовы настроить модели. В этом упражнении я использовал новый пакет tidymodels и использовал 30-кратную перекрестную проверку для сравнения:

library(tidymodels)
library(parsnip)
library(poissonreg)
pois_mod <-  poisson_reg() %>%  set_engine("glm")
lin_mod  <-  linear_reg() %>% set_engine("lm")
rf_mod   <-  rand_forest(trees=100) %>% 
             set_engine("randomForest") %>% 
             set_mode("regression")
folds <- vfold_cv(data, v = 30)

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

home_score_formula <- formula(“home_score ~ ranking_diff”)
away_score_formula <- formula(“away_score ~ ranking_diff”)

Вот пример кода для регрессии Пуассона:

#poisson model workflow set up for predicting home scores
pois_mod_hs_wf <- 
  workflow() %>%
  add_model(pois_mod) %>%
  add_formula(home_score_formula)
#perform cross validation
pois_mod_hs_rs <- 
  pois_mod_hs_wf %>% 
  fit_resamples(folds)
...
#collect cv scores
collect_metrics(pois_mod_hs_rs)
collect_metrics(lin_mod_hs_rs)
collect_metrics(rf_mod_hs_rs)

Результаты перекрестной проверки

Результаты перекрестной проверки интересны и показывают (путем сравнения среднеквадратичной ошибки (RMSE)), что регрессия случайного леса превосходит как линейную регрессию, так и обсуждаемую регрессию Пуассона !!

CV-RMSE Poisson Regression 1.30
CV-RMSE Linear Regression 1.34
CV-RMSE Random Forest Regression 1.17

Визуальное сравнение моделей

Но подождите, действительно ли RMSE - лучший способ сравнить модели здесь? В этом потоке с перекрестной проверкой есть хороший и подробный ответ о том, как выбрать показатели производительности для регрессии Пуассона, в котором более подробно рассматривается эта тема. Поскольку здесь слишком много деталей, я решил визуально осмотреть модели на диаграмме рассеяния и проверить так называемый внешний вид моделей:

Глядя на модели визуально, мы видим, что линейная модель (зеленая) явно не соответствует данным и совсем не способна уловить кривизну. Модель случайного леса (синяя), однако, показывает беспокойную зигзагообразную линию, которая перекрывает наши данные и, вероятно, не будет хорошо обобщаться на новых данных. Наконец, модель Пуассона (красная), кажется, очень удовлетворительно отражает тенденцию и кривизну данных! Таким образом, «внешний вид» ясно говорит: «Используйте модель Пуассона!».

От оценки целей к прогнозированию результата (победа, поражение, ничья)

Подведем итоги того, что у нас есть: две регрессионные модели, которые предсказывают голы домашней и гостевой команд.

Но как на самом деле «предсказать», какая команда выиграла дуэль?

Мы не можем просто сравнить цели домашней и гостевой команд и назначить победителем команду с большим числом. Почему? Поскольку, поскольку наши прогнозы представляют собой числа с плавающей запятой, мы, по сути, никогда не закончим прогнозом ничьей: Представьте, что прогноз для целей команды A равен 1,1, а прогноз для целей команды B равен 1,09. С помощью этого простого метода, описанного выше, мы назначим команду A победителем, даже если у обеих команд очень похожие прогнозы!

1. Простой подход - сравните округленное прогнозируемое количество голов за матч.

Самый простой выход - просто округлить результаты до ближайшего целого числа, а затем сравнить эти числа. В R это можно сделать следующим образом:

pred_result <- rep(0, length(nrow(data)))
#home_score_pred contains the poisson home goal predictions for each match
#away_score_pred contains the poisson away goal predictions for each match
#assign home team win 0
pred_result[round(home_score_pred) > round(away_score_pred)]  <- 0 
#assign away team win 1 
pred_result[round(home_score_pred) < round(away_score_pred)]  <- 1
#assign draw 2
pred_result[round(home_score_pred) == round(away_score_pred)] <- 2

Если мы подумаем о нашем примере выше, то с помощью этого метода Команде A (1.1) и Команде B (1.09) будет назначен по 1 голу каждой, и, следовательно, матч будет классифицирован как ничья, что кажется более правдоподобным.

Вот матрица путаницы для наших обучающих данных с использованием этого простого подхода округления и сравнения:

На Рисунке 4 видно, что прогнозы на победу домашней команды довольно хороши: 167 из 217 (167 + 9 + 41) были предсказаны правильно. Точность прогнозирования победы команды гостей по-прежнему довольно высока, наши модели в сочетании с нашим подходом округления, однако, действительно, похоже, не могут правильно прогнозировать ничьи.

В целом точность для обучающей выборки составляет 65% с взвешенной оценкой F-1, равной 67%.

2. Более комплексный подход к тому, как лучше классифицировать результаты матчей.

Выше мы могли видеть, что округление прогнозируемых результатов команд с последующим их простым сравнением дает точность 65%. Но можно ли получить лучший результат при другом подходе? Давайте рассмотрим другой пример:

Представьте, что прогнозируемые голы команды A составляют 1,49, а прогнозируемые голы команды B - 1,51. В приведенном выше примере округления оценка команды A будет округлена до 1, а оценка команды B будет округлена до 2, и поэтому команда B будет объявлена ​​победителем. Но не лучше ли в этом случае предсказать ничью, ведь прогнозы обеих команд настолько близки друг к другу? Ну да! Но как выбрать правильный порог разницы в том, как далеко должны быть друг от друга прогнозы голов, чтобы одна команда могла быть объявлена ​​победителем или проигравшей?

Таким образом, классификация исходов игр (победа, поражение, ничья) меняется на следующую:

predicted_result <- rep(NA, length(pois_hs_res))
#home_score_pred contains the poisson home goal predictions for each match
#away_score_pred contains the poisson away goal predictions for each match
#assign home team win 0
predicted_result[home_score_pred > away_score_pred+diff] <- 0
#assign home away win 1
predicted_result[home_score_pred < awy_score_pred-diff] <- 1
#assign draw 2
predicted_result[!(home_score_pred > away_score_pred+diff) & !(home_score_pred < away_score_pred-diff)] <- 2

По сути, мы ищем способ максимизировать показатель точности нашей классификации результатов игры на основе порогового значения разницы в головах:

После того, как мы выберем показатель, скажем «Взвешенный F1-балл» или «Точность», мы можем просто запустить приведенное выше назначение результата для серии пороговых значений разницы мячей и посмотреть, какой порог дает лучший F1-балл. Давайте сделаем это!

На рисунке 5 выше показано, что F1-баллы нашей классификации матчей (победа, поражение, ничья) сильно различаются в зависимости от выбранного нами порогового значения разницы. Первоначально F1-Scores начинают увеличиваться почти до 70% с порогом разницы 0,41. После этого F1-баллы снова начинают неуклонно снижаться и достигают минимума в правой части графика.

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

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

В целом, точность и F1-оценка подскочили примерно с 65% до сейчас 69%!

Прогноз матчей Евро-2020

Хватит скучной обработки данных и моделирования! Давайте наконец воспользуемся нашим методом для прогноза исходов первых матчей группового этапа Евро-2020:

Вы можете видеть, что с помощью простого метода мы достигли точности 72% и взвешенного F1-балла 71% на тестовой выборке. 13 из 18 матчей были предсказаны верно! Большинство дуэлей было предсказано правильно, и, честно говоря, кто ожидал, что Дания так хорошо выступит в этом чемпионате, а Испания сыграет вничью со Швецией? :)

Обратите внимание на следующее: зависимость хозяев и гостей от забитых голов имеет смысл только тогда, когда игровая площадка не нейтральна. Однако во время чемпионата Европы большинство игровых площадок нейтральны, и поэтому было бы более уместно предсказать результаты обеих команд по единой модели, которая не учитывает команды гостей и хозяев.

Резюме

Это было подробное пошаговое руководство о том, как прогнозировать футбольные результаты и результаты с помощью простой регрессии Пуассона, просто используя одну прогностическую переменную (различия в рейтинге ФИФА между конкурирующими командами). В целом мы достигли точности 72%. Однако есть еще много возможностей для улучшения! Мы могли бы, например, использовать больше функций в качестве входных данных для модели, таких как количество голов, забитых каждой командой в последних двух играх, в качестве индикатора последних результатов!

Если вам интересно узнать больше по этой теме или вы хотите, чтобы прогнозы на предстоящие игры впечатлили ваших друзей, напишите мне комментарий! :)

Если вас интересует полный код, посетите мой GitHub.