Nous chargeons Infer.NET pour implementer le système TrueSkill, developpe par Microsoft Research pour Xbox Live. Ce système de classement bayesien estime les competences des joueurs a partir des résultats de matchs, tout en quantifiant l’incertitude sur ces estimations.
Chargement du helper de visualisation des graphes de facteurs.
// Chargement du helper pour visualiser les graphes de facteurs#load "FactorGraphHelper.cs"Console.WriteLine("FactorGraphHelper charge. Graphviz disponible : "+ FactorGraphHelper.IsGraphvizAvailable());
Infer.NET est maintenant charge avec tous les namespaces necessaires pour la programmation probabiliste. Les principaux composants utilises dans ce notebook :
Namespace
Usage
Microsoft.ML.Probabilistic.Distributions
Gaussiennes pour modeliser les skills
Microsoft.ML.Probabilistic.Models
Variables et contraintes du modèle
Microsoft.ML.Probabilistic.Algorithms
Expectation Propagation (EP)
Note technique : TrueSkill utilise l’algorithme Expectation Propagation car les facteurs de comparaison (perf1 > perf2) ne sont pas conjugues avec les Gaussiennes. EP approxime ces facteurs par des Gaussiennes, permettant une inference efficace.
2. Introduction a TrueSkill
Contexte
TrueSkill est le système de classement developpe par Microsoft Research pour Xbox Live. Il est une generalisation bayesienne du système Elo.
Principe
Chaque joueur a un skill (competence) modelise par une distribution Gaussienne : - Moyenne (mu) : estimation du skill - Variance (sigma^2) : incertitude sur cette estimation
Note historique : TrueSkill a ete developpe par Ralf Herbrich, Tom Minka et Thore Graepel chez Microsoft Research (article NIPS 20, publié en 2007 — TrueSkill: A Bayesian Skill Rating System). Tom Minka est également l’auteur d’Expectation Propagation (EP), l’algorithme d’inférence au cœur de TrueSkill (voir section 6). Le système est utilisé sur Xbox Live depuis 2007 pour le matchmaking de millions de joueurs. Le notebook distille le chapitre 3 « Meeting Your Match » du Model-Based Machine Learning (Winn & Bishop).
Fidélité à la source : Ce notebook distille le chapitre 3 « Meeting Your Match » du Model-Based Machine Learning (Winn & Bishop, mbmlbook.com/TrueSkill.html), lui-même adapté de Herbrich, Minka & Graepel (2007). Le scénario (matchs Xbox Live/Halo 2, skill déduit du résultat), la mécanique bayésienne (performance = skill + bruit, facteur IsGreaterThan) et la nécessité d’Expectation Propagation (posterior exact non-Gaussien après troncation) suivent le livre. À distinguer de Infer-7-Skills-IRT qui distille le chapitre 2 (« Assessing People’s Skills ») : la skill y est déduite de réponses à un test (modèle Rasch/IRT), ici elle est déduite du résultat d’un match.
Elo : le prédécesseur déterministe que TrueSkill généralise
Avant TrueSkill, le classement compétitif était dominé par Elo (échecs, années 1960), que la cellule suivante implémente from-scratch. Chaque joueur y est représenté par un unique scalaire\(R\) (son rating) :
\(K\) : facteur de mise à jour FIXE (typiquement 16 à 32).
Elo est simple, robuste et éprouvé. Mais il est déterministe et ponctuel : il ne modélise pas son incertitude. La cellule suivante montre concrètement ce que cela implique, et pourquoi Microsoft a développé TrueSkill pour Xbox Live.
// Elo : le systeme de classement deterministe que TrueSkill generalise.// Implementation from-scratch (pure C#, deterministe) pour servir de baseline.doubleExpectedScore(double ratingA,double ratingB)=>1.0/(1.0+ Math.Pow(10,(ratingB - ratingA)/400.0));(double,double)UpdateElo(double ratingA,double ratingB,double scoreA,double K =32){double ea =ExpectedScore(ratingA, ratingB);return(ratingA + K *(scoreA - ea), ratingB - K *(scoreA - ea));// somme nulle}Console.WriteLine("ELO : LE PREDECESSEUR DETERMINISTE");Console.WriteLine(newstring('=',60));// Deux nouveaux joueurs, meme rating initial (convention Elo : 1500).double R1 =1500.0, R2 =1500.0;Console.WriteLine($"Avant : R1 = {R1:F1}, R2 = {R2:F1} (deux nouveaux joueurs)");Console.WriteLine($" Score attendu de J1 : E = {ExpectedScore(R1, R2):F3}");// Joueur 1 gagne (resultat = 1).(R1, R2)=UpdateElo(R1, R2, scoreA:1.0);Console.WriteLine($"Apres (J1 gagne) : R1 = {R1:F1}, R2 = {R2:F1} (Delta = +16,0 / -16,0)");Console.WriteLine();Console.WriteLine("CECITE A L'INCERTITUDE : Elo applique le meme K en permanence");Console.WriteLine(newstring('-',60));// Une serie de 5 victoires consecutives de J1.R1 =1500.0; R2 =1500.0;double prev = R1;for(int k =1; k <=5; k++){(R1, R2)=UpdateElo(R1, R2, scoreA:1.0);double delta = R1 - prev; Console.WriteLine($" Victoire {k} : R1 = {R1,7:F1} (increment +{delta:F1})"); prev = R1;}Console.WriteLine();Console.WriteLine(">>> Elo ne SAIT PAS qu'il est incertain. Un nouveau joueur et un");Console.WriteLine(" veteran de 1000 matchs au meme rating sont traites identiquement.");Console.WriteLine(" C'est ce defaut que TrueSkill corrige en modelisant sigma.");
ELO : LE PREDECESSEUR DETERMINISTE
============================================================
Avant : R1 = 1500,0, R2 = 1500,0 (deux nouveaux joueurs)
Score attendu de J1 : E = 0,500
Apres (J1 gagne) : R1 = 1516,0, R2 = 1484,0 (Delta = +16,0 / -16,0)
CECITE A L'INCERTITUDE : Elo applique le meme K en permanence
------------------------------------------------------------
Victoire 1 : R1 = 1516,0 (increment +16,0)
Victoire 2 : R1 = 1530,5 (increment +14,5)
Victoire 3 : R1 = 1543,7 (increment +13,2)
Victoire 4 : R1 = 1555,8 (increment +12,1)
Victoire 5 : R1 = 1566,8 (increment +11,0)
>>> Elo ne SAIT PAS qu'il est incertain. Un nouveau joueur et un
veteran de 1000 matchs au meme rating sont traites identiquement.
C'est ce defaut que TrueSkill corrige en modelisant sigma.
Lecture : Elo est aveugle à sa propre incertitude
Les incréments rétrécissent (16,0 → 14,5 → 13,2 → 12,1 → 11,0) au fil des victoires consécutives. Ce n’est pas parce qu’Elo « apprend » qu’il est confiant : c’est un effet mécanique. À mesure que \(R_1\) monte, le score attendu \(E_A\) grimpe vers 1, donc l’écart \((S_A - E_A)\) diminue, et la même mise \(K\) produit un delta plus petit. C’est une conséquence arithmétique de la formule, pas une modélisation de l’incertitude.
La limite fondamentale : un nouveau joueur (0 match) et un vétéran (1000 matchs) au même rating reçoivent exactement le même \(K\). Elo ne sait pas distinguer « je suis sûr à 25,0 ± 8,3 » de « je suis sûr à 25,0 ± 0,1 ». C’est précisément ce défaut que TrueSkill corrige en représentant chaque compétence par une distribution\(\mathcal{N}(\mu, \sigma^2)\) : \(\sigma\) diminue avec chaque match observé, et la mise à jour s’adapte à l’incertitude courante plutôt qu’à un \(K\) figé.
Le tableau de comparaison ci-dessus (axes Représentation, Incertitude, Convergence…) prend maintenant tout son sens : TrueSkill n’est pas « un meilleur Elo », c’est une généralisation bayésienne qui substitue une distribution au scalaire, rendant l’incertitude explicite et exploitée.
3. Modèle Deux Joueurs
Construction du modèle étape par étape
Le code suivant construit le modèle TrueSkill en quatre phases :
Paramètres : Definition des hyperparametres (mu=25, sigma=8.33, beta=4.17)
Priors : Chaque joueur commence avec la même distribution Gaussienne
Performances : Ajout de bruit pour modeliser la variabilite d’un match
Observation : Le résultat du match (qui a gagne) est observe
Cette structure separe clairement les croyances initiales (priors) des données observees (résultat du match).
// Parametres TrueSkilldouble muInitial =25.0;double sigmaInitial =25.0/3.0;double beta = sigmaInitial /2.0;// Variabilite de la performance// Skills des joueurs (priors)Variable<double> skill1 = Variable.GaussianFromMeanAndVariance(muInitial, sigmaInitial * sigmaInitial).Named("skill1");Variable<double> skill2 = Variable.GaussianFromMeanAndVariance(muInitial, sigmaInitial * sigmaInitial).Named("skill2");// Performances (skill + bruit)Variable<double> perf1 = Variable.GaussianFromMeanAndVariance(skill1, beta * beta).Named("perf1");Variable<double> perf2 = Variable.GaussianFromMeanAndVariance(skill2, beta * beta).Named("perf2");// Resultat du match : Joueur 1 gagneVariable<bool> joueur1Gagne =(perf1 > perf2).Named("joueur1Gagne");// Observation : Joueur 1 a effectivement gagnejoueur1Gagne.ObservedValue=true;Console.WriteLine("Modele TrueSkill deux joueurs defini.");
Modele TrueSkill deux joueurs defini.
Structure du modèle graphique
Le modèle TrueSkill peut etre represente comme un graphe de facteurs :
Intuition : L’observation que “joueur 1 gagne” impose la contrainte perf1 > perf2. L’inference propage cette information vers les skills, augmentant skill1 et diminuant skill2.
Exécution de l’inference
Nous allons maintenant executer l’inference pour calculer les posterieurs des skills après avoir observe que le joueur 1 a gagne. L’algorithme EP va propager l’information du résultat vers les distributions de skill.
// Inference apres le matchInferenceEngine moteur =newInferenceEngine(newExpectationPropagation());moteur.Compiler.CompilerChoice= CompilerChoice.Roslyn;moteur.ShowFactorGraph=true;// Activer la generation du graphe de facteursGaussian skill1Post = moteur.Infer<Gaussian>(skill1);Gaussian skill2Post = moteur.Infer<Gaussian>(skill2);Console.WriteLine("=== Apres un match (Joueur 1 gagne) ===");Console.WriteLine($"\nAvant le match :");Console.WriteLine($" Skill1 = N({muInitial:F1}, {sigmaInitial:F2})");Console.WriteLine($" Skill2 = N({muInitial:F1}, {sigmaInitial:F2})");Console.WriteLine($"\nApres le match :");Console.WriteLine($" Skill1 = N({skill1Post.GetMean():F2}, {Math.Sqrt(skill1Post.GetVariance()):F2})");Console.WriteLine($" Skill2 = N({skill2Post.GetMean():F2}, {Math.Sqrt(skill2Post.GetVariance()):F2})");Console.WriteLine($"\nChangement de skill :");Console.WriteLine($" Joueur 1 : +{skill1Post.GetMean() - muInitial:F2}");Console.WriteLine($" Joueur 2 : {skill2Post.GetMean() - muInitial:F2}");
Compiling model...done.
=== Apres un match (Joueur 1 gagne) ===
Avant le match :
Skill1 = N(25,0, 8,33)
Skill2 = N(25,0, 8,33)
Apres le match :
Skill1 = N(29,21, 7,19)
Skill2 = N(20,79, 7,19)
Changement de skill :
Joueur 1 : +4,21
Joueur 2 : -4,21
Analyse détaillée du résultat
Avant le match : Les deux joueurs sont identiques N(25, 8.33) Après le match : Skill1 = N(29.21, 7.19), Skill2 = N(20.79, 7.19)
Observations clés :
Aspect
Valeur
Explication
Gain du gagnant
+4.21
Augmentation significative
Perte du perdant
-4.21
Symétrique (priors identiques)
Réduction sigma
8.33 → 7.19
Plus d’info = moins d’incertitude
Intuition : Un match entre deux joueurs de même niveau (selon les priors) est informatif. Le gagnant a démontré qu’il est probablement meilleur.
Comparaison avec Elo : Contrairement au système Elo classique qui utilise des changements fixes (±16 points), TrueSkill adapte le changement en fonction de l’incertitude. Un joueur avec grand sigma (nouveau) verra son rating changer plus rapidement.
// Visualisation du graphe de facteurs TrueSkilldisplay(HTML(FactorGraphHelper.GetLatestFactorGraphHtml()));
Model_08_19_26_02_22_45_04.svg
Lecture du graphe de facteurs TrueSkill 1v1
Le graphe ci-dessus montre la structure du modèle TrueSkill pour un match a deux joueurs :
Noeuds de variables (ellipses) : - skill1, skill2 : Les competences latentes des joueurs (Gaussiennes) - perf1, perf2 : Les performances observees pendant le match - joueur1Gagne : Le résultat du match (observe = true)
Noeuds de facteurs (rectangles) : - GaussianFromMeanAndVariance : Lie les priors aux skills et les skills aux performances - IsGreaterThan (ou >) : La contrainte de comparaison entre performances
Flux d’information : L’algorithme Expectation Propagation (EP) propage des messages le long de ce graphe : 1. L’observation joueur1Gagne = true envoie un message vers le facteur de comparaison 2. Ce facteur propage l’information vers perf1 (augmente) et perf2 (diminue) 3. Les changements de performance se propagent vers les skills correspondants
Note technique : Le facteur IsGreaterThan n’est pas conjugue avec les Gaussiennes. EP l’approxime par des moments de Gaussienne, ce qui explique pourquoi TrueSkill utilise EP plutot que VMP.
Pourquoi EP ? Le coût de l’inférence exacte
La note précédente dit que TrueSkill utilise EP plutôt que VMP — mais une question plus fondamentale reste en suspens : pourquoi approximer l’inférence du tout ? Pourquoi ne pas calculer le posterior exact des skills ?
Le problème vient du facteur IsGreaterThan. Les priors et les facteurs de performance (GaussianFromMeanAndVariance) sont Gaussiens, donc conjugués : leur produit reste Gaussien. Mais la contrainte \(\text{perf}_1 > \text{perf}_2\)tronque la Gaussienne (elle annule tout le demi-plan où le joueur 2 gagnerait). Le message qui en résulte n’est plus Gaussien : c’est une Gaussienne cumulée (une sigmoïde), et le posterior exact du skill est le produit d’une Gaussienne par cette sigmoïde — une courbe asymétrique, non-Gaussienne.
Un posterior exact a trop de paramètres. Une Gaussienne se résume à 2 nombres (\(\mu\), \(\sigma\)). Le posterior exact (Gaussienne \(\times\) Gaussienne cumulée) nécessite 4 paramètres. Or chaque match ajoute un tel facteur : après \(k\) matchs, la représentation exacte du posterior accumule \(2(k{+}1)\) paramètres. C’est insoutenable pour un système qui classe des millions de joueurs sur des milliers de matchs.
C’est là qu’intervient Expectation Propagation (EP). Plutôt que de traîner un posterior exact de plus en plus complexe, EP reprojette le posterior sur une Gaussienne après chaque facteur (en matchant les moments — moyenne et variance). Le nombre de paramètres reste borné (toujours 2 par skill), au prix d’une approximation locale.
Lecture du résultat cellule 12 : le posterior affiché N(29.21, 7.19) (skill du gagnant) n’est pas le posterior exact — c’est la projection Gaussienne calculée par EP. Le vrai posterior est légèrement asymétrique ; EP en capture la moyenne et la variance, ce qui suffit pour le matchmaking. C’est ce compromis précision/coût qui rend TrueSkill déployable à l’échelle d’Xbox Live.
Lien avec MBML Ch.3 : cette motivation (explosion paramétrique de l’inférence exacte → nécessité d’EP) est développée en détail dans Model-Based Machine Learning (Winn & Bishop), chapitre « Meeting Your Match », dont cette série est distillée.
4. Gestion des Matchs Nuls
Modèle
Un match nul se produit quand la différence de performances est dans un intervalle \([-\epsilon, \epsilon]\).
Pour modeliser un match nul, nous utilisons Variable.ConstrainBetween qui impose que la différence de performances soit dans un intervalle. Cela remplace la contrainte binaire “>” par une contrainte d’intervalle.
// Modele avec possibilite de match nuldouble epsilon =1.0;// Marge pour match nulVariable<double> skillA = Variable.GaussianFromMeanAndVariance(muInitial, sigmaInitial * sigmaInitial).Named("skillA");Variable<double> skillB = Variable.GaussianFromMeanAndVariance(muInitial, sigmaInitial * sigmaInitial).Named("skillB");Variable<double> perfA = Variable.GaussianFromMeanAndVariance(skillA, beta * beta).Named("perfA");Variable<double> perfB = Variable.GaussianFromMeanAndVariance(skillB, beta * beta).Named("perfB");// Difference de performancesVariable<double> diff =(perfA - perfB).Named("diff");// Match nul : diff dans [-epsilon, epsilon]Variable.ConstrainBetween(diff,-epsilon, epsilon);InferenceEngine moteurNul =newInferenceEngine(newExpectationPropagation());moteurNul.Compiler.CompilerChoice= CompilerChoice.Roslyn;moteurNul.ShowFactorGraph=true;// Activer la generation du graphe de facteursGaussian skillAPostNul = moteurNul.Infer<Gaussian>(skillA);Gaussian skillBPostNul = moteurNul.Infer<Gaussian>(skillB);Console.WriteLine("=== Apres un match nul ===");Console.WriteLine($"\nSkillA = N({skillAPostNul.GetMean():F2}, {Math.Sqrt(skillAPostNul.GetVariance()):F2})");Console.WriteLine($"SkillB = N({skillBPostNul.GetMean():F2}, {Math.Sqrt(skillBPostNul.GetVariance()):F2})");Console.WriteLine($"\n=> Les deux joueurs gardent le meme skill moyen");Console.WriteLine($" mais l'incertitude diminue (on sait qu'ils sont proches)");
Compiling model...done.
=== Apres un match nul ===
SkillA = N(25,00, 6,46)
SkillB = N(25,00, 6,46)
=> Les deux joueurs gardent le meme skill moyen
mais l'incertitude diminue (on sait qu'ils sont proches)
Analyse du match nul
Résultat : Les deux joueurs gardent mu=25.00 mais sigma baisse de 8.33 à 6.46
Interprétation :
Un match nul entre joueurs de même niveau prior ne change pas l’estimation moyenne, mais réduit fortement l’incertitude car : - On a observé qu’ils performent de manière similaire - C’est cohérent avec l’hypothèse qu’ils ont le même skill - Donc on est plus confiant dans cette estimation
Paradoxe apparent : Un match “sans résultat” apporte quand même de l’information ! Il confirme que les skills sont proches.
Application : Dans les échecs, une nulle entre deux joueurs de ratings similaires ne change presque pas leurs ratings Elo. Mais avec TrueSkill, leur incertitude diminue, ce qui affectera les futurs matchs.
Exercice : Impact du paramètre beta sur la mise a jour des skills
Le paramètre beta contrôle la variance de la performance (bruit dans un match). Un beta faible signifie que le résultat du match reflete fidelement le skill, tandis qu’un beta eleve signifie beaucoup de variance (chance/peur de gagner).
Objectif : Comparez la mise a jour des skills pour un même match (joueur 1 gagne) avec trois valeurs de beta : 2.0 (faible), 4.17 (defaut), et 8.0 (eleve).
Étapes : 1. Pour chaque valeur de beta, créez le modèle TrueSkill 1v1 avec les priors par defaut (mu=25, sigma=8.33) 2. Observez que joueur 1 gagne 3. Calculez les posterieurs des deux joueurs 4. Affichez un tableau comparatif des changements de skill pour chaque beta
Indices : - Un beta faible => le match est très informatif => grand changement de skill - Un beta eleve => le match est peu informatif => petit changement de skill - Comparez aussi la reduction de sigma (incertitude) entre les trois cas
// Exercice : Impact du parametre beta sur la mise a jour des skillsdouble muInit =25.0;double sigmaInit =25.0/3.0;// TODO: Definir les trois valeurs de beta a tester// Indice: double[] betas = { 2.0, 4.17, 8.0 };// TODO: Boucler sur chaque beta et creer le modele TrueSkill 1v1// Indice: Pour chaque beta, Variable<double> skill1 = Variable.GaussianFromMeanAndVariance(muInit, sigmaInit^2);// Variable<double> perf1 = Variable.GaussianFromMeanAndVariance(skill1, beta^2);// Meme chose pour skill2/perf2, puis Variable<bool> win = (perf1 > perf2); win.ObservedValue = true;// TODO: Inferer les posterieurs et afficher le tableau comparatif// Console.WriteLine($"| beta={b:F2} | skill1={s1.GetMean():F2} | sigma={Math.Sqrt(s1.GetVariance()):F2} | delta={s1.GetMean()-muInit:F2} |");Console.WriteLine("Exercice a completer : Impact du parametre beta");
Exercice a completer : Impact du parametre beta
// Visualisation du graphe de facteurs pour le match nuldisplay(HTML(FactorGraphHelper.GetLatestFactorGraphHtml()));
Model_08_19_26_02_22_47_00.svg
Lecture du graphe de facteurs - Match nul
Ce graphe differe du modèle 1v1 par le facteur de contrainte :
Différence structurelle : - diff : Variable intermediaire representant perfA - perfB - ConstrainBetween : Facteur imposant que diff soit dans l’intervalle [-epsilon, epsilon]
Comparaison avec le modèle 1v1 :
Aspect
Match 1v1
Match nul
Facteur de résultat
IsGreaterThan
ConstrainBetween
Information
Ordre strict
Proximite
Effet sur mu
Augmente/diminue
Inchange
Effet sur sigma
Reduit
Reduit davantage
Le facteur ConstrainBetween est plus informatif car il impose une double contrainte (borne inf et sup), ce qui explique la reduction plus importante de l’incertitude.
5. Apprentissage en Ligne
Principe
Après chaque match, les posterieurs deviennent les priors pour le match suivant.
Match 1 : Prior -> Inference -> Posterieur
|
v
Match 2 : Prior (= Posterieur 1) -> Inference -> Posterieur
|
v
Match 3 : ...
Implementation de la classe TrueSkillOnline
La classe suivante encapsule la logique d’apprentissage en ligne :
Dictionary skills : Stocke le posterieur actuel de chaque joueur
GetSkill() : Retourne le prior initial si le joueur est nouveau
EnregistrerMatch() : Met a jour les posterieurs après un match
AfficherClassement() : Affiche le rating conservatif (mu - 3*sigma)
Le rating conservatif mu - 3*sigma est la metrique publique utilisee par Xbox Live. Il represente une borne inferieure a 99.7% de confiance sur le vrai skill.
En pratique : 1. Le posterieur après le match n-1 devient le prior pour le match n 2. Chaque match apporte de l’information incrementale 3. Le système “n’oublie jamais” mais l’influence des anciens matchs diminue naturellement
Avantage computationnel : Contrairement a un recalcul global, l’apprentissage en ligne a une complexite O(1) par match, permettant de gerer des millions de joueurs en temps reel.
Une nuance essentielle : l’apprentissage en ligne n’est pas une évolution du skill
L’affirmation ci-dessus (« le système n’oublie jamais ») décrit fidèlement le modèle à skill fixe : chaque joueur possède une compétence unique et immuable, et l’apprentissage en ligne resserre simplement l’incertitude (σ) autour de cette valeur fixe. Une idée reçue fréquente consiste à croire que ce mécanisme permet au skill de dériver dans le temps — ce n’est pas le cas. Le posterior se resserre sur une inconnue fixe ; il ne modélise pas une compétence qui évolue.
La conséquence est importante : après de nombreux matchs, σ s’effondre (ex. 8,33 → ~1). Si le joueur s’améliore ensuite réellement (entraînement, coaching), le posterior étroit résiste au suivi : la mise à jour devient minuscule car le prior est trop confiant dans l’ancien niveau. C’est précisément le défaut rapporté par les bêta-testeurs Xbox Live et corrigé au climax du chapitre MBML (§3.5, Allowing the skills to vary) : certains joueurs voyaient leur skill « bloqué » à bas niveau malgré une progression réelle.
La correction (modèle à skill dynamique) : remplacer le skill fixe par une marche aléatoire gaussienne
où γ ( change variance ) contrôle la vitesse de variation admissible entre deux matchs. Le posterior d’un match sert de moyenne au suivant, élargi par γ, ce qui laisse au système la souplesse de suivre une trajectoire. C’est ce modèle étendu, dit TrueSkill Through Time (Dangauthier, Herbrich, Minka & Graepel, 2007), qui permet de comparer des joueurs d’échecs d’époques différentes — y compris des champions n’ayant jamais joué ensemble.
Le présent notebook modélise le skill fixe (cas pédagogique de base, §3.1–3.4 du MBML). Cette limitation est déjà signalée §10 (Résumé → Limitations). L’extension dynamique (§3.5) constitue le grain de fond naturel d’une suite.
Simulation d’un tournoi complet
Nous simulons maintenant un petit tournoi de 6 matchs entre 4 joueurs. Observez comment les skills evoluent au fur et a mesure des matchs, et comment le classement emerge des résultats.
// Simulation d'un tournoivar ts =newTrueSkillOnline();Console.WriteLine("=== Tournoi TrueSkill ===");// Serie de matchsvar matchs =new(string,string)[]{("Alice","Bob"),// Alice bat Bob("Charlie","Dave"),// Charlie bat Dave("Alice","Charlie"),// Alice bat Charlie("Bob","Dave"),// Bob bat Dave("Alice","Dave"),// Alice bat Dave("Charlie","Bob")// Charlie bat Bob};foreach(var(gagnant, perdant)in matchs){ Console.WriteLine($"Match : {gagnant} bat {perdant}"); ts.EnregistrerMatch(gagnant, perdant);}ts.AfficherClassement();
=== Tournoi TrueSkill ===
Match : Alice bat Bob
Compiling model...done.
Match : Charlie bat Dave
Compiling model...done.
Match : Alice bat Charlie
Compiling model...done.
Match : Bob bat Dave
Compiling model...done.
Match : Alice bat Dave
Compiling model...done.
Match : Charlie bat Bob
Compiling model...done.
=== Classement ===
1. Alice : mu=33,3, sigma=6,01, rating=15,2
2. Charlie : mu=28,3, sigma=5,58, rating=11,6
3. Bob : mu=21,7, sigma=5,58, rating=4,9
4. Dave : mu=16,7, sigma=6,01, rating=-1,3
Analyse du classement final
Classement obtenu : Alice > Charlie > Bob > Dave
Joueur
V-D
Rating
Sigma
Alice
3-0
15.2
6.01
Charlie
2-1
11.6
5.58
Bob
1-2
4.9
5.58
Dave
0-3
-1.3
6.01
Observations :
Transitivité respectée : Alice > Charlie (directement) et Charlie > Bob (directement) implique Alice > Bob
Rating conservatif : mu - 3σ pénalise les joueurs avec peu de matchs (plus grande incertitude)
Sigma décroît : Plus de matchs = moins d’incertitude sur le skill
Pourquoi utiliser mu - 3σ ? - Évite de surclasser un joueur chanceux avec peu de matchs - Avec 3σ, on a ~99.7% de confiance que le vrai skill est supérieur - Xbox Live utilise cette métrique pour le matchmaking public
6. Extension aux Équipes
Modèle
Pour un match par équipes, la performance d’équipe est la somme des performances individuelles.
Modelisation de la performance d’équipe
Dans ce modèle 2v2, la performance d’une équipe est la somme des performances individuelles. Ce choix de modelisation implique que :
Un bon joueur peut “porter” un coequipier plus faible
La variance de l’équipe augmente avec le nombre de joueurs
L’attribution du credit est uniforme entre coequipiers
// Modele par equipes (2v2)// Equipe 1 : Joueurs A et BVariable<double> skillA2 = Variable.GaussianFromMeanAndVariance(25,70).Named("skillA2");Variable<double> skillB2 = Variable.GaussianFromMeanAndVariance(25,70).Named("skillB2");// Equipe 2 : Joueurs C et DVariable<double> skillC = Variable.GaussianFromMeanAndVariance(25,70).Named("skillC");Variable<double> skillD = Variable.GaussianFromMeanAndVariance(25,70).Named("skillD");// Performances individuellesVariable<double> perfA2 = Variable.GaussianFromMeanAndVariance(skillA2,17).Named("perfA2");Variable<double> perfB2 = Variable.GaussianFromMeanAndVariance(skillB2,17).Named("perfB2");Variable<double> perfC2 = Variable.GaussianFromMeanAndVariance(skillC,17).Named("perfC2");Variable<double> perfD2 = Variable.GaussianFromMeanAndVariance(skillD,17).Named("perfD2");// Performances d'equipe (somme)Variable<double> perfEquipe1 =(perfA2 + perfB2).Named("perfEquipe1");Variable<double> perfEquipe2 =(perfC2 + perfD2).Named("perfEquipe2");// Equipe 1 gagneVariable<bool> equipe1Gagne =(perfEquipe1 > perfEquipe2).Named("equipe1Gagne");equipe1Gagne.ObservedValue=true;InferenceEngine moteurEquipe =newInferenceEngine(newExpectationPropagation());moteurEquipe.Compiler.CompilerChoice= CompilerChoice.Roslyn;moteurEquipe.ShowFactorGraph=true;// Activer la generation du graphe de facteursConsole.WriteLine("=== Match par equipes (2v2) ===");Console.WriteLine("Equipe 1 (A+B) bat Equipe 2 (C+D)\n");Console.WriteLine($"Skill A apres : {moteurEquipe.Infer<Gaussian>(skillA2).GetMean():F2}");Console.WriteLine($"Skill B apres : {moteurEquipe.Infer<Gaussian>(skillB2).GetMean():F2}");Console.WriteLine($"Skill C apres : {moteurEquipe.Infer<Gaussian>(skillC).GetMean():F2}");Console.WriteLine($"Skill D apres : {moteurEquipe.Infer<Gaussian>(skillD).GetMean():F2}");Console.WriteLine("\n=> Tous les membres de l'equipe gagnante voient leur skill augmenter");
=== Match par equipes (2v2) ===
Equipe 1 (A+B) bat Equipe 2 (C+D)
Compiling model...done.
Skill A apres : 27,99
Skill B apres : 27,99
Skill C apres : 22,01
Skill D apres : 22,01
=> Tous les membres de l'equipe gagnante voient leur skill augmenter
Analyse du match par équipes
Résultats :
Joueur
Équipe
Skill avant
Skill après
Delta
A
Gagnante
25.00
27.99
+2.99
B
Gagnante
25.00
27.99
+2.99
C
Perdante
25.00
22.01
-2.99
D
Perdante
25.00
22.01
-2.99
Observations cles :
Attribution uniforme : Chaque membre recoit le même changement (priors identiques)
Gain plus faible qu’en 1v1 : +2.99 vs +4.21 car l’information est “diluee” entre coequipiers
Problème de l’attribution : Impossible de distinguer le “carry” du “porte”
Limitation : TrueSkill basique attribue également le credit/blame. Des extensions comme TrueSkill 2 (2018) utilisent des statistiques individuelles (kills, assists) pour une attribution plus fine.
// Visualisation du graphe de facteurs pour le match par equipes 2v2display(HTML(FactorGraphHelper.GetLatestFactorGraphHtml()));
Model_08_19_26_02_22_49_78.svg
Lecture du graphe de facteurs - Match par équipes 2v2
Le graphe 2v2 illustre l’extension du modèle TrueSkill aux équipes :
Structure hiérarchique :
skillA2 skillB2 skillC skillD
| | | |
v v v v
perfA2 perfB2 perfC2 perfD2
\ / \ /
\ / \ /
v v v v
perfEquipe1 perfEquipe2
\ /
\ /
v v
equipe1Gagne (observe = true)
Facteurs d’agregation : - Plus (ou +) : Combine les performances individuelles en performance d’équipe - IsGreaterThan : Compare les performances d’équipe
Propagation de credit : L’information “équipe 1 gagne” se propage : 1. Vers perfEquipe1 (augmente) et perfEquipe2 (diminue) 2. Via les facteurs Plus, vers chaque performance individuelle 3. Puis vers chaque skill individuel
Dilution du signal : Avec 4 joueurs au lieu de 2, l’information est diluee. Chaque joueur recoit environ la moitie du changement de skill qu’il aurait eu en 1v1. C’est le “problème d’attribution de credit” inherent aux jeux d’équipe.
7. Multi-joueurs (Free-for-all)
Modèle
Pour N joueurs, on decompose le résultat en N-1 comparaisons par paires : - 1er > 2e > 3e > … > Ne
Implementation avec contraintes d’ordre transitives
Pour N joueurs classes du 1er au Neme, nous imposons N-1 contraintes transitives : - perf[0] > perf[1] (1er bat 2e) - perf[1] > perf[2] (2e bat 3e) - … - perf[N-2] > perf[N-1] (avant-dernier bat dernier)
Infer.NET resout ce système de contraintes simultanement grace a EP.
// Modele multi-joueurs (4 joueurs)// Resultat : P1 > P2 > P3 > P4Variable<double>[] skillsMulti =new Variable<double>[4];Variable<double>[] perfsMulti =new Variable<double>[4];for(int i =0; i <4; i++){ skillsMulti[i]= Variable.GaussianFromMeanAndVariance(25,70).Named($"skill_P{i+1}"); perfsMulti[i]= Variable.GaussianFromMeanAndVariance(skillsMulti[i],17).Named($"perf_P{i+1}");}// Contraintes d'ordre : perf1 > perf2 > perf3 > perf4Variable.ConstrainTrue(perfsMulti[0]> perfsMulti[1]);Variable.ConstrainTrue(perfsMulti[1]> perfsMulti[2]);Variable.ConstrainTrue(perfsMulti[2]> perfsMulti[3]);InferenceEngine moteurMulti =newInferenceEngine(newExpectationPropagation());moteurMulti.Compiler.CompilerChoice= CompilerChoice.Roslyn;moteurMulti.ShowFactorGraph=true;// Activer la generation du graphe de facteursConsole.WriteLine("=== Course multi-joueurs ===");Console.WriteLine("Classement : P1 > P2 > P3 > P4\n");for(int i =0; i <4; i++){ Gaussian post = moteurMulti.Infer<Gaussian>(skillsMulti[i]); Console.WriteLine($"Joueur {i+1} (position {i+1}) : mu={post.GetMean():F2}, sigma={Math.Sqrt(post.GetVariance()):F2}");}
Les contraintes transitives P1 > P2 > P3 > P4 impliquent : - Le 1er et le dernier ont les changements les plus extremes - Les positions intermediaires ont des changements moderes - Sigma est plus eleve aux extremes (moins d’info directe)
Application : Ce modèle est utilise pour les jeux Battle Royale (Fortnite, PUBG) ou les courses (Mario Kart). Le placement complet apporte plus d’information qu’une simple victoire/defaite.
// Visualisation du graphe de facteurs pour le mode multi-joueursdisplay(HTML(FactorGraphHelper.GetLatestFactorGraphHtml()));
Model_08_19_26_02_22_50_42.svg
Lecture du graphe de facteurs - Multi-joueurs (Free-for-all)
Le graphe multi-joueurs montre une structure en chaîne de contraintes :
Chaîne de comparaisons : N-1 facteurs IsGreaterThan pour N joueurs
Joueurs intermediaires : P2 et P3 participent a deux comparaisons chacun
Correlation induite : Les contraintes couplent les variables entre elles
Propagation EP iterative : Le graphe montre pourquoi EP necessite des itérations : - L’info de P1>P2 affecte P2 - L’info de P2>P3 affecte aussi P2 - Ces deux sources d’info doivent etre reconciliees
Complexite computationnelle : Contrairement au cas 1v1 (solution analytique), le cas multi-joueurs necessite des itérations EP. C’est pourquoi on observe “Iterating: …” dans la sortie. La complexite est O(N^2) par itération pour N joueurs.
8. Analyse d’Echecs (Elo Bayesien)
Application aux echecs
Nous appliquons TrueSkill aux echecs avec des paramètres adaptes a l’echelle Elo :
Paramètre
Valeur TrueSkill standard
Valeur echecs
mu_initial
25
1500
sigma_initial
8.33
350
beta
4.17
175
L’echelle est simplement multipliee par 60 pour correspondre aux ratings Elo traditionnels.
=== Classement Echecs (Elo Bayesien) ===
Parties :
Magnus bat Fabiano
Compiling model...done.
Magnus bat Ian
Compiling model...done.
Fabiano bat Ian
Compiling model...done.
Magnus bat Fabiano
Compiling model...done.
Magnus bat Ian
Compiling model...done.
Ian bat Fabiano
Compiling model...done.
Magnus bat Fabiano
Compiling model...done.
Magnus bat Ian
Compiling model...done.
Fabiano bat Ian
Compiling model...done.
Magnus bat Ian
Compiling model...done.
=== Classement ===
1. Magnus : mu=1923,7, sigma=213,54, rating=1283,1
2. Fabiano : mu=1344,7, sigma=183,39, rating=794,6
3. Ian : mu=1217,4, sigma=182,68, rating=669,4
Analyse du classement echecs
Résultats :
Joueur
Victoires
Defaites
Mu
Sigma
Rating
Magnus
7
0
1923.7
213.54
1283.1
Fabiano
2
4
1344.7
183.39
794.6
Ian
1
6
1217.4
182.68
669.4
Observations :
Magnus domine : 7-0 (7 victoires sur les 10 matchs) avec un gain de +423.7 points (1500 -> 1923.7)
L’upset compte : Ian bat Fabiano (match 6), ce qui explique pourquoi Ian n’est pas beaucoup plus bas
Sigma decroit : Plus de matchs = plus de certitude sur le niveau reel
Comparaison avec le vrai classement FIDE (2024) :
Joueur
FIDE Elo
Notre estimation
Magnus Carlsen
~2830
1923.7
Fabiano Caruana
~2800
1344.7
Ian Nepomniachtchi
~2790
1217.4
Note : Les vrais ecarts sont plus faibles (30-40 points), car notre simulation suppose que Magnus gagne toujours, ce qui est irrealiste au plus haut niveau.
9. Exemple guide : Simuler un Tournoi
Enonce
Créez un tournoi avec 6 joueurs et simulez 15 matchs aleatoires. Comparez le classement final aux “vrais skills” que vous aurez définis.
Indice
Definissez des skills “vrais” pour chaque joueur
Simulez le résultat de chaque match en fonction des skills
Utilisez TrueSkillOnline pour mettre a jour les estimations
Simulation avec “vrais skills” connus
Cet exercice illustre un cas fondamental en statistique bayesienne : nous connaissons les vrais skills (simulation) et pouvons evaluer la qualite des estimations.
Protocole experimental : 1. Définir les vrais skills de 6 joueurs (inconnus du modèle) 2. Simuler 15 matchs ou le meilleur joueur gagne plus souvent 3. Comparer les estimations TrueSkill aux vrais skills
Notez que le joueur ne gagne pas toujours même s’il est meilleur : on ajoute du bruit (+/- 5 points) pour simuler la variance de performance.
// Exemple guide : Tournoi simule// Vrais skills (inconnus du systeme)var vraisSkills =new Dictionary<string,double>{["Elite1"]=35,["Elite2"]=32,["Moyen1"]=25,["Moyen2"]=24,["Debutant1"]=18,["Debutant2"]=15};var joueurs = vraisSkills.Keys.ToArray();var rng =newRandom(42);var tournoi =newTrueSkillOnline();Console.WriteLine("=== Tournoi Simule ===");Console.WriteLine("\nVrais skills :");foreach(var kv in vraisSkills.OrderByDescending(x => x.Value)) Console.WriteLine($" {kv.Key}: {kv.Value}");Console.WriteLine("\nMatchs :");// 15 matchs aleatoiresfor(int m =0; m <15; m++){// Choisir deux joueurs differentsint i = rng.Next(joueurs.Length);int j;do{ j = rng.Next(joueurs.Length);}while(j == i);string j1 = joueurs[i];string j2 = joueurs[j];// Simuler le match (le meilleur gagne avec plus de probabilite)double perf1 = vraisSkills[j1]+ rng.NextDouble()*10-5;// +/- 5double perf2 = vraisSkills[j2]+ rng.NextDouble()*10-5;string gagnant = perf1 > perf2 ? j1 : j2;string perdant = perf1 > perf2 ? j2 : j1; Console.WriteLine($" {gagnant} bat {perdant}"); tournoi.EnregistrerMatch(gagnant, perdant);}tournoi.AfficherClassement();Console.WriteLine("\n=> Comparez le classement estime aux vrais skills !");
=== Tournoi Simule ===
Vrais skills :
Elite1: 35
Elite2: 32
Moyen1: 25
Moyen2: 24
Debutant1: 18
Debutant2: 15
Matchs :
Elite1 bat Debutant1
Compiling model...done.
Elite2 bat Debutant1
Compiling model...done.
Elite2 bat Debutant1
Compiling model...done.
Elite2 bat Moyen1
Compiling model...done.
Elite1 bat Debutant1
Compiling model...done.
Elite1 bat Debutant1
Compiling model...done.
Elite1 bat Debutant1
Compiling model...done.
Moyen2 bat Debutant1
Compiling model...done.
Elite2 bat Moyen2
Compiling model...done.
Moyen2 bat Debutant1
Compiling model...done.
Elite1 bat Debutant1
Compiling model...done.
Elite2 bat Debutant1
Compiling model...done.
Elite1 bat Moyen2
Compiling model...done.
Moyen1 bat Debutant1
Compiling model...done.
Elite1 bat Moyen1
Compiling model...done.
=== Classement ===
1. Elite1 : mu=34,3, sigma=5,08, rating=19,1
2. Elite2 : mu=33,8, sigma=5,48, rating=17,4
3. Moyen2 : mu=24,1, sigma=5,44, rating=7,8
4. Moyen1 : mu=22,4, sigma=5,92, rating=4,6
5. Debutant1 : mu=12,6, sigma=4,48, rating=-0,8
=> Comparez le classement estime aux vrais skills !
Analyse de la simulation
Comparaison vrais skills vs estimations :
Joueur
Vrai skill
Skill estimé
Écart
Elite1
35
34.3
-0.7 ✓
Elite2
32
33.8
+1.8 ✓
Moyen1
25
22.4
-2.6
Moyen2
24
24.1
+0.1 ✓
Debutant1
18
12.6
-5.4
Debutant2
15
-
(pas assez de matchs)
Observations :
Élites bien identifiés : Le modèle distingue clairement le groupe “élite”
Debutant1 sous-estimé : A joué beaucoup mais toujours perdu (malchance statistique)
Debutant2 absent : Sans matchs, reste au prior (invisible dans le classement)
Leçon : TrueSkill converge vers les vrais skills avec suffisamment de matchs, mais des séries malchanceuses peuvent biaiser temporairement les estimations. L’incertitude (sigma) capture ce risque.
10. Resume
Concept
Description
TrueSkill
Système de classement bayesien
Skill
Gaussienne N(mu, sigma^2)
Performance
Skill + bruit gaussien
Match nul
Différence de perf dans [-epsilon, epsilon]
Online learning
Posterieurs -> Priors
Rating conservatif
mu - 3*sigma
Forces de TrueSkill
Quantification explicite de l’incertitude via sigma
Convergence rapide pour les nouveaux joueurs (sigma eleve = grands changements)
Gestion native des équipes et multi-joueurs
Apprentissage en ligne efficace (O(1) par match)
Limitations
Suppose une skill stable dans le temps (pas d’apprentissage du joueur)
Attribution uniforme dans les équipes
Sensible au choix des hyperparametres (beta, epsilon)
Extensions modernes
TrueSkill 2 (2018) : Utilise les statistiques in-game pour attribution fine
Glicko-2 : Alternative populaire avec “volatilite” (changement de skill)
Pour aller plus loin : L’article original “TrueSkill: A Bayesian Skill Rating System” (Herbrich, Minka & Graepel, 2007 — NIPS 20) détaille les approximations EP et les calculs de messages.
Modelisez une ligue de football a 4 équipes avec TrueSkill. Résultats des matchs :
PSG bat Marseille (3-0)
Lyon bat Bordeaux (2-1)
Lyon bat PSG (2-1)
Lyon bat Marseille (1-0)
Definissez une variable de skill gaussienne pour chaque équipe (a priori : Gaussian(100, 1/33))
Encodez chaque résultat par le modèle TrueSkill (performance = Gaussian(skill, 1/beta^2))
Inferez les skills posterieurs et etablissez le classement des équipes
Indice : Reutilisez la structure du modèle TrueSkill de la section 3.
// Exercice : Ligue de football avec TrueSkill - 4 equipesdouble priorMean =100.0;double priorPrec =1.0/33.333;double beta =8.333;// Variance de performance// TODO: Creer le moteur d'inference// TODO: Definir les variables de skill pour les 4 equipes// TODO: Pour chaque match, creer les variables de performance et observer que gagnant > perdant// Exemple pour PSG bat Marseille :// TODO: Inferer les skills posterieurs et afficher le classement// Qui est classe premier ?Console.WriteLine("Exercice a completer");
Exercice a completer
12. Exercice : Prediction de Match avec Incertitude
Enonce
Vous disposez des skills estimes de 4 joueurs après un tournoi. Votre objectif est de predire le résultat d’un match entre deux joueurs donnes, en retournant la probabilite que le joueur A gagne.
Données : Skills posterieurs après 10 matchs : - Alice : N(30, 5^2) - Bob : N(25, 4^2) - Charlie : N(22, 6^2) - Dave : N(20, 3^2)
Tâches : 1. Implementez un modèle qui predit la probabilite de victoire de Alice contre chaque autre joueur 2. Quel match est le plus incertain (probabilite la plus proche de 0.5) ? 3. Comment la probabilite change-t-elle si on double beta (variance de performance) ?
Indice
La probabilite que perf1 > perf2 se calcule en utilisant Variable.IsPositive sur la différence des performances. Observez la variable booleenne resultante avec moteur.Infer<Bernoulli>(...).
// Exercice : Prediction de victoire// Skills posterieurs des joueursdouble muAlice =30.0, sigmaAlice =5.0;double muBob =25.0, sigmaBob =4.0;double muCharlie =22.0, sigmaCharlie =6.0;double muDave =20.0, sigmaDave =3.0;double beta =4.17;// Variabilite de performance// TODO: Creer un modele qui calcule P(Alice gagne contre Bob)// Etape 1: Definir les variables de skill (avec les posterieurs comme priors)// Etape 2: Ajouter les performances (skill + bruit)// Etape 3: Observer la contrainte perfAlice > perfBob// Etape 4: Inférer P(Alice gagne) avec moteur.Infer<Bernoulli>(resultat)// TODO: Repeter pour Alice vs Charlie et Alice vs Dave// TODO: Identifier le match le plus incertain (P le plus proche de 0.5)// TODO: Tester avec beta double (beta * 2). Laquelle des probabilites change le plus ?Console.WriteLine("Exercice a completer : prediction de match");
Exercice a completer : prediction de match
13. Exercice : Suivi de l’apprentissage en ligne - Convergence du classement
Enonce
L’apprentissage en ligne (section 5) met a jour les skills après chaque match en utilisant les posterieurs comme nouveaux priors. Votre objectif est de tracer l’evolution des estimations de skill au fil d’une serie de 8 matchs entre 3 joueurs, afin de visualiser comment le système converge.
Joueurs et vrais skills (inconnus du modèle) : - Zoe : skill = 30 (forte) - Leo : skill = 25 (moyen) - Max : skill = 20 (faible)
Serie de matchs : 1. Zoe bat Leo 2. Zoe bat Max 3. Leo bat Max 4. Zoe bat Leo 5. Leo bat Zoe (upset) 6. Max bat Leo (upset) 7. Zoe bat Max 8. Leo bat Max
Tâches : 1. Utilisez la classe TrueSkillOnline définie en section 5 pour enregistrer les 8 matchs 2. Après chaque match, enregistrez le mu et le sigma de chaque joueur dans des listes 3. Affichez un tableau de l’evolution : pour chaque match, montrez le mu de chaque joueur 4. (Bonus) : Après le match 5 (upset Leo bat Zoe), comment evolue le sigma de Zoe par rapport a l’avant-match 5 ? L’upset augmente-t-il l’incertitude ?
Indices :
Initialisez TrueSkillOnline avec les paramètres par defaut
Après chaque EnregistrerMatch(), appelez GetSkill() pour chaque joueur et stockez GetMean() et Math.Sqrt(GetVariance())
Observez comment sigma diminue au fil des matchs (convergence) et comment un upset peut modifier la tendance
// Exercice : Suivi de l'apprentissage en ligne - Convergence du classementstring[] joueursOL ={"Zoe","Leo","Max"};var tsOL =newTrueSkillOnline();// Listes pour stocker l'evolutionvar historiqueMu =new Dictionary<string, List<double>>{["Zoe"]=new List<double>(),["Leo"]=new List<double>(),["Max"]=new List<double>()};var historiqueSigma =new Dictionary<string, List<double>>{["Zoe"]=new List<double>(),["Leo"]=new List<double>(),["Max"]=new List<double>()};// Serie de matchsvar matchsOL =new(string gagnant,string perdant)[]{("Zoe","Leo"),("Zoe","Max"),("Leo","Max"),("Zoe","Leo"),("Leo","Zoe"),// Upset !("Max","Leo"),// Upset !("Zoe","Max"),("Leo","Max")};// TODO 1 : Enregistrez chaque match et capturez les skills apres chaque match// Indice : foreach (var (g, p) in matchsOL)// {// tsOL.EnregistrerMatch(g, p);// foreach (var j in joueursOL)// {// var skill = tsOL.GetSkill(j);// historiqueMu[j].Add(skill.GetMean());// historiqueSigma[j].Add(Math.Sqrt(skill.GetVariance()));// }// }// TODO 2 : Affichez le tableau d'evolution des mu// Indice : Console.WriteLine("Match | Zoe mu | Leo mu | Max mu");// for (int i = 0; i < matchsOL.Length; i++)// Console.WriteLine($"{i+1} | {historiqueMu["Zoe"][i]:F1} | {historiqueMu["Leo"][i]:F1} | {historiqueMu["Max"][i]:F1}");// TODO 3 : Affichez le classement final// tsOL.AfficherClassement();// TODO 4 : (Bonus) Analysez l'effet de l'upset (match 5) sur le sigma de Zoe// Indice : comparez historiqueSigma["Zoe"][3] (avant upset) et historiqueSigma["Zoe"][4] (apres upset)// L'upset (Leo bat Zoe) est-il "surprenant" pour le modele ? Cela augmente-t-il sigma ?Console.WriteLine("Exercice a completer : suivi apprentissage en ligne");
Exercice a completer : suivi apprentissage en ligne
14. Pour aller plus loin : les formules fermées de TrueSkill
La mise à jour closed-form de TrueSkill (Herbrich, Minka & Graepel, NeurIPS 2007) — les fonctions de troncature V(t), W(t) et leur vérification numérique exacte contre le moteur EP de la section 3 — fait l’objet de la lettre dédiée Infer-8b-TrueSkill-Formules-Fermees.
Conclusion
Ce notebook a presente le système TrueSkill : classement bayesien par matchs 1v1, matchs nuls, apprentissage en ligne et extensions multi-joueurs/équipes.
Posterieur(n-1) = Prior(n), complexite O(1) par match
Match nul
ConstrainBetween(-eps, +eps) : reduit sigma sans changer mu
Rating conservatif
mu - 3*sigma : borne inferieure a 99.7% de confiance
Distribution
Rôle
Gaussian
Skills et performances des joueurs
ExpectationPropagation
Algorithme pour les facteurs de comparaison non-conjugues
Apport TrueSkill : Contrairement a Elo (score ponctuel), TrueSkill propage l’incertitude via sigma. Un nouveau joueur (sigma eleve) converge rapidement ; un joueur etabli (sigma faible) est stable. L’apprentissage en ligne permet de mettre a jour des millions de joueurs en temps reel sur Xbox Live.