locked
Correlated trueskill with poisson(exp(skill difference)) factor? RRS feed

  • Question

  • Each player has both offence and defence rating.

    My prior X  (Variable<Vector>) is a multivariate normal variable of 2* N variables,  which is of the form (o1, o2, ... oN, d1, d2, .. dN) where N is the number of players, o1 is offence rating of player1, dN is defence rating of playerN.

    Each match has 2 outcomes which is similar to basketball scores, which is assumed to be of Poisson (Exp (oA - dB)), and Poisson(Exp (oB - dA)).


    So far, I have encountered such problems:

    1.  I need to build a factor to represent oA - dB, so I guess it is just a matrix M times X, where M is of the form

    (1, 0, 0, ..., 0, -1, -1,..., -1)

    (0, 1, 0, ..., 0, -1, -1,..., -1)

    ...

    (0, 0, 0, ...1, 0, -1, -1,..., -1)

    (0, 0, 0, ...0, 1, -1, -1,..., -1)

    So that the result of multiplication is 

    (o1 - d1, o1 - d2, ... o1 - dN)

    ...

    (oN - d1, oN - d2, ... oN - dN)

    So my Matrix is 

        myMatrix = 
            let left = Array2D.init N N (fun i j -> if i = j then 1.0 else 0.0)
            let right = Array2D.create N N -1.0
            let ret = Array2D.init N (2 * N) (fun i j -> if j < N then left.[i,j] else right.[i, j-N])
            new Matrix(ret)

    when I would like to apply the factor, I tried:

        let B = Variable.MatrixTimesVector(myMatrix, X)

    It doesn't work since myMatrix is not of type Variable<Matrix>

    I also tried let B = Variable.Factor(Factor.Product, myMatrix, X), it doesn't work.

    2. I am unable to apply Poisson (Exp (..) ) factor to B piecewisely.  Do I have to convert the matrix variable B into VarrayArray and then apply the factor?I know I can convert a Variable<Vector> into VariableArray via Variable.ArrayFromVector, but not for a Matrix. Maybe I should convert the prior X into Variable<Vector> in the first place?




    • Edited by colinfang Wednesday, October 8, 2014 12:39 PM
    Wednesday, October 8, 2014 12:14 PM

Answers

  • You can do it like this:

                var indexA = Variable.Observed(0);
                var indexB = Variable.Observed(1);
                Range r = new Range(4);
                var indicesAB = Variable.Array<double>(r);
                using (var fb = Variable.ForEach(r))
                {
                    var i = fb.Index;
                    var isA = (i == indexA) & true;
                    using (Variable.If(isA))
                    {
                        indicesAB[i] = 1;
                    }
                    using (Variable.IfNot(isA))
                    {
                        var isB = (i == indexB) & true;
                        using (Variable.If(isB))
                        {
                            indicesAB[i] = -1;
                        }
                        using (Variable.IfNot(isB))
                        {
                            indicesAB[i] = 0;
                        }
                    }
                }
                var indicesABVector = Variable.Vector(indicesAB);
    
                InferenceEngine engine = new InferenceEngine();
                Console.WriteLine(engine.Infer(indicesABVector));
    

    The silly '& true' bits are to work-around a bug in the current version of Infer.NET.
    • Marked as answer by colinfang Thursday, October 9, 2014 10:17 PM
    Thursday, October 9, 2014 5:28 PM
    Owner

All replies

  • To get oA-dB, use Variable.InnerProduct.  Make a Vector containing a 1 at A, -1 at B, and rest zero.  Matrix multiply doesn't help you here.
    Wednesday, October 8, 2014 12:32 PM
    Owner
  • This post might be useful.
    Wednesday, October 8, 2014 2:02 PM
  •     scoreA.[rangeMatches] <- Variable.Poisson (Variable.Exp (Variable.InnerProduct(od, indicesABVector.[rangeMatches]) ))
        scoreB.[rangeMatches] <- Variable.Poisson (Variable.Exp (Variable.InnerProduct(od, indicesBAVector.[rangeMatches]) ))


    where od is the multivariate normal variable, indicesABVector is a VariableArray<Vector>, 1 at A and -1 at B, rest zero.

    Currently I set the observedvalues of both manually, 

        let buildIndicesABVector game =
                let indexA = nameIndex.[game.PlayerA]
                let indexB = nameIndex.[game.PlayerB]
                let ret = Array.zeroCreate (2 * numPlayers)
                ret.[indexA] <- 1.0
                ret.[indexB + numPlayers] <- -1.0
                Vector.FromArray(ret)

        let buildIndicesBAVector game =
                let indexA = nameIndex.[game.PlayerA]
                let indexB = nameIndex.[game.PlayerB]
                let ret = Array.zeroCreate (2 * numPlayers)
                ret.[indexB] <- 1.0
                ret.[indexA + numPlayers] <- -1.0
                Vector.FromArray(ret)

        indicesABVector.ObservedValue <- matches |> Array.map buildIndicesABVector
        indicesBAVector.ObservedValue <- matches |> Array.map buildIndicesBAVector

    Suppose if I have VariableArray<int> indexA,  VariableArray<int> indexB, which are to be observed. Is it possible to define indicesABVector from indexA and indexB? If it is possible, it seems better than the above approach.

                
    • Edited by colinfang Thursday, October 9, 2014 3:53 PM
    Thursday, October 9, 2014 3:47 PM
  • You can do it like this:

                var indexA = Variable.Observed(0);
                var indexB = Variable.Observed(1);
                Range r = new Range(4);
                var indicesAB = Variable.Array<double>(r);
                using (var fb = Variable.ForEach(r))
                {
                    var i = fb.Index;
                    var isA = (i == indexA) & true;
                    using (Variable.If(isA))
                    {
                        indicesAB[i] = 1;
                    }
                    using (Variable.IfNot(isA))
                    {
                        var isB = (i == indexB) & true;
                        using (Variable.If(isB))
                        {
                            indicesAB[i] = -1;
                        }
                        using (Variable.IfNot(isB))
                        {
                            indicesAB[i] = 0;
                        }
                    }
                }
                var indicesABVector = Variable.Vector(indicesAB);
    
                InferenceEngine engine = new InferenceEngine();
                Console.WriteLine(engine.Infer(indicesABVector));
    

    The silly '& true' bits are to work-around a bug in the current version of Infer.NET.
    • Marked as answer by colinfang Thursday, October 9, 2014 10:17 PM
    Thursday, October 9, 2014 5:28 PM
    Owner