Entre
tron et game of drones, j'avais commencé a regarder plus en détail
l'implémentation de trueskill qui calcule le fameux "score"
de nos IA. Je voulais plus particulièrement voir l'influence du
nombre de matchs joués, l'influence de remettre une IA dans le
leaderboard alors que les autres sont déja classées
etc.
TrueSkill
Si
je ne me trompe pas, c'est TrueSkill qui a été utilisé pour
classer les IA sur tron et game of drones. TrueSkill est un outil
développé chez Microsoft qui est utilisé pour classer les joueurs
du XBox live. Ils ont publiés les formules, et pour ceux que ça
intéresse, vous aurez les détails mathématiques ici
: http://www.moserware.com/2010/03/computing-your-skill.html.
Si
vous voulez jouer avec, vous trouverez une implémentation en python
ici : http://trueskill.org/
TrueSkill
permet en particulier de classer des joueurs lors de rencontres où
il y a un nombre d'équipes variés, ou le résultat peut avoir des
égalités, où le nombre de joueur dans chaque équipe peut être
différent, et même avec la possibilité pour un joueur de ne pas
faire toute la rencontre et d'avoir donc une contribution partielle.
Il permet donc de classer des joueurs sur des jeux très
variés.
Si
on résume, chaque joueur possède seulement deux variables : mu et
sigma. mu est l'évaluation de son niveau actuel, et sigma la
confiance qu'on a dans ce niveau. Un nouveau joueur commence
traditionnellement avec un mu à 25, et un Sigma à 25/3. Le score
d'un joueur est ensuite calculé en faisant mu-(3*sigma). C'est ce
qu'on voit afficher dans le leaderboard. Un nouveau joueur commence
donc avec un score de zero. Après chaque rencontre, on donne a
trueskill les valeurs de mu et sigma des joueurs qui se sont
affrontés, ainsi que le résultat de la rencontre. Il nous redonne
alors les nouvelles valeurs de mu et sigma de chacun. On peut donc en
déduire leur nouveau score.
Expérience
1
Ca
me semblais trop complexe d'estimer le niveau réel d'IA sur un jeu
simple, j'ai donc pris le parti de fixer le niveau des joueurs
(niveau réel), et de les faires jouer a un jeu dont le résultat est
défini en fonction de ce niveau afin de faire classer trueSkill ces
joueurs. Il n'y a donc aucun jeu derrière ces tests, mais ils
permettent par contre de voir l'influence de certaines
caractéristiques sur le résultat final d'un leaderboard.
Les
premiers tests que j'ai fait sont de considérer que l'IA qui a le
niveau réel le plus fort l'emporte toujours. J'ai donc pris 10
joueurs, P0 à P9, P9 étant le plus fort. P9 gagnera donc toujours
tous ses matchs, P8 gagnera contre tout le monde sauf P9, P0 perdra
toujours etc. Il faut ensuite choisir les matchs à jouer. J'ai donc
choisi de faire jouer en priorité le joueur qui avait fait le moins
de matchs. Ses adversaires sont alors pris aléatoirement en fonction
de leur score trueskill au moment de choisir le match avec un écart
de classement de +/- 5 places (donc le dernier joue seulement contre
les 5 derniers, le premier contre les 5 premiers, le 4e contre tout
le monde sauf le dernier etc). Cette stratégie permet de garantir un
nombre de match équitable à chaque IA, et dans les cas réels,
garantie aussi que le match est intéressant (il n'y a pas grand
intérêt a faire jouer le premier contre le dernier...)
En
faisant jouer 1000 matchs à chaque IA, j'obtiens alors les courbes
suivantes pour le score de chaque joueur:
Plutôt
pas mal non :) ?
Experience
2
Mais
bon dans la vrai vie, le premier ne gagne pas toujours, le dernier ne
perds pas toujours (si si, même ceux qui crashent toujours crashent
moins vite si ils ne crashent pas en premier :) ). Je me suis donc
dis qu'il serais bien d'ajouter un peu d'aléatoire sur les résultats
des matchs, tout en conservant une plus grande probabilité de
victoire pour le meilleur.
Si
on a deux joueurs avec des niveaux j1 et j2, J'ai choisi (et c'est
très certainement perfectible) que:
la
probabilité que j1 gagne seras:j1/(j1+j2)
la
probabilité que j2 gagne seras:j2/(j1+j2)
Si
on prends des exemples numériques avec j1=5 et j2=9, ça donne:
j1
gagne dans 5/14, et j2 gagne dans 9/14
Si
on a j1=1, j2=9, alors j1 gagne 1 fois sur 10 etc
En
faisant jouer 1000 matchs par IA, on obtiens alors les courbes
suivantes pour les scores de chaque joueur:
Gasp...
C'est loin de se stabiliser lorsque les niveaux des bots sont très
proches même malgré une augmentation du nombre de match.
En
fait c'est tout a fait logique : TrueSkill s’attend a une
probabilité de victoire en fonction du sigma et du mu de chaque
joueur. Or lorsqu'il fait le réajustement, progressivement, plus les
matchs sont éloignés, moins ils comptent dans le score final. L'IA
est donc classé par rapport a ses derniers matchs (difficile
d'évaluer un nombre exact). TrueSkill étant utilisé sur des
humains, c'est fiable dans le sens ou le niveau de chaque joueur
varie avec le temps, et il est donc normal que les résultats des
matchs anciens soient progressivement oubliés.
Cependant
nous ici quand on classe des programmes, tous les matchs ont la même
valeur.
Comment
on pourrais changer ça? Simplement en faisant la moyenne des
estimations trueskill : les matchs passés sont certes
progressivement oubliés pour établir le skill courant, mais
continuent d'être comptabilisés pour le skill final. Si on reprends
le chart précédent et qu'on fait la moyenne de tous les scores
calculés lors des itérations précédentes, on obtiens ça:
A
partir de 200/300 matchs par IA, non seulement on a les IA dans le
bon ordre, mais en plus, ça deviens très stable! Il n'y a plus de
variations de dernière minutes si frustrantes pour nos nerfs
:)
Expérience
3
Souvent
on a été frustré de devoir attendre que son IA remonte dans le
classement avant de voir si elle s’améliorait ou non. Qu'est ce
que ça donnerais si on ne remettais pas a 0 l’évaluation
trueSkill de notre bot? Imaginons que j'améliore mon bot: l'IA 7 a
fait une super mise a jour, et est donc maintenant la plus forte avec
un skill de 11:
On
observe bien une progression de l'IA, qui en une centaine de matchs a
pris sa position dans les meilleurs.
Ne
serait t'il pas préférable de faire un reset de l'IA lors de la
remise dans l'arène, et lui faire jouer beaucoup de matchs (c'est
comme ça qu'on était évalué sur tron et game of thrones)? Si je
fait un reset du skill d'une IA après que chacune en ais joué 500,
puis que je la remet dans l'arène pour 500 matchs où elle participe
à tous les matchs, ça donne ça:
L'IA
reviens rapidement autour de son classement réel si elle a
suffisament de matchs (~250 matchs), et arrive même a le dépasser a
force de jouer contre des IA plus faibles, et accumuler des victoires
pendant que les autres jouent beaucoup moins...
Conclusion
Mon
objectif n'est pas de remettre en question les classements des deux
précédents concours (les trois premiers de game of drones sont non
seulement largement devant, mais n'ont pas remis a jour au dernier
moment, et avaient donc suffisamment de matchs pour avoir un
classement stable), mais plutot de s'assurer que les prochains auront
un déroulement plus équitable, et des résultats plus stables. Si
j'avais le sentiment sur tron d'avoir été sous évalué, sur game
of drones c'est plutot l'inverse :D
En
conclusion, si j'avais des recommandations a faire, j'utiliserais
trueskill de la manière suivante:
Lors
des phase de qualifications, on souhaite avoir un ordre de grandeur
du niveau de notre IA. Lorsqu'on remet a jour on souhaite un feedback
rapide contre des IA de notre niveau. Je ne remettrais donc pas a
zéro les valeurs de mu et sigma de trueSkill. Dans l'idéal je
ferais jouer des matchs en continue a toutes les IA afin de garantir
un nombre de matchs équitables, mais si ça consomme trop de CPU,
lancer des matchs avec la nouvelle IA, sans remettre a zero ses
caractéristiques trueskill me parait raisonnable.
Pour
les phases finales, et afin d'avoir un résultat stable, il faut
remettre toutes les IA a zero (on est aussi certains que d'anciens
matchs contre des IA qui n'existent plus ne sont pas comptabilisés).
Puis toujours en répartissant les matchs sur les joueurs, on calcule
le score en faisant une moyenne du score trueskill sur tous les
matchs qui ont été joués. Ca devrait garantir une certaine
stabilité dans le classement final.
Vos
commentaires sont évidement les bienvenus. Des que j'ai du temps je
poste le code que j'ai utilisé pour obtenir ces résultats
:)
A+
Manwe
En lisant ton message, je me suis aussi dis que comme c'est fait aujourd'hui, comme il n'y a pas de remise à zéro, les matchs contre des IA qui n'existent plus sont tout de même comptabilisés.
Salut,
J'ai retravaillé mon outil pour faire des tests avec
trueskill. Il y a une interface graphique faite en JavaFX, et on peut
donc expérimenter pas mal de choses. En particulier, on peut choisir les
probabilités de victoires de chaque adversaires a partir d'un fichier.
On peut augmenter ou diminuer le nombre de joueurs.
Par exemple, avec le fichier suivant:
;P1;P2;P3
P1;0;1;0.5
P2;0;0;0.8
P3;0.5;0.2;0
On
a défini trois joueurs, P1, P2 et P3. Quand P1 oue contre P2, il gagne à
chaque fois, quand P1 joue contre P3, il a une chance sur deux de
gagner. Quand P2 joue contre P3, il a 80% de chances de gagner.
Attention,
vous pouvez parfaitement configurer des probabilités différentes
lorsque le joueur 1 joue contre le joueur 2 ou le joueur 2 joue contre
le joueur 1!
Ensuite quand on lance les matchs on obtient ça en quelques secondes: