«Непередбачувана гра»? Як я за допомогою Python намагався вирахувати переможця Чемпіонату світу з футболу 2022
Багато хто називає футбол «непередбачуваною грою». Чому? Бо є безліч факторів, що можуть вплинути на рахунок.
Це так… Але лише певною мірою. Так вважає розробник та дата-саєнтист Френк Ендрейд. Він пропонує вирахувати, хто все ж таки переможе на Чемпіонаті світу з футболу 2022. Передаємо йому слово.
Важко передбачити остаточний рахунок або переможця матчу, але можна дізнатись, хто переможе у змаганні. Останні п’ять років Bayern Munich вигравав всі Бундесліги, а Manchester City виграв чотири Прем’єр-ліги. Не думаю, що це випадковість…
У середині сезону 20-21 я створив модель для передбачення переможця Прем’єр-ліги, Ла Ліги, Серії А та Бундесліги. З її допомогою я правильно назвав усіх переможців.
Цей прогноз було не так вже й важко зробити, оскільки на той момент уже відбулось 19 матчів. Зараз я запускаю ту саму модель, щоб передбачити Чемпіонат світу з футболу 2022 року.
Ось результат мого передбачення, виконаний з допомогою Python. Щоб дізнатися більше про код, перегляньте цей годинний відеоурок:
Як ми будемо прогнозувати матчі?
Є різні способи робити прогнози. Я міг би працювати з машинним навчанням та різноманітними змінними, але кілька прочитаних статей переконали мене спробувати розподіл Пуассона.
Зараз поясню, чому. Давайте почнемо з визначення розподілу Пуассона.
Розподіл Пуассона — це дискретний розподіл ймовірностей, який описує кількість подій, що відбуваються протягом фіксованого інтервалу часу або області можливостей.
Якщо ми розглядаємо гол як подію, яка може статися протягом 90 хвилин футбольного матчу, ми можемо обчислити, скільки голів ймовірно заб’є команда А і команда Б.
Нам потрібно, щоб виконувались такі умови:
- Кількість подій можна підрахувати (під час матчу можуть забити 1 або більше голів).
- Події незалежні одна від одної (те, що забили перший гол, не повинно впливати на ймовірність іншого голу).
- Швидкість, з якою відбуваються події, є постійною (ймовірність досягнення мети в певний проміжок часу має бути однаковою для будь-якого часового проміжку такої ж довжини).
- Дві події не можуть відбутися в один і той самий момент часу (не можна одночасно забити два гола).
Без сумніву, припущення 1 і 4 виконуються, але 2 і 3 — частково вірні. Проте припустімо, що припущення 2 і 3 завжди вірні.
Коли я прогнозував переможців вищих європейських ліг, я побудував гістограму кількості голів у кожному матчі за останні п’ять років для чотирьох найкращих ліг:
Якщо ви подивитеся на відповідну криву будь-якої ліги, вона виглядає як розподіл Пуассона.
Тепер можна сказати, що можна використовувати розподіл Пуассона для розрахунку ймовірності кількості голів, які можуть бути забиті в матчі.
Ось формула розподілу Пуассона.
Щоб зробити передбачення, я розглянув:
lambda: медіана голів за 90 хвилин (Команда A і B)
x: кількість голів у матчі, які можуть забити команди A та B
Щоб обчислити lambda, нам потрібні середні результати, забиті/пропущені кожною національною командою. Тому переходимо до наступного пункту.
Голи, забиті / пропущені кожною збірною
Зібравши дані з усіх матчів чемпіонату світу з 1930 по 2018 рік, я підрахував середню кількість забитих і пропущених голів кожною національною командою:
У своєму прогнозі для чотирьох найкращих європейських ліг я врахував фактор «дома/виїзд», але оскільки на Чемпіонаті світу майже всі команди грають на нейтральному стадіоні, я не враховував його для цього аналізу.
Після того, як я отримав голи, забиті / пропущені кожною національною командою, я створив функцію, яка передбачає кількість очок, яку кожна команда отримає на груповому етапі.
Прогноз групового етапу
Нижче наведено код, який я використав, щоб передбачити кількість очок, які кожна збірна отримає на груповому етапі:
def predict_points(home, away): if home in df_team_strength.index and away in df_team_strength.index: lamb_home = df_team_strength.at[home,'GoalsScored'] * df_team_strength.at[away,'GoalsConceded'] lamb_away = df_team_strength.at[away,'GoalsScored'] * df_team_strength.at[home,'GoalsConceded'] prob_home, prob_away, prob_draw = 0, 0, 0 for x in range(0,11): #number of goals home team for y in range(0, 11): #number of goals away team p = poisson.pmf(x, lamb_home) * poisson.pmf(y, lamb_away) if x == y: prob_draw += p elif x > y: prob_home += p else: prob_away += p points_home = 3 * prob_home + prob_draw points_away = 3 * prob_away + prob_draw return (points_home, points_away) else: return (0, 0)
Якщо говорити простою мовою, predict_points
обчислює, скільки очок отримають місцеві та гості-команди. Для цього я обчислив lambda для кожної команди за формулою середні_забиті_голи * середні_пропущені_голи
.
Потім я змоделював всі можливі рахунки матчу від 0–0 до 10–10. Я маю lambda та x та використовую формулу розподілу Пуассона, щоб обчислити p.
Prob_home
, prob_draw
і prob_away
накопичує значення p, якщо, скажімо, матч закінчується з рахунком 1–0 (перемога господарів), 1–1 (нічия) або 0–1 (перемога гостей) відповідно. Потім бали розраховуються за наведеною нижче формулою:
points_home = 3 * prob_home + prob_draw points_away = 3 * prob_away + prob_draw
Якщо ми використаємо predict_points
для прогнозування матчу Англія – США, ми отримаємо це:
>>> predict_points('England', 'United States') (2.2356147635326007, 0.5922397535606193)
Якщо ми застосуємо цю функцію predict_points
до всіх матчів на груповому етапі, ми отримаємо першу та другу позицію в кожній групі, отже, наступні матчі в нокаутах.
Прогнозування нокаутів
Для нокаутів мені потрібно прогнозувати не очки, а переможця кожного bracket. Ось чому я створив нову функцію get_winner
на основі попередньої функції predict_points
.
def get_winner(df_fixture_updated): for index, row in df_fixture_updated.iterrows(): home, away = row['home'], row['away'] points_home, points_away = predict_points(home, away) if points_home > points_away: winner = home else: winner = away df_fixture_updated.loc[index, 'winner'] = winner return df_fixture_updated
Простіше кажучи, якщо points_home
більше, ніж points_away
, переможцем є команда господарів, якщо ні — переможцем є команда гостей.
Завдяки функції get_winner
я можу отримати результати попередніх brackets
:
Прогнозування чвертьфіналу, півфіналу та фіналу
Якщо я знову використаю get_winner
, я зможу передбачити переможця чемпіонату світу. Я запускаю функцію ще раз, і дізнаюся, що переможцем буде… Бразилія!
Ось як я передбачив Чемпіонат світу з футболу 2022 року за допомогою Python і розподілу Пуассона. Щоб побачити повний код, перегляньте мій GitHub, а всі статті про цей проєкт можна знайти на моєму блозі Medium.
Автор: Френк Ендрейд
Примітка редакції: у п’ятницю, 9 грудня, у матчі ¼ фіналу зійшлися збірні Хорватії та Бразилії. В основний час та екстратаймах суперники не визначили найсильнішого (1:1), все вирішилося в серії пенальті, яка несподівано завершилася на користь хорватів — 4:2.
Текст адаптувала Євгенія Козловська
Favbet Tech – це ІТ-компанія зі 100% українською ДНК, що створює досконалі сервіси для iGaming і Betting з використанням передових технологій та надає доступ до них. Favbet Tech розробляє інноваційне програмне забезпечення через складну багатокомпонентну платформу, яка здатна витримувати величезні навантаження та створювати унікальний досвід для гравців.
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: