locked
Modifying Trueskill model RRS feed

  • Question

  • Hi everyone,

    My model is based on TrueSkill but I want to modify a little bit. In my model, each game has a group of players and the number of players in one game is not fixed, it could change. One player is considered as a winner if he win all the other players who join this game. For this reason, the differences between the skill of winner and all opponents are considered. My model is declared in the below part

    namespace Testing
    {
        class Model
        {
            Variable<int> nPlayers = Variable.New<int>().Named("nPlayers");
            Variable<int> nGames = Variable.New<int>().Named("nGames");
            InferenceEngine engine = new InferenceEngine();
            VariableArray<Gaussian> SkillPrior;
            VariableArray<double> Skill;
            VariableArray<VariableArray<int>, int[][]> observedLoser;
            VariableArray<int> observedWinner;
            VariableArray<int> numOfLosers; //number of losers in each game
    
            public Model()
            {
                InferenceEngine.DefaultEngine.ShowFactorGraph = true;
                
                Range rangeOfPlayers = new Range(nPlayers).Named("range of players");
                Range rangeOfGames = new Range(nGames).Named("range of games");
                observedWinner = Variable.Array<int>(rangeOfGames).Named("winner");
                numOfLosers = Variable.Array<int>(rangeOfGames);
                Range rangeOfLosers = new Range(numOfLosers[rangeOfGames]).Named("losers");
                observedLoser = Variable.Array(Variable.Array<int>(rangeOfLosers), rangeOfGames).Named("loser");
                SkillPrior = Variable.Array<Gaussian>(rangeOfPlayers).Named("SkillPrior");
                Skill = Variable.Array<double>(rangeOfPlayers).Named("Skill");
                Skill[rangeOfPlayers] = Variable.Random<double, Gaussian>(SkillPrior[rangeOfPlayers]);
                
                Range rangeOfLoserEachGame = observedLoser[rangeOfGames].Range;
                Variable.ConstrainPositive(Skill[observedWinner[rangeOfGames]] - Skill[observedLoser[rangeOfGames][rangeOfLoserEachGame]]);
                
            }
    
            public Gaussian[] Infer(int numOfPlayer, int numOfGames, Gaussian[] priors, int[] winner, int[][] losers)
            {
                nPlayers.ObservedValue = numOfPlayer;
                nGames.ObservedValue = winner.Length;
                SkillPrior.ObservedValue = priors;
                observedWinner.ObservedValue = winner;
                observedLoser.ObservedValue = losers;
                numOfLosers.ObservedValue = getNumOfLoserEachGame(losers);//length of loser for each game
    
                engine = new InferenceEngine();
                Gaussian[] SkillPostr = new Gaussian[numOfPlayer];
                for (int i = 0; i < numOfPlayer; i++)
                    SkillPostr[i] = engine.Infer<Gaussian>(Skill[i]);
                
                return SkillPostr;
            }
    
            private int[] getNumOfLoserEachGame(int[][] losers)
            {
                int[] result = new int[losers.Length];
                for (int i = 0; i < losers.Length; i++)
                {
                    result[i] = losers[i].Length;
                }
                return result;
            }
        }
    }

    In this code, winner[i] could be equal to winner[j] when i != j because this player is the best player in 2 different games.

    However, when I try to do inference using Expectation Propagation there is an exception here.

    Unhandled Exception: System.ArgumentException: This class was not built to infer
     Skill_vint10_

    Would you please help me to fix this problem?

    Thanks and best regards,

    Nam



    • Edited by Nam Doan Friday, June 14, 2013 11:04 AM fix some typo
    Friday, June 14, 2013 11:02 AM

Answers

  • Hi Nam

    TrueSkill has both a skill variable for each player, and a performance variable for each player in a game. The performance is a noised up version of the skill. This is important because it allows a less skilful player to beat a more skilful player on occasion. If you don't have it you may well end up with impossible zero-probability situations. So try putting in a performance variable as follows:

    using (Variable.ForEach(rangeOfGames))
    {
        var performance = Variable<double>.Array(rangeOfPlayers);
        using (Variable.ForEach(rangeOfPlayers))
        {
            performance[rangeOfPlayers] = Variable.GaussianFromMeanAndPrecision(Skill[rangeOfPlayers], beta);
        }
    
        Variable.ConstrainPositive(performance[observedWinner[rangeOfGames]] - performance[observedLoser[rangeOfGames][rangeOfLosers]]);
    }
    where beta is a hyper-parameter (to avoid model recompilation you can make beta a Variable<double> and observe it.)

    John

    • Marked as answer by Nam Doan Tuesday, June 25, 2013 2:16 AM
    Monday, June 24, 2013 4:36 PM
    Owner

All replies

  • Hi Nam

    You cannot infer an individual element of a VariableArray. Instead, infer the whole array directly: 

    Gaussian[] SkillPostr = engine.Infer<Gaussian[]>(Skill);
    Monday, June 17, 2013 9:33 AM
    Owner
  • Hi John,

    Thank you for your response. I dont usually update this thread so dont know your answer. Sorry about that.

    After applying your recommendation, my program now run without this error but it throws another exception

    Unhandled Exception: MicrosoftResearch.Infer.Maths.AllZeroException: The model has zero probability

    My model contains nearly 600 players and around 36 000 games (the players in each game are also defined.) Would you please help me to fix this exception?

    Thanks,

    Nam.

    Monday, June 24, 2013 2:26 PM
  • Hi Nam

    TrueSkill has both a skill variable for each player, and a performance variable for each player in a game. The performance is a noised up version of the skill. This is important because it allows a less skilful player to beat a more skilful player on occasion. If you don't have it you may well end up with impossible zero-probability situations. So try putting in a performance variable as follows:

    using (Variable.ForEach(rangeOfGames))
    {
        var performance = Variable<double>.Array(rangeOfPlayers);
        using (Variable.ForEach(rangeOfPlayers))
        {
            performance[rangeOfPlayers] = Variable.GaussianFromMeanAndPrecision(Skill[rangeOfPlayers], beta);
        }
    
        Variable.ConstrainPositive(performance[observedWinner[rangeOfGames]] - performance[observedLoser[rangeOfGames][rangeOfLosers]]);
    }
    where beta is a hyper-parameter (to avoid model recompilation you can make beta a Variable<double> and observe it.)

    John

    • Marked as answer by Nam Doan Tuesday, June 25, 2013 2:16 AM
    Monday, June 24, 2013 4:36 PM
    Owner
  • Thank John for your support. I have marked your response as the answer for my question.

    Best regards,

    Nam

    Tuesday, June 25, 2013 2:17 AM