locked
Vector creation problem RRS feed

  • Question

  • Hello Infer.Net community,

    I've been trying to build an Infer.Net model where I first train the model to predict a set of observed values (The percentage of points a player has won in a game) and then build a Bayes Point Machine taking those predicted values as inputs to classify the data (Determine whether the player won the match). The problem I have is that I'm not sure how to go about creating the vector from the predicted values as they are a Variable<double>[] array instead of a double[] array that is used in the BPM example. Below is the code I've tried to do this which doesn't work:

            string[] Skills = new string[] { "P1S", "P1R", "P2S", "P2R" };
            Dictionary<string, Variable<Gaussian>> SkillPrior = new Dictionary<string, Variable<Gaussian>>();
            Dictionary<string, Variable<double>> SkillPriorPlusTau = new Dictionary<string, Variable<double>>();
            Dictionary<string, Variable<double>> Skill = new Dictionary<string, Variable<double>>();
            Dictionary<string, Variable<double>> Performance = new Dictionary<string, Variable<double>>();
            Variable<double> P1PointsWinPercentage;
            Variable<double> P2PointsWinPercentage;
            Variable<Vector> weights = Variable.Random(new VectorGaussian(Vector.Zero(2), PositiveDefiniteMatrix.Identity(2)));
            VariableArray<bool> PWin;
            InferenceEngine engine = new InferenceEngine(new ExpectationPropagation());
    
            public TrueSkill_BPM_Model(double beta, double tau, double noise) //Build model
            {
                foreach (string i in Skills)
                {
                    SkillPrior[i] = Variable.New<Gaussian>();
                    SkillPriorPlusTau[i] = Variable.Random<double, Gaussian>(SkillPrior[i]);
                    Skill[i] = Variable.GaussianFromMeanAndVariance(SkillPriorPlusTau[i], tau);
                    Performance[i] = Variable.GaussianFromMeanAndVariance(Skill[i], beta);
                }
                P1PointsWinPercentage = Performance["P1S"] - Performance["P2R"];
                P2PointsWinPercentage = Performance["P2S"] - Performance["P1R"];
                Variable<double>[] PDiff = new Variable<double>[1];
                PDiff[0] = P1PointsWinPercentage - P2PointsWinPercentage;
                PDiff[1] = P2PointsWinPercentage - P1PointsWinPercentage;
                Variable<Vector>[] PDiffVec = new Variable<Vector>[PDiff.Length];
                for (int i = 0; i < PDiffVec.Length; i++)
                    PDiffVec[i] = Variable<Vector>.Vector(PDiff[i], 1);
                PWin[0] = Variable.GaussianFromMeanAndVariance(Variable.InnerProduct(PDiffVec[0], weights), noise) > 0;
                PWin[1] = Variable.GaussianFromMeanAndVariance(Variable.InnerProduct(PDiffVec[1], weights), noise) > 0;
            }

    Please can someone advise how to modify this code so the Vector creation line:

    PDiffVec[i] = Variable<Vector>.Vector(PDiff[i], 1);

    Works as intended?

    Thanks in advance!


    Monday, May 19, 2014 12:30 AM

Answers

  • In these lines:

    P1Win = true;
    P2Win = false;
    

    I think you meant to say:

    P1Win.ObservedValue = true;
    P2Win.ObservedValue = false;
    

    Also, you should be able to re-use the model instead of creating a new one for each match.

    • Marked as answer by MarkG87 Tuesday, June 3, 2014 3:22 PM
    Monday, May 19, 2014 2:04 PM
    Owner
  • Use two instances of the model, one where these values are observed and one where they are not, and send your queries to the appropriate model.
    • Marked as answer by MarkG87 Tuesday, June 3, 2014 3:22 PM
    Monday, May 19, 2014 2:45 PM
    Owner
  • PDiffVec has length 1 but weights has length 2, so you can't take their inner product. What should the other weight get multiplied by? If you just want to have a slope and intercept term, you can write:

    PWin[0] = Variable.GaussianFromMeanAndVariance(PDiff[0]*slope + intercept, noise) > 0;


    where slope and intercept are the unknown parameters.
    Monday, May 19, 2014 9:10 AM
    Owner
  • Note that you'll have a product of two stochastic inputs, and you might want to consider using VMP for this factor. Look at how the problem is handled in the recommender example.

    • Marked as answer by MarkG87 Tuesday, June 3, 2014 3:22 PM
    Monday, May 19, 2014 10:47 AM

