예제 #1
0
        /// <summary>
        /// VMP message to 'matrixMultiply'
        /// </summary>
        /// <param name="A">Incoming message from 'A'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
        /// <param name="B">Incoming message from 'B'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'matrixMultiply' as the random arguments are varied.
        /// The formula is <c>proj[sum_(A,B) p(A,B) factor(matrixMultiply,A,B)]</c>.
        /// </para></remarks>
        /// <exception cref="ImproperMessageException"><paramref name="A"/> is not a proper distribution</exception>
        /// <exception cref="ImproperMessageException"><paramref name="B"/> is not a proper distribution</exception>
        public static GaussianArray2D MatrixMultiplyAverageLogarithm([SkipIfUniform] DistributionArray2D <Gaussian> A, [SkipIfUniform] DistributionArray2D <Gaussian> B, GaussianArray2D result)
        {
            if (result == null)
            {
                result = new DistributionStructArray2D <Gaussian, double>(A.GetLength(0), B.GetLength(1));
            }
            // x[i,j] = sum_k a[i,k]*b[k,j]
            // E(x[i,j]) = sum_k E(a[i,k])*E(b[k,j])
            // var(x[i,j]) = sum_k E(a[i,k])^2*var(b[k,j]) + var(a[i,k])*E(b[k,j])^2 + var(a[i,k])*var(b[k,j])
            int rows  = result.GetLength(0);
            int cols  = result.GetLength(1);
            int inner = A.GetLength(1);

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    double mean = 0; double var = 0;
                    for (int k = 0; k < inner; k++)
                    {
                        double Am, Av, Bm, Bv;
                        A[i, k].GetMeanAndVariance(out Am, out Av);
                        B[k, j].GetMeanAndVariance(out Bm, out Bv);
                        mean += Am * Bm;
                        var  += Av * Bm * Bm + Bv * Am * Am + Av * Bv;
                    }
                    Gaussian rij = result[i, j];
                    rij.SetMeanAndVariance(mean, var);
                    result[i, j] = rij;
                }
            }
            return(result);
        }
예제 #2
0
        public void FactorAnalysisMslTest()
        {
            InferenceEngine engine = new InferenceEngine(new VariationalMessagePassing());

            engine.Compiler.DeclarationProvider = RoslynDeclarationProvider.Instance;
            double[,] dataIn = MatlabReader.ReadMatrix(new double[400, 64],
                                                       Path.Combine(
#if NETCORE
                                                           Path.GetDirectoryName(typeof(VmpMslTests).Assembly.Location), // work dir is not the one with Microsoft.ML.Probabilistic.Tests.dll on netcore and neither is .Location on netfull
#endif
                                                           "Data", "pca.txt"),
                                                       ' ');
            int C = 8;
            engine.ShowProgress                 = true;
            engine.ShowTimings                  = true;
            engine.NumberOfIterations           = 20;
            engine.Compiler.DeclarationProvider = RoslynDeclarationProvider.Instance;
            var ca = engine.Compiler.Compile(FactorAnalysisModel, C, dataIn,
                                             BioTests.RandomGaussianArray(C, dataIn.GetLength(1)),
                                             BioTests.RandomGaussianArray(dataIn.GetLength(0), C));
            ca.Execute(engine.NumberOfIterations);
            DistributionArray2D <Gaussian> wMarginal = ca.Marginal <DistributionArray2D <Gaussian> >("W");
            DistributionArray2D <Gaussian> xMarginal = ca.Marginal <DistributionArray2D <Gaussian> >("x");
            //WriteMatrix(wMarginal.ToArray<Gaussian[,]>(), @"..\..\faresultsW.txt");
            //WriteMatrix(xMarginal.ToArray<Gaussian[,]>(), @"..\..\faresultsX.txt");

            // Reconstruct
            DistributionArray2D <Gaussian> productMarginal = MatrixMultiplyOp.MatrixMultiplyAverageLogarithm(xMarginal, wMarginal, null);
            double error = 0;
            for (int i = 0; i < productMarginal.GetLength(0); i++)
            {
                for (int j = 0; j < productMarginal.GetLength(1); j++)
                {
                    //Assert.True(productMarginal[i,j].GetLogProb(dataIn[i,j]) > -130);
                    error += System.Math.Abs(productMarginal[i, j].GetMean() - dataIn[i, j]);
                }
            }
            error /= productMarginal.Count;
            // error = 0.121231278712027
            Console.WriteLine("error = {0}", error);
            Assert.True(error < 0.15); // C=2: 0.15
        }
