/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="ExpOp_Laplace"]/message_doc[@name="DAverageConditional(Gamma, Gaussian, Gaussian)"]/*'/> public static Gaussian DAverageConditional([SkipIfUniform] Gamma exp, [Proper] Gaussian d, Gaussian to_d) { if (exp.IsPointMass) { return(ExpOp.DAverageConditional(exp.Point)); } Gaussian dPost = d * to_d; double dhat = dPost.GetMean(); double ehat = Math.Exp(dhat); double a = exp.Shape; double b = exp.Rate; double dlogf = (a - 1) - b * ehat; double ddlogf = -b * ehat; double r = -ddlogf; if (ForceProper && r < 0) { r = 0; } return(Gaussian.FromNatural(r * dhat + dlogf, r)); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="ExpOp_Laplace2"]/message_doc[@name="DAverageConditional(Gamma, Gaussian, double)"]/*'/> public static Gaussian DAverageConditional([SkipIfUniform] Gamma exp, [Proper] Gaussian d, double x) { if (exp.IsPointMass) { return(ExpOp.DAverageConditional(exp.Point)); } double expx = Math.Exp(x); double a = exp.Shape; double b = exp.Rate; double ddlogf = -b * expx; double dddlogf = ddlogf; double d4logf = ddlogf; double dlogf = (a - 1) + ddlogf; double v = 1 / (d.Precision - ddlogf); // this is Laplace's estimate of the posterior mean and variance double mpost = x + 0.5 * dddlogf * v * v; double vpost = v + 0.5 * d4logf * v * v * v + dddlogf * dddlogf * v * v * v * v; //double vpost = v + 0.25 * dddlogf * dddlogf * v * v * v * v; Gaussian result = Gaussian.FromMeanAndVariance(mpost, vpost); result.SetToRatio(result, d, ExpOp.ForceProper); return(result); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="LogOp_EP"]/message_doc[@name="LogAverageConditional(Gaussian, Gamma, Gaussian)"]/*'/> public static Gaussian LogAverageConditional([Proper] Gaussian log, [SkipIfUniform] Gamma d, Gaussian result) { var g = Gamma.FromShapeAndRate(d.Shape + 1, d.Rate); return(ExpOp.DAverageConditional(g, log, result)); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="LogOp_EP"]/message_doc[@name="DAverageConditional(Gaussian, Gamma, Gaussian)"]/*'/> public static Gamma DAverageConditional([Proper] Gaussian log, Gamma d, Gaussian to_log) { var g = Gamma.FromShapeAndRate(d.Shape + 1, d.Rate); return(ExpOp.ExpAverageConditional(g, log, to_log)); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="LogOp_EP"]/message_doc[@name="LogAverageFactor(Gaussian, Gamma, Gaussian)"]/*'/> public static double LogAverageFactor(Gaussian log, Gamma d, [Fresh] Gaussian to_log) { Gamma g = Gamma.FromShapeAndRate(d.Shape + 1, d.Rate); return(d.Shape / d.Rate * ExpOp.LogAverageFactor(g, log, to_log)); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="ExpOp_BFGS"]/message_doc[@name="DAverageLogarithm(Gamma, Gaussian, Gaussian)"]/*'/> public static Gaussian DAverageLogarithm([Proper] Gamma exp, [Proper, Stochastic] Gaussian d, Gaussian to_d) { if (exp.IsPointMass) { return(ExpOp.DAverageLogarithm(exp.Point)); } double m, v; d.GetMeanAndVariance(out m, out v); double mu, s2; var prior = d / to_d; prior.GetMeanAndVariance(out mu, out s2); var z = Vector.Zero(2); z[0] = m; z[1] = Math.Log(v); double startingValue = GradientAndValueAtPoint(mu, s2, z, exp.Shape, exp.Rate, null); var s = new BFGS(); int evalCounter = 0; s.MaximumStep = 1e3; s.MaximumIterations = 100; s.Epsilon = 1e-5; s.convergenceCriteria = BFGS.ConvergenceCriteria.Objective; z = s.Run(z, 1.0, delegate(Vector y, ref Vector grad) { evalCounter++; return(GradientAndValueAtPoint(mu, s2, y, exp.Shape, exp.Rate, grad)); }); m = z[0]; v = Math.Exp(z[1]); to_d.SetMeanAndVariance(m, v); to_d.SetToRatio(to_d, prior); double endValue = GradientAndValueAtPoint(mu, s2, z, exp.Shape, exp.Rate, null); //Console.WriteLine("Went from {0} to {1} in {2} steps, {3} evals", startingValue, endValue, s.IterationsPerformed, evalCounter); if (startingValue < endValue) { Console.WriteLine("Warning: BFGS resulted in an increased objective function"); } return(to_d); /* ---------------- NEWTON ITERATION VERSION 1 ------------------- * double meanTimesPrec, prec; * d.GetNatural(out meanTimesPrec, out prec); * Matrix K = new Matrix(2, 2); * K[0, 0]=1/prec; // d2K by dmu^2 * K[1, 0]=K[0, 1]=-meanTimesPrec/(prec*prec); * K[1, 1]=meanTimesPrec*meanTimesPrec/Math.Pow(prec, 3)+1/(2*prec*prec); * double[,,] Kprime = new double[2, 2, 2]; * Kprime[0, 0, 0]=0; * Kprime[0, 0, 1]=Kprime[0, 1, 0]=Kprime[1, 0, 0]=-1/(prec*prec); * Kprime[0, 1, 1]=Kprime[1, 1, 0]=Kprime[1, 0, 1]=2*meanTimesPrec/Math.Pow(prec, 3); * Kprime[1, 1, 1]=-3*meanTimesPrec*meanTimesPrec/Math.Pow(prec, 4)-1/Math.Pow(prec, 3); * Vector gradS = new Vector(2); * gradS[0]=(exp.Shape-1)/prec-exp.Rate/prec*Math.Exp((meanTimesPrec+.5)/prec); * gradS[1]=-(exp.Shape-1)*meanTimesPrec/(prec*prec)+exp.Rate*(meanTimesPrec+.5)/(prec*prec)*Math.Exp((meanTimesPrec+.5)/prec); * Matrix grad2S = new Matrix(2, 2); * grad2S[0, 0]=-exp.Rate/(prec*prec)*Math.Exp((meanTimesPrec+.5)/prec); * grad2S[0, 1]=grad2S[1, 0]=-(exp.Shape-1)/(prec*prec)+exp.Rate*(1/(prec*prec)+(meanTimesPrec+.5)/Math.Pow(prec, 3))*Math.Exp((meanTimesPrec+.5)/prec); * grad2S[1, 1]=2*(exp.Shape-1)*meanTimesPrec/Math.Pow(prec, 3)-exp.Rate*(meanTimesPrec+.5)/(prec*prec)*(2/prec+(meanTimesPrec+.5)/(prec*prec))*Math.Exp((meanTimesPrec+.5)/prec); * Vector phi = new Vector(new double[] { result.MeanTimesPrecision, result.Precision }); * Vector gradKL = K*phi-gradS; * Matrix hessianKL = K - grad2S; * for (int i=0; i<2; i++) * for (int j=0; j<2; j++) * for (int k=0; k<2; k++) * hessianKL[i, j]+=Kprime[i, j, k]*phi[k]; * double step = 1; * Vector direction = GammaFromShapeAndRate.twoByTwoInverse(hessianKL)*gradKL; * Vector newPhi = phi - step * direction; * result.SetNatural(newPhi[0], newPhi[1]); * return result; * * ---------------- NEWTON ITERATION VERSION 2 ------------------- * double mean, variance; * d.GetMeanAndVariance(out mean, out variance); * Gaussian prior = d / result; * double mean1, variance1; * prior.GetMeanAndVariance(out mean1, out variance1); * Vector gradKL = new Vector(2); * gradKL[0]=-(exp.Shape-1)+exp.Rate*Math.Exp(mean+variance/2)+mean/variance1-mean1/variance1; * gradKL[1]=-1/(2*variance)+exp.Rate*Math.Exp(mean+variance/2)+1/(2*variance1); * Matrix hessianKL = new Matrix(2, 2); * hessianKL[0, 0]=exp.Rate*Math.Exp(mean+variance/2)+1/variance1; * hessianKL[0, 1]=hessianKL[1, 0]=.5*exp.Rate*Math.Exp(mean+variance/2); * hessianKL[1, 1]=1/(2*variance*variance)+exp.Rate*Math.Exp(mean+variance/2)/4; * result.GetMeanAndVariance(out mean, out variance); * if (double.IsInfinity(variance)) * variance=1000; * Vector theta = new Vector(new double[] { mean, variance }); * theta -= GammaFromShapeAndRate.twoByTwoInverse(hessianKL)*gradKL; * result.SetMeanAndVariance(theta[0], theta[1]); * return result; * ----------------------------------------------------------------- */ }
public static Gaussian DAverageConditional([SkipIfUniform] Gamma exp, [Proper] Gaussian d) { // as a function of d, the factor is Ga(exp(d); shape, rate) = exp(d*(shape-1) -rate*exp(d)) if (exp.IsUniform()) { return(Gaussian.Uniform()); } if (exp.IsPointMass) { return(ExpOp.DAverageConditional(exp.Point)); } if (exp.Rate < 0) { throw new ImproperMessageException(exp); } if (exp.Rate == 0) { return(Gaussian.FromNatural(exp.Shape - 1, 0)); } if (d.IsUniform()) { if (exp.Shape <= 1) { throw new ArgumentException("The posterior has infinite variance due to input of Exp distributed as " + d + " and output of Exp distributed as " + exp + " (shape <= 1)"); } // posterior for d is a shifted log-Gamma distribution: // exp((a-1)*d - b*exp(d)) =propto exp(a*(d+log(b)) - exp(d+log(b))) // we find the Gaussian with same moments. // u = d+log(b) // E[u] = digamma(a-1) // E[d] = E[u]-log(b) = digamma(a-1)-log(b) // var(d) = var(u) = trigamma(a-1) double lnRate = Math.Log(exp.Rate); return(new Gaussian(MMath.Digamma(exp.Shape - 1) - lnRate, MMath.Trigamma(exp.Shape - 1))); } double aMinus1 = exp.Shape - 1; double b = exp.Rate; if (d.IsPointMass) { double x = d.Point; double expx = Math.Exp(x); double dlogf = aMinus1 - b * expx; double ddlogf = -b * expx; return(Gaussian.FromDerivatives(x, dlogf, ddlogf, true)); } double dmode, dmin, dmax; GetIntegrationBounds(exp, d, out dmode, out dmin, out dmax); double expmode = Math.Exp(dmode); int n = QuadratureNodeCount; double inc = (dmax - dmin) / (n - 1); MeanVarianceAccumulator mva = new MeanVarianceAccumulator(); for (int i = 0; i < n; i++) { double x = dmin + i * inc; double xMinusMode = x - dmode; double diff = aMinus1 * xMinusMode - b * (Math.Exp(x) - expmode) - 0.5 * ((x * x - dmode * dmode) * d.Precision - 2 * xMinusMode * d.MeanTimesPrecision); double p = Math.Exp(diff); mva.Add(x, p); if (double.IsNaN(mva.Variance)) { throw new Exception(); } } double dMean = mva.Mean; double dVariance = mva.Variance; Gaussian result = Gaussian.FromMeanAndVariance(dMean, dVariance); result.SetToRatio(result, d, true); return(result); }