All replies

  • PDiffVec has length 1 but weights has length 2, so you can't take their inner product. What should the other weight get multiplied by? If you just want to have a slope and intercept term, you can write:

    PWin[0] = Variable.GaussianFromMeanAndVariance(PDiff[0]*slope + intercept, noise) > 0;


    where slope and intercept are the unknown parameters.
    Monday, May 19, 2014 9:10 AM
    Owner
  • Note that you'll have a product of two stochastic inputs, and you might want to consider using VMP for this factor. Look at how the problem is handled in the recommender example.

    • Marked as answer by MarkG87 Tuesday, June 3, 2014 3:22 PM
    Monday, May 19, 2014 10:47 AM
  • Thanks very much Tom,

    I had tried that before but I run into problems when inferring the values of slope + intercept (labelled weight + constant in my code below) - whenever I run inference the values for each doesn't change. I figured it was to something to do with the fact I was using two separate variables and asking to infer each separately rather than a single VectorGaussian. The skill parameters otherwise infer fine. What am I doing wrong in the code below? (As a side note - is there a better way for me to 'reset' the model's ObservedValues than calling a new model each time as I do below?)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using MicrosoftResearch.Infer.Models;
    using MicrosoftResearch.Infer.Distributions;
    using MicrosoftResearch.Infer;
    using MicrosoftResearch.Infer.Maths;
    using FileHelpers;
    
    namespace TrueSkill_BPM
    {
        [DelimitedRecord(",")]
        public class Data
        {
            public string DATE;
            public int ID1;
            public int ID2;
            public string RESULT;
            public double SPP1;
            public double SPP2;
        }
        class TrueSkill_BPM_Model
        {
            // Define the variables
            string[] Skills = new string[] { "P1S", "P1R", "P2S", "P2R" };
            Dictionary<string, Variable<Gaussian>> SkillPrior = new Dictionary<string, Variable<Gaussian>>();
            Dictionary<string, Variable<double>> SkillPriorPlusTau = new Dictionary<string, Variable<double>>();
            Dictionary<string, Variable<double>> Skill = new Dictionary<string, Variable<double>>();
            Dictionary<string, Variable<double>> Performance = new Dictionary<string, Variable<double>>();
            Variable<double> P1PointsWinPercentage;
            Variable<double> P2PointsWinPercentage;
            Variable<Gaussian> WeightPrior;
            Variable<Gaussian> ConstantPrior;
            Variable<double> weight;
            Variable<double> constant;
            Variable<bool> P1Win;
            Variable<bool> P2Win;
            InferenceEngine engine = new InferenceEngine(new ExpectationPropagation());
    
            public TrueSkill_BPM_Model(double beta, double tau, double noise) //Build model
            {
                foreach (string i in Skills)
                {
                    SkillPrior[i] = Variable.New<Gaussian>();
                    SkillPriorPlusTau[i] = Variable.Random<double, Gaussian>(SkillPrior[i]);
                    Skill[i] = Variable.GaussianFromMeanAndVariance(SkillPriorPlusTau[i], tau);
                    Performance[i] = Variable.GaussianFromMeanAndVariance(Skill[i], beta);
                }
                P1PointsWinPercentage = Performance["P1S"] - Performance["P2R"];
                P2PointsWinPercentage = Performance["P2S"] - Performance["P1R"];
                WeightPrior = Variable.New<Gaussian>();
                ConstantPrior = Variable.New<Gaussian>();
                weight = Variable.Random<double, Gaussian>(WeightPrior);
                constant = Variable.Random<double, Gaussian>(ConstantPrior);
                P1Win = Variable.GaussianFromMeanAndVariance((weight * (P1PointsWinPercentage - P2PointsWinPercentage) + constant), noise) > 0;
                P2Win = Variable.GaussianFromMeanAndVariance((weight * (P2PointsWinPercentage - P1PointsWinPercentage) + constant), noise) > 0;
            }
            public Dictionary<string, Gaussian> InferSkills(Dictionary<string, Gaussian> PriorSkills, double P1SP, double P2SP, Gaussian w, Gaussian c)
            {
                //Set up Observed Priors
                foreach (KeyValuePair<string, Gaussian> Prior in PriorSkills)
                {
                    SkillPrior[Prior.Key].ObservedValue = Prior.Value;
                }
                //Set Observed Outcomes
                P1PointsWinPercentage.ObservedValue = P1SP;
                P2PointsWinPercentage.ObservedValue = P2SP;
                WeightPrior.ObservedValue = w;
                ConstantPrior.ObservedValue = c;
                P1Win = true;
                P2Win = false;
                //Infer Posterior Value
                Dictionary<string, Gaussian> SkillsPosterior = new Dictionary<string, Gaussian>();
                foreach (KeyValuePair<string, Gaussian> Prior in PriorSkills)
                {
                    SkillsPosterior[Prior.Key] = engine.Infer<Gaussian>(Skill[Prior.Key]);
                }
                return SkillsPosterior;
            }
            public Gaussian InferWeight(Dictionary<string, Gaussian> PriorSkills, double P1SP, double P2SP, Gaussian w, Gaussian c)
            {
                //Set up Observed Priors
                foreach (KeyValuePair<string, Gaussian> Prior in PriorSkills)
                {
                    SkillPrior[Prior.Key].ObservedValue = Prior.Value;
                }
                //Set Observed Outcomes
                P1PointsWinPercentage.ObservedValue = P1SP;
                P2PointsWinPercentage.ObservedValue = P2SP;
                WeightPrior.ObservedValue = w;
                ConstantPrior.ObservedValue = c;
                P1Win = true;
                P2Win = false;
                //Infer Posterior Value
                Gaussian InferWeights = engine.Infer<Gaussian>(weight);
                return InferWeights;
            }
            public Gaussian InferConstant(Dictionary<string, Gaussian> PriorSkills, double P1SP, double P2SP, Gaussian w, Gaussian c)
            {
                //Set up Observed Priors
                foreach (KeyValuePair<string, Gaussian> Prior in PriorSkills)
                {
                    SkillPrior[Prior.Key].ObservedValue = Prior.Value;
                }
                //Set Observed Outcomes
                P1PointsWinPercentage.ObservedValue = P1SP;
                P2PointsWinPercentage.ObservedValue = P2SP;
                WeightPrior.ObservedValue = w;
                ConstantPrior.ObservedValue = c;
                P1Win = true;
                P2Win = false;
                //Infer Posterior Value
                Gaussian InferConstants = engine.Infer<Gaussian>(constant);
                return InferConstants;
            }
            public Gaussian InferP1SP(Dictionary<string, Gaussian> PriorSkills, Gaussian w, Gaussian c)
            {
                //Set up Observed Priors
                foreach (KeyValuePair<string, Gaussian> Prior in PriorSkills)
                {
                    SkillPrior[Prior.Key].ObservedValue = Prior.Value;
                }
                WeightPrior.ObservedValue = w;
                ConstantPrior.ObservedValue = c;
                //Infer Posterior Value
                Gaussian InferedP1SP = engine.Infer<Gaussian>(P1PointsWinPercentage);
                return InferedP1SP;
            }
            public Gaussian InferP2SP(Dictionary<string, Gaussian> PriorSkills, Gaussian w, Gaussian c)
            {
                //Set up Observed Priors
                foreach (KeyValuePair<string, Gaussian> Prior in PriorSkills)
                {
                    SkillPrior[Prior.Key].ObservedValue = Prior.Value;
                }
                WeightPrior.ObservedValue = w;
                ConstantPrior.ObservedValue = c;
                //Infer Posterior Value
                Gaussian InferedP2SP = engine.Infer<Gaussian>(P2PointsWinPercentage);
                return InferedP2SP;
            }
            public Bernoulli InferP1Win(Dictionary<string, Gaussian> PriorSkills, Gaussian w, Gaussian c)
            {
                //Set up Observed Priors
                foreach (KeyValuePair<string, Gaussian> Prior in PriorSkills)
                {
                    SkillPrior[Prior.Key].ObservedValue = Prior.Value;
                }
                WeightPrior.ObservedValue = w;
                ConstantPrior.ObservedValue = c;
                //Infer Posterior Value
                Bernoulli InferedP1Win= engine.Infer<Bernoulli>(P1Win);
                return InferedP1Win;
            }
            public Bernoulli InferP2Win(Dictionary<string, Gaussian> PriorSkills, Gaussian w, Gaussian c)
            {
                //Set up Observed Priors
                foreach (KeyValuePair<string, Gaussian> Prior in PriorSkills)
                {
                    SkillPrior[Prior.Key].ObservedValue = Prior.Value;
                }
                WeightPrior.ObservedValue = w;
                ConstantPrior.ObservedValue = c;
                //Infer Posterior Value
                Bernoulli InferedP2Win= engine.Infer<Bernoulli>(P2Win);
                return InferedP2Win;
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                //var model = new TrueSkill_BPM_Model(0.1,0.01,0.1);
                var runcount = new double();
                runcount = 0;
                var PSSkills = new Dictionary<double, Gaussian>();
                var PRSkills = new Dictionary<double, Gaussian>();
                var CurrentPriorSkills = new Dictionary<string, Gaussian>();
                // Initialise starting values for Weight and Constant
                var CurrentWeight = new Gaussian();
                var CurrentConstant = new Gaussian();
                CurrentWeight = Gaussian.FromMeanAndVariance(0, 1);
                CurrentConstant = Gaussian.FromMeanAndVariance(0, 1);
                //Match results - IDX: The ID of Player 1/2, SPPX: point win percantage observed, Player 1 is always the winner
                var FHengine = new FileHelperEngine<Data>();
                var matches = FHengine.ReadFile("testdata.csv");
                //Cycle through the matches
                foreach (var match in matches)
                {
                    //Check if we already have a Gaussian for each player skill and use that, else set a default value
                    var model = new TrueSkill_BPM_Model(0.1, 0.01, 0.1);
                    if (PSSkills.ContainsKey(match.ID1))
                        CurrentPriorSkills["P1S"] = PSSkills[match.ID1];
                    else
                        CurrentPriorSkills["P1S"] = Gaussian.FromMeanAndVariance(1.3, 1);
                    if (PSSkills.ContainsKey(match.ID2))
                        CurrentPriorSkills["P2S"] = PSSkills[match.ID2];
                    else
                        CurrentPriorSkills["P2S"] = Gaussian.FromMeanAndVariance(1.3, 1);
                    if (PRSkills.ContainsKey(match.ID1))
                        CurrentPriorSkills["P1R"] = PRSkills[match.ID1];
                    else
                        CurrentPriorSkills["P1R"] = Gaussian.FromMeanAndVariance(0.65, 1);
                    if (PRSkills.ContainsKey(match.ID2))
                        CurrentPriorSkills["P2R"] = PRSkills[match.ID2];
                    else
                        CurrentPriorSkills["P2R"] = Gaussian.FromMeanAndVariance(0.65, 1);
                    //Give estimates of values
                    Gaussian P1SPEstimate = model.InferP1SP(CurrentPriorSkills, CurrentWeight, CurrentConstant);
                    Gaussian P2SPEstimate = model.InferP2SP(CurrentPriorSkills, CurrentWeight, CurrentConstant);
                    Bernoulli P1WinEstimate = model.InferP1Win(CurrentPriorSkills, CurrentWeight, CurrentConstant);
                    Bernoulli P2WinEstimate = model.InferP2Win(CurrentPriorSkills, CurrentWeight, CurrentConstant);
                    Console.WriteLine("P1SP Estimate: {0} Actual: {1}", P1SPEstimate, match.SPP1);
                    Console.WriteLine("P2SP Estimate: {0} Actual: {1}", P2SPEstimate, match.SPP2);
                    Console.WriteLine("P1 Win Estimate: {0}", P1WinEstimate);
                    Console.WriteLine("P2 Win Estimate: {0}", P2WinEstimate);
                    //Perform Inference and Update Skills & Weights
                    Dictionary<string, Gaussian> updatedSkills = model.InferSkills(CurrentPriorSkills, match.SPP1, match.SPP2, CurrentWeight, CurrentConstant);
                    Console.WriteLine("Updated Skills: P1S: {0}, P1R: {1}, P2S: {2}, P2R: {3}", updatedSkills["P1S"], updatedSkills["P1R"], updatedSkills["P2S"], updatedSkills["P2R"]);
                    Gaussian updatedWeight = model.InferWeight(CurrentPriorSkills, match.SPP1, match.SPP2, CurrentWeight, CurrentConstant);
                    Gaussian updatedConstant = model.InferConstant(CurrentPriorSkills, match.SPP1, match.SPP2, CurrentWeight, CurrentConstant);
                    Console.WriteLine("Weight: {0}", updatedWeight);
                    Console.WriteLine("Constant: {0}", updatedConstant);
                    PSSkills[match.ID1] = updatedSkills["P1S"];
                    PSSkills[match.ID2] = updatedSkills["P2S"];
                    PRSkills[match.ID1] = updatedSkills["P1R"];
                    PRSkills[match.ID2] = updatedSkills["P2R"];
                    CurrentWeight = updatedWeight;
                    CurrentConstant = updatedConstant;
                    runcount = runcount + 1;
                    Console.WriteLine("Runcount: {0}", runcount);
                }
                while (true)
                {
    
                }
            }
        }
    }
    

    Monday, May 19, 2014 11:43 AM
  • Thanks very much Yordan - I'll take a look at that example now.
    Monday, May 19, 2014 11:44 AM
  • In these lines:

    P1Win = true;
    P2Win = false;
    

    I think you meant to say:

    P1Win.ObservedValue = true;
    P2Win.ObservedValue = false;
    

    Also, you should be able to re-use the model instead of creating a new one for each match.

    • Marked as answer by MarkG87 Tuesday, June 3, 2014 3:22 PM
    Monday, May 19, 2014 2:04 PM
    Owner
  • Tom,

    Ah yes, changing it to ObservedValues has fixed that problem and it infers correctly! Thanks very much.

    In terms of re-using the model - when I comment out the line:

    var model = new TrueSkill_BPM_Model(0.1, 0.01, 0.1);

    Which is within the match loop and uncomment out the one outside it runs much faster as it's not recompiling the model each time however the problem is that when I try and infer the next match's P1Win/P2Win and the P1/P2PointsWinPercentage the values it returns are simply the ObservedValues I specified in the previous match; I figure I need to 'reset' the ObservedValues each time but I tried setting them to null and this returns an error (null is the wrong type). Is there a more efficient way to unset the ObservedValues without needing to re-call the model (and hence trigger the re-compiling of the model) as I'm doing in the match loop?

    Monday, May 19, 2014 2:40 PM
  • Use two instances of the model, one where these values are observed and one where they are not, and send your queries to the appropriate model.
    • Marked as answer by MarkG87 Tuesday, June 3, 2014 3:22 PM
    Monday, May 19, 2014 2:45 PM
    Owner
  • Ah yes of course - that works well now, thanks very much Tom!
    Monday, May 19, 2014 2:58 PM