public static NonconjugateGaussian DNonconjugateAverageLogarithm([Proper] Gamma exp, [Proper, SkipIfUniform] Gaussian d, NonconjugateGaussian result) { var vf = -1.0; var a = exp.Shape; var v_opt = 1.0 / (a - 1.0); var b = exp.Rate; double m = 0.0, v = 0.0; d.GetMeanAndVariance(out m, out v); if (a > 1) { var mf = Math.Log((a - 1) / b) - .5 * v_opt; if (mf != m) { var grad_S_m = -b *Math.Exp(m + v / 2) + a - 1; vf = (mf - m) / grad_S_m; result.MeanTimesPrecision = mf / vf; result.Precision = 1 / vf; } } //m = (mp + prior_mp)/(p + prior_p); if (vf < 0) { result.Precision = b * Math.Exp(m + v / 2); result.MeanTimesPrecision = (m - 1) * result.Precision + a - 1; } double bf = -1, afm1 = -1; if (a <= 1) { v_opt = FindMinimumInV(b * Math.Exp(m)); } if (v_opt != v) { var grad_S_v = -.5 * b * Math.Exp(m + v / 2); bf = v * grad_S_v / (v_opt - v); afm1 = v_opt * bf; } if (afm1 < 0 || bf < 0) { afm1 = b * v * v * Math.Exp(m + v / 2) / 4; bf = b * (1 + v / 2) * Math.Exp(m + v / 2) / 2; } result.Shape = afm1 + 1; result.Rate = bf; if (!result.IsProper()) { throw new ApplicationException("improper message calculated by ExpOp.DNonconjugateAverageLogarithm"); } return(result); }
/// <summary>VMP message to <c>b</c>.</summary> /// <param name="ProductExp">Incoming message from <c>productExp</c>. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="A">Incoming message from <c>a</c>. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="B">Incoming message from <c>b</c>. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="to_B">Previous outgoing message to <c>B</c>.</param> /// <param name="result">Modified to contain the outgoing message.</param> /// <returns> /// <paramref name="result" /> /// </returns> /// <remarks> /// <para>The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except <c>b</c>. Because the factor is deterministic, <c>productExp</c> is integrated out before taking the logarithm. The formula is <c>exp(sum_(a) p(a) log(sum_productExp p(productExp) factor(productExp,a,b)))</c>.</para> /// </remarks> /// <exception cref="ImproperMessageException"> /// <paramref name="ProductExp" /> is not a proper distribution.</exception> /// <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 NonconjugateGaussian BAverageLogarithm( [SkipIfUniform] Gaussian ProductExp, [Proper, SkipIfUniform] Gaussian A, [Proper, SkipIfUniform] Gaussian B, NonconjugateGaussian to_B, NonconjugateGaussian result) { if (B.IsPointMass) { return(NonconjugateGaussian.Uniform()); } if (ProductExp.IsPointMass) { return(BAverageLogarithm(ProductExp.Point, A)); } if (!B.IsProper()) { throw new ImproperMessageException(B); } // catch uniform case to avoid 0*Inf if (ProductExp.IsUniform()) { return(NonconjugateGaussian.Uniform()); } double mx, vx, m, v, mz, vz; ProductExp.GetMeanAndVariance(out mz, out vz); A.GetMeanAndVariance(out mx, out vx); B.GetMeanAndVariance(out m, out v); //if (mx * mz < 0) //{ // Console.WriteLine("Warning: mx*mz < 0, setting to uniform"); // result.SetToUniform(); // return result; //} double Ex2 = mx * mx + vx; double grad2_S_m2 = -2 * Ex2 * Math.Exp(2 * m + 2 * v) / vz + mx * mz * Math.Exp(m + .5 * v) / vz; double grad_m = -Ex2 *Math.Exp(2 *m + 2 *v) / vz + mx * mz * Math.Exp(m + .5 * v) / vz; double threshold = 10; double mf, vf, afm1, bf; if (grad2_S_m2 >= -threshold && mx * mz > 0) { mf = Math.Log(mx * mz / Ex2) - 1.5 * v; vf = (mf - m) / grad_m; } else { vf = -1 / grad2_S_m2; mf = m - grad_m / grad2_S_m2; } Gaussian priorG; if (result.IsUniform()) { priorG = B; } else { var prior = new NonconjugateGaussian(); prior.SetToRatio((new NonconjugateGaussian(B)), to_B); priorG = prior.GetGaussian(); } result.MeanTimesPrecision = mf / vf; result.Precision = 1 / vf; var updatedM = new Gaussian(mf, vf) * priorG; m = updatedM.GetMean(); double grad_S2_v2 = -2 * Ex2 * Math.Exp(2 * m + 2 * v) / vz + .25 * mx * mz * Math.Exp(m + .5 * v) / vz; double grad_S_v = -Ex2 *Math.Exp(2 *m + 2 *v) / vz + .5 * mx * mz * Math.Exp(m + .5 * v) / vz; afm1 = -1; bf = -1; if (grad2_S_m2 >= -threshold) { afm1 = -v * v * grad_S2_v2; bf = -grad_S_v + afm1 / v; } if ((afm1 < 0 || bf < 0) && mx * mz > 0) { double v_opt = 2 / 3 * (Math.Log(mx * mz / Ex2 / 2) - m); if (v_opt != v) { bf = v * grad_S_v / (v_opt - v); afm1 = v_opt * bf; } } if (afm1 < 0 || bf < 0) { afm1 = -v * v * grad_S2_v2; bf = -grad_S_v + afm1 / v; } if (afm1 < 0 || bf < 0) { result.Shape = 1; result.Rate = 0; } else { result.Shape = afm1 + 1; result.Rate = bf; } if (!result.IsProper()) { throw new ApplicationException("improper"); } return(result); // REMEMBER TO ADD ENTROPY TERM IN REPLICATE OP }
/// <summary> /// VMP message to 'b' /// </summary> /// <param name="ProductExp">Incoming message from 'productExp'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="A">Incoming message from 'a'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="B">Incoming message from 'b'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="to_B">Previous outgoing message to 'B'.</param> /// <param name="result">Modified to contain the outgoing message</param> /// <returns><paramref name="result"/></returns> /// <remarks><para> /// The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except 'b'. /// Because the factor is deterministic, 'productExp' is integrated out before taking the logarithm. /// The formula is <c>exp(sum_(a) p(a) log(sum_productExp p(productExp) factor(productExp,a,b)))</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="ProductExp"/> is not a proper distribution</exception> /// <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 NonconjugateGaussian BAverageLogarithm([SkipIfUniform] Gaussian ProductExp, [Proper, SkipIfUniform] Gaussian A, [Proper, SkipIfUniform] Gaussian B, NonconjugateGaussian to_B, NonconjugateGaussian result) { if (B.IsPointMass) return NonconjugateGaussian.Uniform(); if (ProductExp.IsPointMass) return BAverageLogarithm(ProductExp.Point, A); if (!B.IsProper()) throw new ImproperMessageException(B); // catch uniform case to avoid 0*Inf if (ProductExp.IsUniform()) return NonconjugateGaussian.Uniform(); double mx, vx, m, v, mz, vz; ProductExp.GetMeanAndVariance(out mz, out vz); A.GetMeanAndVariance(out mx, out vx); B.GetMeanAndVariance(out m, out v); //if (mx * mz < 0) //{ // Console.WriteLine("Warning: mx*mz < 0, setting to uniform"); // result.SetToUniform(); // return result; //} double Ex2 = mx * mx + vx; double grad2_S_m2 = -2 * Ex2 * Math.Exp(2 * m + 2 * v) / vz + mx * mz * Math.Exp(m + .5 * v) / vz; double grad_m = -Ex2 * Math.Exp(2 * m + 2 * v) / vz + mx * mz * Math.Exp(m + .5 * v) / vz; double threshold = 10; double mf, vf, afm1, bf; if (grad2_S_m2 >= -threshold && mx * mz > 0) { mf = Math.Log(mx * mz / Ex2) - 1.5 * v; vf = (mf - m) / grad_m; } else { vf = -1 / grad2_S_m2; mf = m - grad_m / grad2_S_m2; } Gaussian priorG; if (result.IsUniform()) priorG = B; else { var prior = new NonconjugateGaussian(); prior.SetToRatio((new NonconjugateGaussian(B)), to_B); priorG = prior.GetGaussian(); } result.MeanTimesPrecision = mf / vf ; result.Precision = 1 / vf; var updatedM = new Gaussian(mf,vf) * priorG; m = updatedM.GetMean(); double grad_S2_v2 = -2 * Ex2 * Math.Exp(2 * m + 2 * v) / vz + .25 * mx * mz * Math.Exp(m + .5 * v) / vz; double grad_S_v = -Ex2 * Math.Exp(2 * m + 2 * v) / vz + .5 * mx * mz * Math.Exp(m + .5 * v) / vz; afm1 = -1; bf = -1; if (grad2_S_m2 >= -threshold) { afm1 = -v * v * grad_S2_v2; bf = -grad_S_v + afm1 / v; } if ((afm1 < 0 || bf < 0) && mx * mz > 0) { double v_opt = 2 / 3 * (Math.Log(mx * mz / Ex2 / 2) - m); if (v_opt != v) { bf = v * grad_S_v / (v_opt - v); afm1 = v_opt * bf; } } if (afm1 < 0 || bf < 0) { afm1 = -v * v * grad_S2_v2; bf = -grad_S_v + afm1 / v; } if (afm1 < 0 || bf < 0) { result.Shape = 1; result.Rate = 0; } else { result.Shape = afm1 + 1; result.Rate = bf; } if (!result.IsProper()) throw new ApplicationException("improper"); return result; // REMEMBER TO ADD ENTROPY TERM IN REPLICATE OP }
public static NonconjugateGaussian DNonconjugateAverageLogarithm([Proper] Gamma exp, [Proper, SkipIfUniform] Gaussian d, NonconjugateGaussian result) { var vf = -1.0; var a = exp.Shape; var v_opt = 1.0 / (a - 1.0); var b = exp.Rate; double m = 0.0, v = 0.0; d.GetMeanAndVariance(out m, out v); if (a > 1) { var mf = Math.Log((a - 1) / b) - .5 * v_opt; if (mf != m) { var grad_S_m = -b * Math.Exp(m + v / 2) + a - 1; vf = (mf - m) / grad_S_m; result.MeanTimesPrecision = mf / vf; result.Precision = 1 / vf; } } //m = (mp + prior_mp)/(p + prior_p); if (vf < 0) { result.Precision = b * Math.Exp(m + v / 2); result.MeanTimesPrecision = (m - 1) * result.Precision + a - 1; } double bf = -1, afm1 = -1; if (a <= 1) v_opt = FindMinimumInV(b * Math.Exp(m)); if (v_opt != v) { var grad_S_v = -.5 * b * Math.Exp(m + v / 2); bf = v * grad_S_v / (v_opt - v); afm1 = v_opt * bf; } if (afm1 < 0 || bf < 0) { afm1 = b * v * v * Math.Exp(m + v / 2) / 4; bf = b * (1 + v / 2) * Math.Exp(m + v / 2) / 2; } result.Shape = afm1 + 1; result.Rate = bf; if (!result.IsProper()) throw new ApplicationException("improper message calculated by ExpOp.DNonconjugateAverageLogarithm"); return result; }