/// <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); }
/// <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])); }