예제 #1
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="InnerProductOpBase"]/message_doc[@name="InnerProductAverageLogarithm(DenseVector, PositiveDefiniteMatrix, DenseVector, PositiveDefiniteMatrix)"]/*'/>
        public static Gaussian InnerProductAverageLogarithm(DenseVector AMean, PositiveDefiniteMatrix AVariance, DenseVector BMean, PositiveDefiniteMatrix BVariance)
        {
            Gaussian result = new Gaussian();

            // p(x|a,b) = N(E[a]'*E[b], E[b]'*var(a)*E[b] + E[a]'*var(b)*E[a] + trace(var(a)*var(b)))
            // Uses John Winn's rule for deterministic factors.
            // Strict variational inference would set the variance to 0.
            result.SetMeanAndVariance(AMean.Inner(BMean), AVariance.QuadraticForm(BMean) + BVariance.QuadraticForm(AMean) + AVariance.Inner(BVariance));
            return(result);
        }
예제 #2
0
        /// <summary>
        /// Create a COM-Poisson distribution with the given sufficient statistics.
        /// </summary>
        /// <param name="mean">E[x]</param>
        /// <param name="meanLogFactorial">E[log(x!)]</param>
        /// <returns>A new COM-Poisson distribution</returns>
        /// <remarks>
        /// This routine implements maximum-likelihood estimation of a COM-Poisson distribution, as described by
        /// Thomas P. Minka, Galit Shmueli, Joseph B. Kadane, Sharad Borle, and Peter Boatwright,
        /// "Computing with the COM-Poisson distribution", CMU Tech Report 776.
        /// http://www.stat.cmu.edu/tr/tr776/tr776.html
        /// </remarks>
        public static Poisson FromMeanAndMeanLogFactorial(double mean, double meanLogFactorial)
        {
            DenseVector theta = DenseVector.Zero(2);

            theta[0] = Math.Log(mean);
            theta[1] = 1;
            DenseVector            newTheta  = DenseVector.Zero(2);
            DenseVector            gradient2 = DenseVector.Zero(2);
            DenseVector            gradient  = DenseVector.Zero(2);
            PositiveDefiniteMatrix hessian   = new PositiveDefiniteMatrix(2, 2);
            double    stepsize            = 1;
            const int numIter             = 1000;
            double    rate                = Math.Exp(theta[0]);
            double    precision           = theta[1];
            double    logZ                = GetLogNormalizer(rate, precision);
            double    meanEst             = Math.Exp(GetLogPowerSum(rate, precision, 1) - logZ);
            double    Z                   = Math.Exp(logZ);
            double    meanLogFactorialEst = GetSumLogFactorial(rate, precision) / Z;

            for (int iter = 0; iter < numIter; iter++)
            {
                double varEst              = Math.Exp(GetLogPowerSum(rate, precision, 2) - logZ) - meanEst * meanEst;
                double varLogFactorialEst  = GetSumLogFactorial2(rate, precision) / Z - meanLogFactorialEst * meanLogFactorialEst;
                double covXLogFactorialEst = GetSumXLogFactorial(rate, precision) / Z - meanEst * meanLogFactorialEst;
                gradient[0] = mean - meanEst;
                gradient[1] = meanLogFactorialEst - meanLogFactorial;
                double sqrGrad = gradient.Inner(gradient);
                // the Hessian is guaranteed to be positive definite
                hessian[0, 0] = varEst;
                hessian[0, 1] = -covXLogFactorialEst;
                hessian[1, 0] = hessian[0, 1];
                hessian[1, 1] = varLogFactorialEst;
                gradient.PredivideBy(hessian);
                // line search to reduce sqrGrad
                // we use sqrGrad instead of the likelihood since the point of zero gradient may not exactly match the likelihood mode due to numerical inaccuracy
                while (true)
                {
                    newTheta.SetToSum(1.0, theta, stepsize, gradient);
                    double sqrGrad2 = sqrGrad;
                    if (newTheta[1] >= 0)
                    {
                        rate                = Math.Exp(newTheta[0]);
                        precision           = newTheta[1];
                        logZ                = GetLogNormalizer(rate, precision);
                        meanEst             = Math.Exp(GetLogPowerSum(rate, precision, 1) - logZ);
                        Z                   = Math.Exp(logZ);
                        meanLogFactorialEst = GetSumLogFactorial(rate, precision) / Z;
                        gradient2[0]        = mean - meanEst;
                        gradient2[1]        = meanLogFactorialEst - meanLogFactorial;
                        sqrGrad2            = gradient2.Inner(gradient2);
                    }
                    if (sqrGrad2 < sqrGrad)
                    {
                        theta.SetTo(newTheta);
                        gradient.SetTo(gradient2);
                        stepsize *= 2;
                        break;
                    }
                    else
                    {
                        stepsize /= 2;
                        if (stepsize == 0)
                        {
                            break;
                        }
                    }
                }
                //Console.WriteLine("{0}: {1}", iter, theta);
                double maxGradient = Math.Max(Math.Abs(gradient[0]), Math.Abs(gradient[1]));
                if (maxGradient < 1e-10)
                {
                    break;
                }
                if (stepsize == 0)
                {
                    break;
                }
                if (iter == numIter - 1)
                {
                    throw new Exception("not converging");
                }
            }
            return(new Poisson(Math.Exp(theta[0]), theta[1]));
        }