Prédire les résultats au foot

Prédiction entre Montpellier et Auxerre

Présentation du projet

Il m’est venue l’idée après le projet de prédiction des élections de prédire d’autres types de résultats, étant très intéréssé par le football de par la varitété de tactiques de jeu et de joueurs différents. Je me doutais qu’il était possible de prédire avec une précision relative des résultats de matchs.

Stratégie

Pour avoir un projet fonctionnel qui fait office de proof of concept il faut pouvoir avoir des premier résultats assez rapidement, de plus le prix des apis pour faire appel à des apis sur le football sont parfois assez chère, il était donc obligatoire pour moi de trouver un niveau de service gratuit d’utilisation. Pour obtenir des résultats rapide j’ai décidé de ma baser sur le résultat des matchs précédents afin de déterminer le résultat des matchs retours, sans prendre en compte les joueurs sur le terrain.

Collecte de données

La première étape est de récolter les données j’ai trouver Cette api qui a une politique de pricing très intéréssante afin d’avoir un dataset suffisament complet.

Persistance

Pour assurer la persistance des données récupérées via l’API, j’ai développé une application Java utilisant Spring. Cette application effectue régulièrement des requêtes à l’API concernée et enregistre les résultats des matchs dans une base de données MySQL.

Voici un extrait de code illustrant cette fonctionnalité :

public void updateMatchList() throws IOException {
		MatchApi matchApi = new MatchApi();
		LocalDate yesterday = LocalDate.now().minusDays(1);
		LocalDate today = LocalDate.now();
		List<Match> refreshedMatchList = matchApi.getMatchList(yesterday, today);
		for (Match match : refreshedMatchList) {
			Optional<Match> matchInBase = matchRepository.findObjbyLegacyid(match.getId());
			Team homeTeam = getOrCreateTeam(match.getHomeTeam().getId(), match.getHomeTeam());
			Team awayTeam = getOrCreateTeam(match.getAwayTeam().getId(), match.getAwayTeam());

			match.setHomeTeam(homeTeam);
			match.setAwayTeam(awayTeam);
			LocalDate now = LocalDate.now();
			matchInBase.ifPresentOrElse(matchinbase -> {
				if (!"FINISHED".equals(matchinbase.getStatus())) {
					match.setDate_fetched(now);
					matchRepository.delete(matchinbase);
					matchRepository.save(match);
				}
			}, () -> {
				log.info("match pas en base %d", match.getId());
				matchRepository.save(match);//
			});
		}
	}

Création du modèle

Sur un notebook Python, j’ai créé un modèle qui récupère les informations stockées dans la base de données. Ce modèle est entraîné en utilisant des techniques de machine learning pour prédire le nombre de buts marqués par chaque équipe, en se basant sur les résultats passés.

Dans cette section, je définis les variables X et Y. X représente la partie du DataFrame utilisée pour l’entraînement, tandis que Y correspond à la variable à prédire :

from sklearn.model_selection import train_test_split

X = data_encoded.drop(['nbr_goal_full_away', 'nbr_goal_full_home'], axis=1)
y_away = data_encoded['nbr_goal_full_away']
y_home = data_encoded['nbr_goal_full_home']

X_train, X_test, y_away_train, y_away_test, y_home_train, y_home_test = train_test_split(X, y_away, y_home, test_size=0.2, random_state=42)

Une fois les paramètres d’entrée définis, il est nécessaire d’utiliser un algorithme de prédiction. Dans ce cas, j’ai opté pour la Random Forest, qui a donné les meilleurs résultats dans mon étude.

from sklearn.model_selection import RandomizedSearchCV

# Définir la grille des hyperparamètres
param_grid = {
    'n_estimators': [50, 100, 200, 500],
    'max_depth': [None, 10, 20, 30],
    'min_samples_split': [2, 5, 10],
    'min_samples_leaf': [1, 2, 4],
    'max_features': ['auto', 'sqrt', 'log2']
}

rf = RandomForestRegressor(random_state=42)

rf_random_away = RandomizedSearchCV(estimator=rf, param_distributions=param_grid, n_iter=100, cv=3, verbose=2, random_state=42, n_jobs=-1)
rf_random_home = RandomizedSearchCV(estimator=rf, param_distributions=param_grid, n_iter=100, cv=3, verbose=2, random_state=42, n_jobs=-1)
# Train
rf_random_away.fit(X_train, y_away_train)
rf_random_home.fit(X_train, y_home_train)

Ce modèle est ensuite “dumpé” et un fichier dataframe.pkl est généré et récupérer avec le système d’artefacts de gitlab et ce fichier est copié sur un serveur pour ensuite être consommé afin de visualiser les résultats.

Ensuite les résultats sont consultables grâce à une application frontend qui fais la rêquete avec le nom de l’équipe tapé par l’utilisateur.

Le site est consultable à cette addresse en http.

Martin Généreux
Martin Généreux
Développeur d’application, DevOps, IA