예제 #3
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MatrixVectorProductOp"]/message_doc[@name="AAverageConditional(VectorGaussian, DistributionArray2D{Gaussian, double}, Vector, PositiveDefiniteMatrix, DistributionStructArray2D{Gaussian, double})"]/*'/>
        public static DistributionStructArray2D <Gaussian, double> AAverageConditional([SkipIfUniform] VectorGaussian product, DistributionArray2D <Gaussian, double> A, Vector BMean, PositiveDefiniteMatrix BVariance, DistributionStructArray2D <Gaussian, double> result)
        {
            if (product.IsUniform())
            {
                result.SetToUniform();
                return(result);
            }
            if (!A.IsPointMass)
            {
                throw new ArgumentException("A is not a point mass");
            }
            // logZ = log N(mProduct; A*BMean, vProduct + A*BVariance*A')
            //      = -0.5 (mProduct - A*BMean)' inv(vProduct + A*BVariance*A') (mProduct - A*BMean) - 0.5 logdet(vProduct + A*BVariance*A')
            //      = -0.5 (mProduct - A*BMean)' pPrec inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean)
            //        - 0.5 logdet(pProduct + pProduct*A*BVariance*A'*pProduct) + logdet(pProduct)
            // dlogZ   = 0.5 (dA*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean)
            //         +0.5 (mProduct - A*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (dA*BMean)
            //         +0.5 (mProduct - A*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) (pProduct*dA*BVariance*A'*pProduct + pProduct*A*BVariance*dA'*pProduct) inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean)
            //         - 0.5 tr(inv(pProduct + pProduct*A*BVariance*A'*pProduct) (pProduct*dA*BVariance*A'*pProduct + pProduct*A*BVariance*dA'*pProduct))
            // dlogZ/dA = pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean) BMean'
            //          + pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean) (mProduct - A*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct*A*BVariance
            //          - pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct A*BVariance
            var Amatrix                 = new Matrix(A.Point);
            var pProductA               = product.Precision * Amatrix;
            var pProductABV             = pProductA * BVariance;
            PositiveDefiniteMatrix prec = new PositiveDefiniteMatrix(product.Dimension, product.Dimension);

            prec.SetToSum(product.Precision, pProductABV * pProductA.Transpose());
            // pProductA is now free
            for (int i = 0; i < prec.Rows; i++)
            {
                if (prec[i, i] == 0)
                {
                    prec[i, i] = 1;
                }
            }
            var v           = prec.Inverse();
            var ABM         = Amatrix * BMean;
            var pProductABM = product.Precision * ABM;
            var diff        = pProductABM;

            diff.SetToDifference(product.MeanTimesPrecision, pProductABM);
            // ABM is now free
            var pProductV     = product.Precision * v;
            var pProductVdiff = ABM;

            pProductVdiff.SetToProduct(pProductV, diff);
            var Vdiff = v * diff;

            pProductV.Scale(-1);
            pProductV.SetToSumWithOuter(pProductV, 1, pProductVdiff, Vdiff);
            Matrix dlogZ = pProductA;

            dlogZ.SetToProduct(pProductV, pProductABV);
            dlogZ.SetToSumWithOuter(dlogZ, 1, pProductVdiff, BMean);
            int rows = A.GetLength(0);
            int cols = A.GetLength(1);

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    double dlogp = dlogZ[i, j];
                    // for now, we don't compute the second derivative.
                    double ddlogp = -1;
                    result[i, j] = Gaussian.FromDerivatives(A[i, j].Point, dlogp, ddlogp, false);
                }
            }
            return(result);
        }
예제 #4
0
 public static GaussianArray2D MatrixMultiplyAverageLogarithmInit([IgnoreDependency] DistributionArray2D <Gaussian> A, [IgnoreDependency] double[,] B)
 {
     return(new DistributionStructArray2D <Gaussian, double>(A.GetLength(0), B.GetLength(1)));
 }