Answered by:
Vector creation problem
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 reuse 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 PMOwner 
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 PMOwner 
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. Edited by Tom MinkaMicrosoft employee, Owner Monday, May 19, 2014 9:11 AM
 Marked as answer by MarkG87 Tuesday, June 3, 2014 3:22 PM
Monday, May 19, 2014 9:10 AMOwner 
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. Edited by Tom MinkaMicrosoft employee, Owner Monday, May 19, 2014 9:11 AM
 Marked as answer by MarkG87 Tuesday, June 3, 2014 3:22 PM
Monday, May 19, 2014 9:10 AMOwner 
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 reuse 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 PMOwner 
Tom,
Ah yes, changing it to ObservedValues has fixed that problem and it infers correctly! Thanks very much.
In terms of reusing 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 recall the model (and hence trigger the recompiling 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 PMOwner 
Ah yes of course  that works well now, thanks very much Tom!Monday, May 19, 2014 2:58 PM