Любители футбола во всем мире убеждены, что могут точно предсказывать результаты футбольных матчей. Они даже «знают», какая команда станет чемпионом лиги или турнира. Эти спортивные фанатики делают это либо потому, что любят «красивую игру», либо для того, чтобы доказать друзьям свои знания в области футбола, получить прибыль от ставок на спорт и/или всего вышеперечисленного. Однако футбол непредсказуем с черными лошадками (командными разоблачениями) и беспрецедентными происшествиями. Английская премьер-лига, первый дивизион системы английских футбольных лиг, является примером этого непредвиденного явления. Например, «Лестер Сити» выиграл лигу 2015–2016 гг., несмотря на то, что всего двумя годами ранее был переведен в Премьер-лигу, в то время как «Ливерпуль» не смог выиграть Премьер-лигу в сезоне 2018–2019 гг., Несмотря на то, что закончил сезон с 97 очками (3-е место за всю историю). позади коронации «Манчестер Сити» с 98 очками в том году и исторического чемпионского титула «Манчестер Сити» в 2017–2018 годах с 100 очками). По этой причине я решил обучить нейронную сеть, используя результаты матчей предыдущих сезонов, для прогнозирования турнирной таблицы Премьер-лиги на следующий год.

Футбол

Однако, прежде чем продолжить, нам нужно глубже понять этот вид спорта и пояснить, что, когда я говорю «футбол», я имею в виду то, что мир знает как футбол, а не футбол, как он (загадочно) известен в Соединенных Штатах. Спорт состоит из двух команд с 10 полевыми игроками и одним вратарем. Результат матча определяется количеством голов, забитых командой, когда мяч пересек линию ворот, которую защищает соперник. Игра состоит из двух таймов по 45 минут каждый и смены сторон в перерыве между таймами. Окончательный результат определяется окончательным счетом, указывающим на победу, поражение или ничью команды. Тем не менее, если игра представляет собой матч на выбывание или финал турнира, то есть дополнительное время и/или пенальти, чтобы разрешить ничью, но это не относится к Премьер-лиге, где разрешены ничьи, и, следовательно, нет необходимости учитывать выбывание. крепления в нашей модели.

Премьер-лига

В таблице турнирной таблицы Премьер-лиги команда-победитель получает 3 очка, 1 за ничью и 0 за поражение, чтобы отсортировать 20 команд, участвующих в соревновании. Всего за сезон проводится 38 матчей, в которых каждая команда играет по два раза дома и на выезде. Согласно регламенту Премьер-лиги, таблица Премьер-лиги разбивает очки по разнице мячей (общее количество забитых голов минус общее количество пропущенных голов в сезоне). команды, и в маловероятном случае, если все еще есть ничья, командам присуждается одинаковая позиция в таблице. Команда, занявшая первое место, становится чемпионом лиги, в то время как три худшие команды переходят в низшую лигу, а их вакантное место заполняется тремя командами, перешедшими из Чемпионшипа, второго дивизиона системы английской футбольной лиги. Если интересно, дополнительную информацию можно найти на https://www.premierleague.com/premier-league-explained, но мы уже рассмотрели основы, необходимые для понимания этого проекта.

Данные

Я использовал data.world, чтобы получить результаты матчей Премьер-лиги за 2015–2016, 2016–2017, 2017–2018 и 2018–2019 годы. Ниже приведена безопасная ссылка для скачивания CSV-файла 2017–2018 гг.: https://query.data.world/s/wxbeoargbmtyy7t3s3xw5tksxxggcj. Файл был отсортирован в хронологическом порядке и содержал много информации, но меня интересовали только столбцы HomeTeam, AwayTeam, FTHG (забитые домашние голы), FTAG (забитые голы на выезде) и FTR (результаты за основное время), потому что не было необходимости например, знать, кто был судьей, или количество домашних красных карточек.

Результат основного времени определялся путем сравнения голов, забитых дома за полное время, с голами, забитыми за полное время на выезде, что указывало на победу дома (H), победу на выезде (A) или ничью (D). Затем я использовал эти данные для воспроизведения таблицы Премьер-лиги за соответствующий сезон, также подсчитав общее количество забитых и пропущенных голов.

Предварительная обработка

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

Архитектура нейронной сети

Я решил использовать простую нейронную сеть с прямой связью с 8 входами и 2 выходами. 8 входных данных представляют собой среднее количество забитых/пропущенных голов, предыдущую позицию и процент побед дома/в гостях, в зависимости от местоположения, для каждой команды. 2 результата представляли голы, забитые хозяевами и гостями. Однако, учитывая тот факт, что в предыдущем сезоне были вновь продвинутые команды без позиции, я решил назначить случайное целое число от 20 до 30 в качестве предыдущей позиции, чтобы подчеркнуть, что команда не входила в число 20 команд в предыдущего сезона, но также допускает вариативность, поэтому нейронная сеть не обрабатывает эти команды одинаково. Кроме того, для среднего количества забитых/пропущенных голов и показателей побед дома/в гостях этих недавно повышенных команд я решил использовать среднее значение результатов последних 10 команд в предыдущем сезоне, чтобы учесть вариативность, но также усилить обобщение, которое недавно повысили. Команды, как правило, испытывают трудности в первый год своего пребывания в Премьер-лиге.

Я решил иметь 3 скрытых слоя по мере перехода от входного к выходному слою. Я понял, что моя модель работала лучше, когда я увеличивал количество скрытых слоев, но после 3 скрытых слоев я не видел каких-либо серьезных улучшений в своих прогнозах, потому что лучшие 6 команд, как правило, соответствовали фактическому положению, а также последние 5 команды. Поэтому я просто уменьшил количество единиц для Dense(), которое представляло умножение матрицы на вектор для обучения нейронной сети, наполовину, пока не достиг выходного слоя из 2 единиц.

x_train = get_x_train(match_results_16_17, input_data_15_16, input_data_15_16.tail(10))
y_train = match_results_16_17.drop(['HomeTeam', 'AwayTeam'], axis =1)
display(x_train)

# get number of columns in training data
n_cols = x_train.shape[1]

model = Sequential([ 
    Dense(32, input_shape=(n_cols,)), 
    Dense(16),
    Dense(8),
    Dense(4),
    # we want team goals scored for the match
    Dense(2) 
])

Я продолжил использовать «адам» в качестве своего оптимизатора, чтобы контролировать скорость обучения моей модели, поскольку были рассчитаны оптимальные веса для модели. Я решил использовать оптимизатор adam, учитывая, что это, как правило, хороший оптимизатор для многих целей, а также потому, что прогнозирование Премьер-лиги не имеет каких-либо особых функций, которые могли бы значительно выиграть от другого оптимизатора. Я использовал стандартную функцию потерь для задач регрессии, учитывая, что мои выходные данные должны были представлять счет матча, поэтому бинарная и многоклассовая классификация не имеет смысла использовать в этом случае. Я также включил раннюю остановку, чтобы модель прекращала обучение, если она больше не улучшалась. Кроме того, как только нейронная сеть была скомпилирована, я обучил модель, пытаясь предсказать результаты матчей 2016–2017 годов, используя данные за 2015–2016 годы (показатели побед дома/в гостях, среднее количество забитых/пропущенных голов, результаты предыдущих лиг). Затем я последовательно вызывал model.fit для постепенного обучения модели, чтобы иметь обученную нейронную сеть для прогнозирования результатов в лиге 2018–2019 годов.

# compile model using mean_squared_error as a measure of model performance
model.compile(optimizer='adam', loss='mean_squared_error')

# set early stopping monitor so the model stops training when it won't improve anymore
early_stopping_monitor = EarlyStopping(patience=3)

# train model with 2016-2017 results
model.fit(x_train, y_train, validation_split=0.2, epochs=30, callbacks=[early_stopping_monitor])

# also train model with 2017-2018 results
x_train = get_x_train(match_results_17_18, input_data_16_17, input_data_16_17.tail(10))
y_train = match_results_17_18.drop(['HomeTeam', 'AwayTeam'], axis =1)
model.fit(x_train, y_train, validation_split=0.2, epochs=30, callbacks=[early_stopping_monitor])

x_test = get_x_train(match_results_18_19, input_data_17_18, input_data_17_18.tail(10))
y_test_predictions = model.predict(x_test)

Прогнозы

Моя модель в целом хорошо справлялась с предсказанием порядка команд, например, «Манчестер Сити» занял первое место, а «Ливерпуль» — второе, как это и произошло на самом деле. Это была та часть, которая меня больше всего интересовала, учитывая, что я знал, что будет очень сложно добиться высокой точности очков и разницы мячей. Тем не менее, я обнаружил, что моя модель была особенно жесткой с новыми командами («Вулверхэмптоном», «Кардиффом» и «Фулхэмом»), но я не был расстроен этим выступлением, потому что «Кардифф» и «Фулхэм» на самом деле вылетели в низшую лигу, а «Вулверхэмптон» стал откровением в том сезоне.

Также из любопытства я решил спрогнозировать турнирную таблицу этого сезона. Я исправил/модифицировал базу данных (в 5-м туре неправильно было Саутгемптон против Эвертона, когда игра должна была быть Борнмут против Эвертона, https://soccersoda.com/soccer-leagues-fixtures/#C4), включая все матчи лиги за сезон 2019–2020 гг. и еще раз использовал model.fit, чтобы моя модель теперь могла включать сезон 2018–2019 гг. Тем не менее, сезон этого года стал большим сюрпризом, учитывая нынешнее преимущество Ливерпуля над Манчестер Сити, занявшим второе место. Лига была приостановлена ​​из-за текущей пандемии и, следовательно, может возобновиться, а может и не возобновиться. В результате мы можем знать или не знать, насколько хороша моя модель, однако она не предсказала такой большой разрыв между командой, занявшей первое место, и остальной частью лиги, что является примером того, почему так сложно делать прогнозы в футболе.

Отражение

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