public void ExpOpTest() { Assert.True(ExpOp.ExpAverageConditional(Gamma.FromShapeAndRate(3.302758272196654, 0.00060601537137241492), Gaussian.FromNatural(55.350150233321628, 6.3510247863590683), Gaussian.FromNatural(27.960892513144643, 3.4099170930572216)).Rate > 0); Gamma exp = new Gamma(1, 1); Gaussian[] ds = new[] { Gaussian.FromNatural(-1.6171314269768655E+308, 4.8976001759138024), Gaussian.PointMass(double.NegativeInfinity), }; foreach (var d in ds) { Gamma to_exp = ExpOp.ExpAverageConditional(exp, d, Gaussian.Uniform()); Gaussian to_d = ExpOp.DAverageConditional(exp, d, Gaussian.Uniform()); Gaussian to_d_slow = ExpOp_Slow.DAverageConditional(exp, d); Trace.WriteLine($"{to_d}"); Trace.WriteLine($"{to_d_slow}"); Assert.True(to_d_slow.MaxDiff(to_d) < 1e-10); } }
public static Gaussian SumDeriv(Gaussian sum, [Proper] IList <Gaussian> array, IList <Gaussian> to_array) { double sumPrec = sum.Precision; double sumOfArrayVariance = 0; double sumOfPostVariance = 0; for (int i = 0; i < array.Count; i++) { double mi, vi; Gaussian prior = array[i] / to_array[i]; prior.GetMeanAndVariance(out mi, out vi); sumOfArrayVariance += vi; double vpost = 1 / (sumPrec + prior.Precision); sumOfPostVariance += vpost; } double mpDeriv = 1 / (sumPrec + 1 / sumOfArrayVariance) / sumOfPostVariance; double precDeriv = 1; return(Gaussian.FromNatural(mpDeriv - 1, precDeriv - 1)); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DoublePlusOp"]/message_doc[@name="SumAverageConditional(double, Gaussian)"]/*'/> public static Gaussian SumAverageConditional(double a, [SkipIfUniform] Gaussian b) { if (b.IsPointMass) { return(SumAverageConditional(a, b.Point)); } if (b.IsUniform()) { return(b); } double meanTimesPrecision = b.MeanTimesPrecision + a * b.Precision; if (Math.Abs(meanTimesPrecision) > double.MaxValue) { return(Gaussian.FromMeanAndPrecision(b.GetMean() + a, b.Precision)); } else { return(Gaussian.FromNatural(meanTimesPrecision, b.Precision)); } }
/// <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)); }
/// <summary> /// VMP message to 'data' /// </summary> /// <param name="vector">Incoming message from 'fromArray'. Must be a proper distribution. If any element is uniform, the result will be uniform.</param> /// <param name="array">Incoming message from 'data'. 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 the factor viewed as a function of 'data' with 'fromArray' integrated out. /// The formula is <c>sum_fromArray p(fromArray) factor(fromArray,data)</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="vector"/> is not a proper distribution</exception> /// <exception cref="ImproperMessageException"><paramref name="array"/> is not a proper distribution</exception> public static GaussianList ArrayAverageLogarithm <GaussianList>([SkipIfUniform] VectorGaussian vector, [Proper] IList <Gaussian> array, GaussianList result) where GaussianList : IList <Gaussian> { // prec[i] = vector[i].Prec // meanTimesPrec = vector.MeanTimesPrec - vector.Prec[:,noti]*array[noti].Mean // = vector.MeanTimesPrec - vector.Prec*array.Mean + diag(invdiag(vector.Prec))*array.Mean if (result.Count != vector.Dimension) { throw new ArgumentException("vector.Dimension (" + vector.Dimension + ") != result.Count (" + result.Count + ")"); } if (result.Count != array.Count) { throw new ArgumentException("array.Count (" + array.Count + ") != result.Count (" + result.Count + ")"); } if (vector.IsPointMass) { return(ArrayAverageLogarithm(vector.Point, result)); } int length = result.Count; Vector mean = Vector.Zero(length); for (int i = 0; i < length; i++) { Gaussian item = array[i]; mean[i] = item.GetMean(); } Vector meanTimesPrecision = vector.Precision * mean; for (int i = 0; i < length; i++) { double prec = vector.Precision[i, i]; if (Double.IsPositiveInfinity(prec)) { throw new NotSupportedException("Singular VectorGaussians not supported"); } double mprec = vector.MeanTimesPrecision[i] - meanTimesPrecision[i] + prec * mean[i]; result[i] = Gaussian.FromNatural(mprec, prec); } return(result); }
/// <summary> /// Gradient matching VMP message from factor to logOdds variable /// </summary> /// <param name="sample">Constant value for 'sample'.</param> /// <param name="logOdds">Incoming message. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="to_LogOdds">Previous message sent, used for damping</param> /// <returns>The outgoing VMP message.</returns> /// <remarks><para> /// The outgoing message is the Gaussian approximation to the factor which results in the /// same derivatives of the KL(q||p) divergence with respect to the parameters of the posterior /// as if the true factor had been used. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="logOdds"/> is not a proper distribution</exception> public static Gaussian LogOddsAverageLogarithm(bool sample, [Proper, SkipIfUniform] Gaussian logOdds, Gaussian to_LogOdds) { double m, v; // prior mean and variance double s = sample ? 1 : -1; logOdds.GetMeanAndVariance(out m, out v); // E = \int q log f dx // Match gradients double dEbydm = s * MMath.LogisticGaussian(-s * m, v); double dEbydv = -.5 * MMath.LogisticGaussianDerivative(s * m, v); double prec = -2.0 * dEbydv; double meanTimesPrec = m * prec + dEbydm; Gaussian result = Gaussian.FromNatural(meanTimesPrec, prec); double step = Rand.Double() * 0.5; // random damping helps convergence, especially with parallel updates if (step != 1.0) { result.Precision = step * result.Precision + (1 - step) * to_LogOdds.Precision; result.MeanTimesPrecision = step * result.MeanTimesPrecision + (1 - step) * to_LogOdds.MeanTimesPrecision; } return(result); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DoublePlusOp"]/message_doc[@name="AAverageConditional(Gaussian, Gaussian)"]/*'/> public static Gaussian AAverageConditional([SkipIfUniform] Gaussian Sum, [SkipIfUniform] Gaussian b) { if (Sum.IsPointMass) { return(AAverageConditional(Sum.Point, b)); } if (b.IsPointMass) { return(AAverageConditional(Sum, b.Point)); } if (Sum.IsUniform() || b.IsUniform()) { return(Gaussian.Uniform()); } double prec = Sum.Precision + b.Precision; if (prec <= 0) { throw new ImproperDistributionException(Sum.IsProper() ? b : Sum); } return(Gaussian.FromNatural((Sum.MeanTimesPrecision * b.Precision - b.MeanTimesPrecision * Sum.Precision) / prec, Sum.Precision * b.Precision / prec)); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DoublePlusOp"]/message_doc[@name="SumAverageConditional(Gaussian, Gaussian)"]/*'/> public static Gaussian SumAverageConditional([SkipIfUniform] Gaussian a, [SkipIfUniform] Gaussian b) { if (a.IsPointMass) { return(SumAverageConditional(a.Point, b)); } if (b.IsPointMass) { return(SumAverageConditional(a, b.Point)); } if (a.IsUniform() || b.IsUniform()) { return(Gaussian.Uniform()); } // E[sum] = E[a] + E[b] // var(sum) = var(a) + var(b) = 1/aPrec + 1/bPrec // E[sum]/var(sum) = E[a]/var(sum) + E[b]/var(sum) // = E[a]/var(a)*var(a)/(1/aPrec + 1/bPrec) + E[b]/var(sum) // var(a)/(1/aPrec + 1/bPrec) = 1/(1 + aPrec/bPrec) = bPrec/(aPrec + bPrec) double meanTimesPrec = MMath.WeightedAverage(b.Precision, a.MeanTimesPrecision, a.Precision, b.MeanTimesPrecision); return(Gaussian.FromNatural(meanTimesPrec, GetPrecisionOfSum(a, b))); }
/// <summary> /// VMP message to 'x' /// </summary> /// <param name="logistic">Incoming message from 'logistic'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="x">Incoming message from 'x'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="to_X">Previous outgoing message to 'X'.</param> /// <returns>The outgoing VMP message to the 'x' argument</returns> /// <remarks><para> /// The outgoing message is the factor viewed as a function of 'x' with 'logistic' integrated out. /// The formula is <c>sum_logistic p(logistic) factor(logistic,x)</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="logistic"/> is not a proper distribution</exception> /// <exception cref="ImproperMessageException"><paramref name="x"/> is not a proper distribution</exception> public static Gaussian XAverageLogarithm([SkipIfUniform] Beta logistic, [Proper, SkipIfUniform] Gaussian x, Gaussian to_X) { if (logistic.IsPointMass) { return(XAverageLogarithm(logistic.Point)); } // f(x) = sigma(x)^(a-1) sigma(-x)^(b-1) // = sigma(x)^(a+b-2) exp(-x(b-1)) // since sigma(-x) = sigma(x) exp(-x) double a = logistic.TrueCount; double b = logistic.FalseCount; double scale = a + b - 2; if (scale == 0.0) { return(Gaussian.Uniform()); } double shift = -(b - 1); Gaussian toLogOddsPrev = Gaussian.FromNatural((to_X.MeanTimesPrecision - shift) / scale, to_X.Precision / scale); Gaussian toLogOdds = BernoulliFromLogOddsOp.LogOddsAverageLogarithm(true, x, toLogOddsPrev); return(Gaussian.FromNatural(scale * toLogOdds.MeanTimesPrecision + shift, scale * toLogOdds.Precision)); }
public static Gaussian FindxF0(Gaussian xB, Gaussian meanPrior, Gamma precPrior, Gaussian xF) { Gaussian xF3 = GaussianOp_Slow.SampleAverageConditional(xB, meanPrior, precPrior); Func <double, double> func = delegate(double tau2) { Gaussian xF2 = Gaussian.FromNatural(tau2, 0); if (tau2 >= 0) { return(double.PositiveInfinity); } Gaussian xB2 = IsPositiveOp.XAverageConditional(true, xF2); //return (xF2*xB2).MaxDiff(xF2*xB) + (xF3*xB).MaxDiff(xF2*xB); //return KlDiv(xF2*xB2, xF2*xB) + KlDiv(xF3*xB, xF2*xB); //return KlDiv(xF3*xB, xF2*xB) + Math.Pow((xF2*xB2).GetMean() - (xF2*xB).GetMean(), 2); return(KlDiv(xF2 * xB2, xF2 * xB) + MeanError(xF3 * xB, xF2 * xB)); }; double tau = xF.MeanTimesPrecision; double fmin; tau = Minimize(func, tau, out fmin); //MinimizePowell(func, x); return(Gaussian.FromNatural(tau, 0)); }
/// <summary> /// VMP message to 'x' /// </summary> /// <param name="logistic">Incoming message from 'logistic'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="x">Incoming message from 'x'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="to_x">Previous outgoing message to 'X'.</param> /// <param name="a">Buffer 'a'.</param> /// <returns>The outgoing VMP message to the 'x' argument</returns> /// <remarks><para> /// The outgoing message is the factor viewed as a function of 'x' with 'logistic' integrated out. /// The formula is <c>sum_logistic p(logistic) factor(logistic,x)</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="logistic"/> is not a proper distribution</exception> /// <exception cref="ImproperMessageException"><paramref name="x"/> is not a proper distribution</exception> public static Gaussian XAverageLogarithm([SkipIfUniform] Beta logistic, /*[Proper, SkipIfUniform]*/ Gaussian x, Gaussian to_x, double a) { if (logistic.IsPointMass) { return(LogisticOp.XAverageLogarithm(logistic.Point)); } // f(x) = sigma(x)^(a-1) sigma(-x)^(b-1) // = sigma(x)^(a+b-2) exp(-x(b-1)) // since sigma(-x) = sigma(x) exp(-x) double scale = logistic.TrueCount + logistic.FalseCount - 2; if (scale == 0.0) { return(Gaussian.Uniform()); } double shift = -(logistic.FalseCount - 1); double m, v; x.GetMeanAndVariance(out m, out v); double sa; if (double.IsPositiveInfinity(v)) { a = 0.5; sa = MMath.Logistic(m); } else { sa = MMath.Logistic(m + (1 - 2 * a) * v * 0.5); } double precision = a * a + (1 - 2 * a) * sa; // meanTimesPrecision = m*a*a + 1-2*a*sa; double meanTimesPrecision = m * precision + 1 - sa; //double vf = 1/(a*a + (1-2*a)*sa); //double mf = m + vf*(true ? 1-sa : sa); //double precision = 1/vf; //double meanTimesPrecision = mf*precision; Gaussian result = Gaussian.FromNatural(scale * meanTimesPrecision + shift, scale * precision); double step = (LogisticOp_SJ99.global_step == 0.0) ? 1.0 : (Rand.Double() * LogisticOp_SJ99.global_step); // random damping helps convergence, especially with parallel updates if (false && !x.IsPointMass) { // if the update would change the sign of 1-2*sa, send a message to make sa=0.5 double newPrec = x.Precision - to_x.Precision + result.Precision; double newv = 1 / newPrec; double newm = newv * (x.MeanTimesPrecision - to_x.MeanTimesPrecision + result.MeanTimesPrecision); double newarg = newm + (1 - 2 * a) * newv * 0.5; if ((sa < 0.5 && newarg > 0) || (sa > 0.5 && newarg < 0)) { // send a message to make newarg=0 // it is sufficient to make (x.MeanTimesPrecision + step*(result.MeanTimesPrecision - to_x.MeanTimesPrecision) + 0.5-a) = 0 double mpOffset = x.MeanTimesPrecision + 0.5 - a; double precOffset = x.Precision; double mpScale = result.MeanTimesPrecision - to_x.MeanTimesPrecision; double precScale = result.Precision - to_x.Precision; double arg = m + (1 - 2 * a) * v * 0.5; //arg = 0; step = (arg * precOffset - mpOffset) / (mpScale - arg * precScale); //step = (a-0.5-x.MeanTimesPrecision)/(result.MeanTimesPrecision - to_x.MeanTimesPrecision); //Console.WriteLine(step); } } if (step != 1.0) { result.Precision = step * result.Precision + (1 - step) * to_x.Precision; result.MeanTimesPrecision = step * result.MeanTimesPrecision + (1 - step) * to_x.MeanTimesPrecision; } return(result); }
public void MaxTest() { Gaussian actual, expected; actual = MaxGaussianOp.MaxAverageConditional(Gaussian.FromNatural(6053.7946407740192, 2593.4559834344436), Gaussian.FromNatural(-1.57090676324773, 1.3751262174888785), Gaussian.FromNatural(214384.78500926663, 96523.508973471908)); Assert.False(actual.IsProper()); actual = MaxGaussianOp.MaxAverageConditional(Gaussian.FromNatural(146.31976467723146, 979.371757950659), Gaussian.FromNatural(0.075442729439046508, 0.086399540048904114), Gaussian.PointMass(0)); Assert.False(actual.IsProper()); actual = MaxGaussianOp.MaxAverageConditional(Gaussian.Uniform(), Gaussian.PointMass(0), new Gaussian(-7.357e+09, 9.75)); expected = Gaussian.PointMass(0); Assert.True(expected.MaxDiff(actual) < 1e-4); Gaussian max; max = new Gaussian(4, 5); actual = MaxGaussianOp.MaxAverageConditional(max, new Gaussian(0, 1), new Gaussian(2, 3)); actual *= max; expected = new Gaussian(2.720481395499785, 1.781481142817509); //expected = MaxPosterior(max, new Gaussian(0, 1), new Gaussian(2, 3)); Assert.True(expected.MaxDiff(actual) < 1e-4); max = new Gaussian(); max.MeanTimesPrecision = 0.2; max.Precision = 1e-10; actual = MaxGaussianOp.MaxAverageConditional(max, new Gaussian(0, 1), new Gaussian(0, 1)); actual *= max; expected = new Gaussian(0.702106815765215, 0.697676918460236); Assert.True(expected.MaxDiff(actual) < 1e-4); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MatrixMultiplyOp"]/message_doc[@name="AAverageLogarithm(DistributionStructArray2D{Gaussian, double}, DistributionStructArray2D{Gaussian, double}, double[,], DistributionStructArray2D{Gaussian, double})"]/*'/> public static GaussianArray2D AAverageLogarithm( [SkipIfUniform] GaussianArray2D matrixMultiply, [Proper, Stochastic] GaussianArray2D A, double[,] B, GaussianArray2D to_A) { GaussianArray2D result = to_A; if (result == null) { result = new DistributionStructArray2D <Gaussian, double>(A.GetLength(0), A.GetLength(1)); } int rows = matrixMultiply.GetLength(0); int cols = matrixMultiply.GetLength(1); int inner = A.GetLength(1); double[] ab = new double[cols]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { double sum = 0.0; for (int k = 0; k < inner; k++) { sum += A[i, k].GetMean() * B[k, j]; } ab[j] = sum; } for (int k = 0; k < inner; k++) { Gaussian old_result = result[i, k]; Gaussian rik = Gaussian.Uniform(); double Am = A[i, k].GetMean(); for (int j = 0; j < cols; j++) { double Bm = B[k, j]; if (Bm == 0) { continue; } Gaussian x = matrixMultiply[i, j]; ab[j] -= Am * Bm; Gaussian msg; if (x.IsPointMass) { msg = Gaussian.PointMass(x.Point / Bm); } else { double prec = (Bm * Bm) * x.Precision; //pm += Bm * (x.MeanTimesPrecision - x.Precision * (ab[j] - Am * Bm)); //Replace previous line with: double pm = Bm * (x.MeanTimesPrecision - x.Precision * ab[j]); msg = Gaussian.FromNatural(pm, prec); } rik.SetToProduct(rik, msg); } result[i, k] = rik; Gaussian partial = A[i, k] / old_result; Gaussian newPosterior = partial * rik; Am = newPosterior.GetMean(); for (int j = 0; j < cols; j++) { ab[j] += Am * B[k, j]; } } } return(result); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MaxGaussianOp"]/message_doc[@name="AAverageConditional(Gaussian, Gaussian, Gaussian)"]/*'/> public static Gaussian AAverageConditional([SkipIfUniform] Gaussian max, [Proper] Gaussian a, [Proper] Gaussian b) { if (max.IsUniform()) { return(Gaussian.Uniform()); } if (!b.IsProper()) { throw new ImproperMessageException(b); } double logw1, alpha1, vx1, mx1; double logw2, alpha2, vx2, mx2; double logz; ComputeStats(max, a, b, out logz, out logw1, out alpha1, out vx1, out mx1, out logw2, out alpha2, out vx2, out mx2); double w1 = Math.Exp(logw1 - logz); double w2 = Math.Exp(logw2 - logz); bool checkDerivatives = false; if (a.IsPointMass) { // f(a) = int p(x = max(a,b)) p(b) db // f(a) = p(x = a) p(a >= b) + p(x = b) p(a < b | x = b) // f(a) = N(a; mx, vx) phi((a - m2)/sqrt(v2)) + N(m2; mx, vx + v2) phi((mx2 - a)/sqrt(vx2)) // f'(a) = (mx-a)/vx N(a; mx, vx) phi((a - m2)/sqrt(v2)) + N(a; mx, vx) N(a; m2, v2) - N(m2; mx, vx + v2) N(a; mx2, vx2) // = (mx-a)/vx N(a; mx, vx) phi((a - m2)/sqrt(v2)) // f''(a) = -1/vx N(a; mx, vx) phi((a - m2)/sqrt(v2)) + (mx-a)^2/vx^2 N(a; mx, vx) phi((a - m2)/sqrt(v2)) + (mx-a)/vx N(a; mx, vx) N(a; m2, v2) // ddlogf = f''(a)/f(a) - (f'(a)/f(a))^2 = (f''(a) f(a) - f'(a)^2)/f(a)^2 double aPoint = a.Point; if (max.IsPointMass) { return(max); } double z = max.MeanTimesPrecision - aPoint * max.Precision; double alpha = z * w1; double beta = (z * alpha1 - max.Precision + z * z) * w1 - alpha * alpha; if (b.IsPointMass && b.Point != aPoint) { beta -= max.Precision * w2 * alpha2 * (b.Point - aPoint); } if (checkDerivatives) { double m1 = a.GetMean(); double delta = m1 * 1e-6; double logzd, logw1d, alpha1d, vx1d, mx1d, logw2d, alpha2d, vx2d, mx2d; ComputeStats(max, Gaussian.FromMeanAndPrecision(m1 + delta, a.Precision), b, out logzd, out logw1d, out alpha1d, out vx1d, out mx1d, out logw2d, out alpha2d, out vx2d, out mx2d); double logzd2; ComputeStats(max, Gaussian.FromMeanAndPrecision(m1 - delta, a.Precision), b, out logzd2, out logw1d, out alpha1d, out vx1d, out mx1d, out logw2d, out alpha2d, out vx2d, out mx2d); double alphaCheck = (logzd - logzd2) / (2 * delta); double alphaError = Math.Abs(alpha - alphaCheck); double betaCheck = (logzd + logzd2 - 2 * logz) / (delta * delta); double betaError = Math.Abs(beta - betaCheck); Console.WriteLine($"alpha={alpha} check={alphaCheck} error={alphaError} beta={beta} check={betaCheck} error={betaError}"); } return(Gaussian.FromDerivatives(aPoint, alpha, beta, ForceProper)); } bool useMessage = (w1 > 0) || (logw2 > -100); if (useMessage) { // vx1 = 1/(1/vx + 1/v1) = vx*v1/(vx + v1) double z, alpha, beta; if (max.IsPointMass) { if (w2 == 0) { return(max); } z = max.Point * a.Precision - a.MeanTimesPrecision; alpha = z * w1 - w2 * alpha2; beta = (z * z - a.Precision) * w1 - z * alpha2 * w2 - alpha * alpha; } else { //z = vx1 * (max.MeanTimesPrecision * a.Precision - a.MeanTimesPrecision * max.Precision); z = (max.MeanTimesPrecision - a.GetMean() * max.Precision) / (max.Precision / a.Precision + 1); alpha = z * w1 - vx1 * max.Precision * w2 * alpha2; if (w2 == 0) { //beta = (z * alpha1 - max.Precision) / (max.Precision / a.Precision + 1); //double resultPrecision = a.Precision * beta / (-a.Precision - beta); //resultPrecision = beta / (-1 - beta/a.Precision); //resultPrecision = 1 / (-1/beta - 1 / a.Precision); //resultPrecision = a.Precision / (-a.Precision / beta - 1); //resultPrecision = a.Precision / (-(a.Precision + max.Precision) / (z * alpha1 - max.Precision) - 1); //resultPrecision = -a.Precision / ((a.Precision + z*alpha1) / (z * alpha1 - max.Precision)); double zalpha1 = z * alpha1; double denom = (1 + zalpha1 / a.Precision); double resultPrecision = (max.Precision - zalpha1) / denom; //double weight = (max.Precision - z * alpha1) / (a.Precision + z * alpha1); //double weightPlus1 = (max.Precision + a.Precision) / (a.Precision + z * alpha1); //double resultMeanTimesPrecision = weight * (a.MeanTimesPrecision + alpha) + alpha; //resultMeanTimesPrecision = weight * a.MeanTimesPrecision + weightPlus1 * alpha; //double resultMeanTimesPrecision = (a.Precision * max.MeanTimesPrecision - z * alpha1 * a.MeanTimesPrecision) / (a.Precision + z * alpha1); double resultMeanTimesPrecision = (max.MeanTimesPrecision - zalpha1 * a.GetMean()) / denom; return(Gaussian.FromNatural(resultMeanTimesPrecision, resultPrecision)); } else { beta = ((z * alpha1 - max.Precision) * vx1 * a.Precision + z * z) * w1 - max.Precision * vx1 * w2 * alpha2 * (mx2 * a.Precision - a.MeanTimesPrecision) / (vx2 * a.Precision + 1) - alpha * alpha; } } //Console.WriteLine($"z={z} w1={w1:r} w2={w2:r} logw2={logw2} alpha1={alpha1} alpha2={alpha2} alpha={alpha:r} beta={beta:r}"); if (checkDerivatives) { double m1 = a.GetMean(); double delta = m1 * 1e-6; double logzd, logw1d, alpha1d, vx1d, mx1d, logw2d, alpha2d, vx2d, mx2d; ComputeStats(max, Gaussian.FromMeanAndPrecision(m1 + delta, a.Precision), b, out logzd, out logw1d, out alpha1d, out vx1d, out mx1d, out logw2d, out alpha2d, out vx2d, out mx2d); double logzd2; ComputeStats(max, Gaussian.FromMeanAndPrecision(m1 - delta, a.Precision), b, out logzd2, out logw1d, out alpha1d, out vx1d, out mx1d, out logw2d, out alpha2d, out vx2d, out mx2d); double alphaCheck = (logzd - logzd2) / (2 * delta); double alphaError = Math.Abs(alpha - alphaCheck); double betaCheck = (logzd + logzd2 - 2 * logz) / (delta * delta); double betaError = Math.Abs(beta - betaCheck); Console.WriteLine($"alpha={alpha} check={alphaCheck} error={alphaError} beta={beta} check={betaCheck} error={betaError}"); } return(GaussianOp.GaussianFromAlphaBeta(a, alpha, -beta, ForceProper)); } else { double m1, v1, m2, v2; a.GetMeanAndVariance(out m1, out v1); b.GetMeanAndVariance(out m2, out v2); // the posterior is a mixture model with weights exp(logw1-logz), exp(logw2-logz) and distributions // N(a; mx1, vx1) phi((a - m2)/sqrt(v2)) / phi((mx1 - m2)/sqrt(vx1 + v2)) // N(a; m1, v1) phi((mx2 - a)/sqrt(vx2)) / phi((mx2 - m1)/sqrt(vx2 + v1)) // the moments of the posterior are computed via the moments of these two components. if (vx1 == 0) { alpha1 = 0; } if (vx2 == 0) { alpha2 = 0; } double mc1 = mx1; if (alpha1 != 0) // avoid 0*infinity { mc1 += alpha1 * vx1; } alpha2 = -alpha2; double mc2 = m1; if (alpha2 != 0) // avoid 0*infinity { mc2 += alpha2 * v1; } // z2 = (mx2 - m1) / Math.Sqrt(vx2 + v1) // logw2 = MMath.NormalCdfLn(z2); // alpha2 = -Math.Exp(Gaussian.GetLogProb(mx2, m1, vx2 + v1) - logw2); // = -1/sqrt(vx2+v1)/NormalCdfRatio(z2) // m1 + alpha2*v1 = sqrt(vx2+v1)*(m1/sqrt(vx2+v1) - v1/(vx2+v1)/NormalCdfRatio(z2)) // = sqrt(vx2+v1)*(mx2/sqrt(vx2+v1) - z2 - v1/(vx2+v1)/NormalCdfRatio(z2)) // = sqrt(vx2+v1)*(mx2/sqrt(vx2+v1) - dY/Y) if vx2=0 double z2 = 0, Y = 0, dY = 0; const double z2small = 0; if (vx2 == 0) { z2 = (mx2 - m1) / Math.Sqrt(vx2 + v1); if (z2 < z2small) { Y = MMath.NormalCdfRatio(z2); dY = MMath.NormalCdfMomentRatio(1, z2); mc2 = mx2 - Math.Sqrt(v1) * dY / Y; } } double m = w1 * mc1 + w2 * mc2; double beta1; if (alpha1 == 0) { beta1 = 0; // avoid 0*infinity } else { double r1 = (mx1 - m2) / (vx1 + v2); beta1 = alpha1 * (alpha1 + r1); } double beta2; if (alpha2 == 0) { beta2 = 0; // avoid 0*infinity } else { double r2 = (mx2 - m1) / (vx2 + v1); beta2 = alpha2 * (alpha2 - r2); } double vc1 = vx1 * (1 - vx1 * beta1); double vc2; if (vx2 == 0 && z2 < z2small) { // beta2 = alpha2 * (alpha2 - z2/sqrt(v1)) // vc2 = v1 - v1^2 * alpha2 * (alpha2 - z2/sqrt(v1)) // = v1 - v1*dY/Y^2 // =approx v1/z2^2 // posterior E[x^2] = v - v*dY/Y^2 + v*dY^2/Y^2 = v - v*dY/Y^2*(1 - dY) = v + v*z*dY/Y = v*d2Y/Y //vc2 = v1 * (1 - dY / (Y * Y)); double d2Y = 2 * MMath.NormalCdfMomentRatio(2, z2); double dYiY = dY / Y; vc2 = v1 * (d2Y / Y - dYiY * dYiY); } else if (beta2 == 0) { vc2 = v1; } else { vc2 = v1 * (1 - v1 * beta2); } double diff = mc1 - mc2; double v = w1 * vc1 + w2 * vc2 + w1 * w2 * diff * diff; Gaussian result = new Gaussian(m, v); //Console.WriteLine($"z2={z2} m={m} v={v} vc2={vc2} diff={diff}"); result.SetToRatio(result, a, ForceProper); if (Double.IsNaN(result.Precision) || Double.IsNaN(result.MeanTimesPrecision)) { throw new InferRuntimeException($"result is NaN. max={max}, a={a}, b={b}"); } 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); }
public static Gaussian XAverageConditional_Helper([SkipIfUniform] Bernoulli isPositive, [SkipIfUniform, Proper] Gaussian x, bool forceProper) { if (x.IsPointMass) { if (isPositive.IsPointMass && (isPositive.Point != (x.Point > 0))) { return(Gaussian.PointMass(0)); } else { return(Gaussian.Uniform()); } } double tau = x.MeanTimesPrecision; double prec = x.Precision; if (prec == 0.0) { if (isPositive.IsPointMass) { if ((isPositive.Point && tau < 0) || (!isPositive.Point && tau > 0)) { // posterior is proportional to I(x>0) exp(tau*x) //double mp = -1 / tau; //double vp = mp * mp; return(Gaussian.FromNatural(-tau, tau * tau) / x); } } return(Gaussian.Uniform()); } else if (prec < 0) { throw new ImproperMessageException(x); } double sqrtPrec = Math.Sqrt(prec); // m/sqrt(v) = (m/v)/sqrt(1/v) double z = tau / sqrtPrec; // epsilon = p(b=F) // eq (51) in EP quickref double alpha; if (isPositive.IsPointMass) { if ((isPositive.Point && z < -10) || (!isPositive.Point && z > 10)) { if (z > 10) { z = -z; } //double Y = MMath.NormalCdfRatio(z); // dY = z*Y + 1 // d2Y = z*dY + Y // posterior mean = m + sqrt(v)/Y = sqrt(v)*(z + 1/Y) = sqrt(v)*dY/Y // = sqrt(v)*(d2Y/Y - 1)/z = (d2Y/Y - 1)/tau // =approx sqrt(v)*(-1/z) = -1/tau // posterior variance = v - v*dY/Y^2 =approx v/z^2 // posterior E[x^2] = v - v*dY/Y^2 + v*dY^2/Y^2 = v - v*dY/Y^2*(1 - dY) = v + v*z*dY/Y = v*d2Y/Y // d3Y = z*d2Y + 2*dY // = z*(z*dY + Y) + 2*dY // = z^2*dY + z*Y + 2*dY // = z^2*dY + 3*dY - 1 double d3Y = 6 * MMath.NormalCdfMomentRatio(3, z); //double dY = MMath.NormalCdfMomentRatio(1, z); double dY = (d3Y + 1) / (z * z + 3); if (MMath.AreEqual(dY, 0)) { double tau2 = tau * tau; if (tau2 > double.MaxValue) { return(Gaussian.PointMass(-1 / tau)); } else { return(Gaussian.FromNatural(-2 * tau, tau2)); } } // Y = (dY-1)/z // alpha = sqrtPrec*z/(dY-1) = tau/(dY-1) // alpha+tau = tau*(1 + 1/(dY-1)) = tau*dY/(dY-1) = alpha*dY // beta = alpha * (alpha + tau) // = alpha * tau * dY / (dY - 1) // = prec * z^2 * dY/(dY-1)^2 // prec/beta = (dY-1)^2/(dY*z^2) // prec/beta - 1 = ((dY-1)^2 - dY*z^2)/(dY*z^2) // weight = beta/(prec - beta) // = dY*z^2/((dY-1)^2 - dY*z^2) // = dY*z^2/(dY^2 -2*dY + 1 - dY*z^2) // = dY*z^2/(dY^2 + 1 + z*Y - d3Y) // = dY*z^2/(dY^2 + dY - d3Y) // = z^2/(dY + 1 - d3Y/dY) double d3YidY = d3Y / dY; double denom = dY - d3YidY + 1; double msgPrec = tau * tau / denom; // weight * (tau + alpha) + alpha // = z^2/(dY + 1 - d3Y/dY) * alpha*dY + alpha // = alpha*(z^2*dY/(dY + 1 - d3Y/dY) + 1) // = alpha*(z^2*dY + dY + 1 - d3Y/dY)/(dY + 1 - d3Y/dY) // = alpha*(z^2*dY + dY + 1 - d3Y/dY)/(dY + 1 - d3Y/dY) // = alpha*(d3Y - 2*dY + 2 - d3Y/dY)/(dY + 1 - d3Y/dY) // z^2*dY = d3Y - 3*dY + 1 double numer = (d3Y - 2 * dY - d3YidY + 2) / (dY - 1); double msgMeanTimesPrec = tau * numer / denom; if (msgPrec > double.MaxValue) { // In this case, the message should be the posterior. // posterior mean = (msgMeanTimesPrec + tau)*denom/(tau*tau) // = (numer + denom)/tau return(Gaussian.PointMass((numer + denom) / tau)); } else { return(Gaussian.FromNatural(msgMeanTimesPrec, msgPrec)); } } else if (isPositive.Point) { alpha = sqrtPrec / MMath.NormalCdfRatio(z); } else { alpha = -sqrtPrec / MMath.NormalCdfRatio(-z); } } else { //double v = MMath.LogSumExp(isPositive.LogProbTrue + MMath.NormalCdfLn(z), isPositive.LogProbFalse + MMath.NormalCdfLn(-z)); double v = LogAverageFactor(isPositive, x); alpha = sqrtPrec * Math.Exp(-z * z * 0.5 - MMath.LnSqrt2PI - v) * (2 * isPositive.GetProbTrue() - 1); } // eq (52) in EP quickref (where tau = mnoti/Vnoti) double beta; if (alpha == 0) { beta = 0; // avoid 0 * infinity } else { beta = alpha * (alpha + tau); } double weight = beta / (prec - beta); if (forceProper && weight < 0) { weight = 0; } Gaussian result = new Gaussian(); if (weight == 0) { // avoid 0 * infinity result.MeanTimesPrecision = alpha; } else { // eq (31) in EP quickref; same as inv(inv(beta)-inv(prec)) result.Precision = prec * weight; // eq (30) in EP quickref times above and simplified result.MeanTimesPrecision = weight * (tau + alpha) + alpha; } if (double.IsNaN(result.Precision) || double.IsNaN(result.MeanTimesPrecision)) { throw new InferRuntimeException($"result is NaN. isPositive={isPositive}, x={x}, forceProper={forceProper}"); } return(result); }
public void ExpOpGammaPowerTest() { Assert.True(!double.IsNaN(ExpOp.ExpAverageConditional(GammaPower.Uniform(-1), Gaussian.FromNatural(0.046634157098979417, 0.00078302234897204242), Gaussian.Uniform()).Rate)); Assert.True(!double.IsNaN(ExpOp.ExpAverageConditional(GammaPower.Uniform(-1), Gaussian.FromNatural(0.36153121930654075, 0.0005524890062312658), Gaussian.Uniform()).Rate)); Assert.True(ExpOp.DAverageConditional(GammaPower.PointMass(0, -1), new Gaussian(0, 1), Gaussian.Uniform()).Point < double.MinValue); ExpOp.ExpAverageConditional(GammaPower.FromShapeAndRate(-1, 283.673, -1), Gaussian.FromNatural(0.004859823703146038, 6.6322755562737905E-06), Gaussian.FromNatural(0.00075506803981220758, 8.24487022054953E-07)); GammaPower exp = GammaPower.FromShapeAndRate(0, 0, -1); Gaussian[] ds = new[] { Gaussian.FromNatural(-1.6171314269768655E+308, 4.8976001759138024), Gaussian.FromNatural(-0.037020622891705768, 0.00034989765084474117), Gaussian.PointMass(double.NegativeInfinity), }; foreach (var d in ds) { Gaussian to_d = ExpOp.DAverageConditional(exp, d, Gaussian.Uniform()); Gaussian to_d_slow = ExpOp_Slow.DAverageConditional(exp, d); Assert.True(to_d_slow.MaxDiff(to_d) < 1e-10); to_d = Gaussian.FromNatural(1, 0); GammaPower to_exp = ExpOp.ExpAverageConditional(exp, d, to_d); //Trace.WriteLine($"{to_exp}"); } ExpOp.ExpAverageConditional(GammaPower.FromShapeAndRate(-1, 883.22399999999993, -1), Gaussian.FromNatural(0.0072160312702854888, 8.1788482512051846E-06), Gaussian.FromNatural(0.00057861649495666474, 5.6316164560235272E-07)); }
public void ProductOpTest3() { Gaussian Product = new Gaussian(3.207, 2.222e-06); Gaussian A = new Gaussian(2.854e-06, 1.879e-05); Gaussian B = new Gaussian(0, 1); Gaussian result = GaussianProductOp_Slow.ProductAverageConditional(Product, A, B); Console.WriteLine(result); Assert.False(double.IsNaN(result.Precision)); Product = Gaussian.FromNatural(2, 1); A = Gaussian.FromNatural(0, 3); B = Gaussian.FromNatural(0, 1); result = GaussianProductOp_Slow.ProductAverageConditional(Product, A, B); Console.WriteLine("{0}: {1}", Product, result); Product = Gaussian.FromNatural(129146.60457039363, 320623.20967711863); A = Gaussian.FromNatural(-0.900376203577801, 0.00000001); B = Gaussian.FromNatural(0, 1); result = GaussianProductOp_Slow.ProductAverageConditional(Product, A, B); Console.WriteLine("{0}: {1}", Product, result); Assert.True(GaussianProductOp_Slow.ProductAverageConditional( Gaussian.FromMeanAndVariance(0.0, 1000.0), Gaussian.FromMeanAndVariance(2.0, 3.0), Gaussian.FromMeanAndVariance(5.0, 1.0)).MaxDiff( Gaussian.FromMeanAndVariance(9.911, 79.2) // Gaussian.FromMeanAndVariance(12.110396063215639,3.191559311624262e+002) ) < 1e-4); A = new Gaussian(2, 3); B = new Gaussian(4, 5); Product = Gaussian.PointMass(2); result = GaussianProductOp_Slow.ProductAverageConditional(Product, A, B); Console.WriteLine("{0}: {1}", Product, result); double prevDiff = double.PositiveInfinity; for (int i = 3; i < 40; i++) { double v = System.Math.Pow(0.1, i); Product = Gaussian.FromMeanAndVariance(2, v); Gaussian result2 = GaussianProductOp_Slow.ProductAverageConditional(Product, A, B); double diff = result.MaxDiff(result2); Console.WriteLine("{0}: {1} diff={2}", Product, result2, diff.ToString("g4")); Assert.True(diff <= prevDiff || diff < 1e-6); prevDiff = diff; } Product = Gaussian.Uniform(); result = GaussianProductOp_Slow.ProductAverageConditional(Product, A, B); Console.WriteLine("{0}: {1}", Product, result); prevDiff = double.PositiveInfinity; for (int i = 3; i < 40; i++) { double v = System.Math.Pow(10, i); Product = Gaussian.FromMeanAndVariance(2, v); Gaussian result2 = GaussianProductOp_Slow.ProductAverageConditional(Product, A, B); double diff = result.MaxDiff(result2); Console.WriteLine("{0}: {1} diff={2}", Product, result2, diff.ToString("g4")); Assert.True(diff <= prevDiff || diff < 1e-6); prevDiff = diff; } }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MatrixMultiplyOp"]/message_doc[@name="BAverageLogarithm(DistributionStructArray2D{Gaussian, double}, double[,], DistributionStructArray2D{Gaussian, double}, DistributionStructArray2D{Gaussian, double})"]/*'/> public static GaussianArray2D BAverageLogarithm( [SkipIfUniform] GaussianArray2D matrixMultiply, double[,] A, [Proper, Stochastic] GaussianArray2D B, GaussianArray2D to_B) { GaussianArray2D result = to_B; if (result == null) { result = new GaussianArray2D(B.GetLength(0), B.GetLength(1)); } int rows = matrixMultiply.GetLength(0); int cols = matrixMultiply.GetLength(1); int inner = A.GetLength(1); double[] ab = new double[rows]; //Gaussian temp = new Gaussian(); for (int j = 0; j < cols; j++) { for (int i = 0; i < rows; i++) { double sum = 0.0; for (int k = 0; k < inner; k++) { sum += A[i, k] * B[k, j].GetMean(); } ab[i] = sum; } for (int k = 0; k < inner; k++) { Gaussian old_result = result[k, j]; Gaussian rkj = Gaussian.Uniform(); double Bm = B[k, j].GetMean(); for (int i = 0; i < rows; i++) { double Am = A[i, k]; if (Am == 0) { continue; } Gaussian x = matrixMultiply[i, j]; ab[i] -= Am * Bm; Gaussian msg; if (x.IsPointMass) { msg = Gaussian.PointMass(x.Point / Am); } else { double prec = (Am * Am) * x.Precision; //pm += Am * (x.MeanTimesPrecision - x.Precision * (ab[i] - Am * Bm)); //Replace previous line with: double pm = Am * (x.MeanTimesPrecision - x.Precision * ab[i]); msg = Gaussian.FromNatural(pm, prec); } rkj.SetToProduct(rkj, msg); } result[k, j] = rkj; Gaussian partial = B[k, j] / old_result; Gaussian newPosterior = partial * rkj; Bm = newPosterior.GetMean(); for (int i = 0; i < rows; i++) { ab[i] += Bm * A[i, k]; } } } return(result); }
public void GaussianOpX() { Gaussian uniform = Gaussian.Uniform(); Gaussian X0 = Gaussian.FromMeanAndVariance(3, 0.5); Gaussian Mean0 = Gaussian.FromMeanAndVariance(7, 1.0 / 3); double Precision0 = 3; Gaussian X, Mean; Gamma Precision, to_precision; Gaussian xActual, xExpected; bool testImproper = false; if (testImproper) { // Test the case where precisionIsBetween = false X = Gaussian.FromNatural(1, 2); Mean = Gaussian.FromNatural(3, -1); Precision = Gamma.FromShapeAndRate(4, 5); to_precision = Gamma.FromShapeAndRate(6, 7); xActual = GaussianOp.SampleAverageConditional(X, Mean, Precision, to_precision); } X = Gaussian.FromNatural(-2.7793306963303595, 0.050822473645365768); Mean = Gaussian.FromNatural(-5.9447032851878134E-09, 3.2975231004586637E-204); Precision = Gamma.FromShapeAndRate(318.50907574398883, 9.6226982361933746E+205); to_precision = Gamma.PointMass(0); xActual = GaussianOp.SampleAverageConditional(X, Mean, Precision, to_precision); X = Gaussian.FromNatural(0.1559599323109816, 8.5162535450918462); Mean = Gaussian.PointMass(0.57957597647840942); Precision = Gamma.FromShapeAndRate(7.8308812008325587E+30, 8.2854255911709925E+30); to_precision = Gamma.FromShapeAndRate(1.4709139487775529, 0.14968339171493822); xActual = GaussianOp.SampleAverageConditional(X, Mean, Precision, to_precision); X = Gaussian.FromNatural(0.15595993233964134, 8.5162535466550349); Mean = Gaussian.PointMass(0.57957597647840942); Precision = Gamma.FromShapeAndRate(3.9206259406339067E+20, 4.1481991194547565E+20); to_precision = Gamma.FromShapeAndRate(1.4709139487806249, 0.14968339171413536); xActual = GaussianOp.SampleAverageConditional(X, Mean, Precision, to_precision); X = Gaussian.FromNatural(0.15595993261634511, 8.5162535617468418); Mean = Gaussian.PointMass(0.57957597647840942); Precision = Gamma.FromShapeAndRate(1.825759224425317E+19, 1.9317356258150703E+19); to_precision = Gamma.FromShapeAndRate(1.4709139487887679, 0.14968339176002607); xActual = GaussianOp.SampleAverageConditional(X, Mean, Precision, to_precision); X = Gaussian.FromNatural(0.16501264432785923, 9.01); Mean = Gaussian.PointMass(0.57957597647840942); Precision = Gamma.FromShapeAndRate(1.6965139612477539E+21, 1.6965139612889427E+21); to_precision = Gamma.FromShapeAndRate(1.4695136363119978, 0.14707291154227081); xActual = GaussianOp.SampleAverageConditional(X, Mean, Precision, to_precision); // initialized in a bad place, gets stuck in a flat region X = Gaussian.FromNatural(3.9112579392580757, 11.631097473681082); Mean = Gaussian.FromNatural(10.449696977834144, 5.5617978202886995); Precision = Gamma.FromShapeAndRate(1.0112702817305146, 0.026480506235719053); to_precision = Gamma.FromShapeAndRate(1, 0.029622790537514355); xActual = GaussianOp.SampleAverageConditional(X, Mean, Precision, to_precision); X = Gaussian.FromNatural(57788.170908674481, 50207.150004827061); Mean = Gaussian.PointMass(0); Precision = Gamma.FromShapeAndRate(19764.051194189466, 0.97190264412377791); xActual = GaussianOp.SampleAverageConditional_slow(X, Mean, Precision); // integration bounds should be [-36,4] X = Gaussian.FromNatural(1.696828485456396, 0.71980672726406147); Mean = Gaussian.PointMass(-1); Precision = new Gamma(1, 1); xActual = GaussianOp.SampleAverageConditional_slow(X, Mean, Precision); xExpected = GaussianOp_Slow.SampleAverageConditional(X, Mean, Precision); Assert.True(xExpected.MaxDiff(xActual) < 1e-4); X = new Gaussian(-1.565, 0.8466); Mean = new Gaussian(0.0682, 0.3629); Precision = new Gamma(103.2, 0.009786); xActual = GaussianOp.SampleAverageConditional_slow(X, Mean, Precision); xExpected = GaussianOp_Slow.SampleAverageConditional(X, Mean, Precision); Assert.True(xExpected.MaxDiff(xActual) < 1e-4); // Fixed precision X = X0; Mean = uniform; Assert.True(GaussianOp.SampleAverageConditional(Mean, Precision0).MaxDiff(uniform) < 1e-10); Mean = Mean0; Assert.True(GaussianOp.SampleAverageConditional(Mean, Precision0).MaxDiff(new Gaussian(Mean.GetMean(), Mean.GetVariance() + 1 / Precision0)) < 1e-10); Mean = Gaussian.PointMass(Mean0.GetMean()); Assert.True(GaussianOp.SampleAverageConditional(Mean, Precision0).MaxDiff(new Gaussian(Mean.GetMean(), 1 / Precision0)) < 1e-10); // Uniform precision // the answer should always be uniform Precision = Gamma.Uniform(); Assert.True(GaussianOp.SampleAverageConditional_slow(X, Mean, Precision).MaxDiff(uniform) < 1e-10); // Unknown precision Precision = Gamma.FromShapeAndScale(3, 3); // Known X X = Gaussian.PointMass(X0.GetMean()); Mean = uniform; Assert.True(GaussianOp.SampleAverageConditional_slow(X, Mean, Precision).MaxDiff(uniform) < 1e-10); // Unknown X X = X0; Mean = uniform; //Console.WriteLine(XAverageConditional2(result)); Assert.True(GaussianOp.SampleAverageConditional_slow(X, Mean, Precision).MaxDiff(uniform) < 1e-10); X = X0; Mean = Mean0; // converge the precision message. (only matters if KeepLastMessage is set). //for (int i = 0; i < 10; i++) GaussianOp.PrecisionAverageConditional(X, Mean, Precision, precisionMessage); // in matlab: test_t_msg if (GaussianOp.ForceProper) { Assert.True(GaussianOp.SampleAverageConditional_slow(X, Mean, Precision).MaxDiff(Gaussian.FromNatural(3.1495, 0)) < 1e-4); } else { Assert.True(GaussianOp.SampleAverageConditional_slow(X, Mean, Precision).MaxDiff(new Gaussian(-9.9121, -4.5998)) < 1e-4); } X = X0; Mean = Gaussian.PointMass(Mean0.GetMean()); // converge the precision message. (only matters if KeepLastMessage is set). //for (int i = 0; i < 10; i++) GaussianOp.PrecisionAverageConditional(X, Mean, Precision, precisionMessage); // in matlab: test_t_msg if (GaussianOp.ForceProper) { Assert.True(GaussianOp.SampleAverageConditional_slow(X, Mean, Precision).MaxDiff(Gaussian.FromNatural(2.443, 0)) < 1e-4); } else { Assert.True(GaussianOp.SampleAverageConditional_slow(X, Mean, Precision).MaxDiff(new Gaussian(0.81394, -1.3948)) < 1e-4); } // Uniform X X = uniform; Mean = Mean0; // converge the precision message. (only matters if KeepLastMessage is set). //for (int i = 0; i < 10; i++) GaussianOp.PrecisionAverageConditional(X, Mean, Precision, precisionMessage); Assert.True(GaussianOp.SampleAverageConditional_slow(X, Mean, Precision).MaxDiff(new Gaussian(7, 0.5)) < 1e-10); X = uniform; Mean = Gaussian.PointMass(Mean0.GetMean()); // converge the precision message. (only matters if KeepLastMessage is set). //for (int i = 0; i < 10; i++) GaussianOp.PrecisionAverageConditional(X, Mean, Precision, precisionMessage); Assert.True(GaussianOp.SampleAverageConditional_slow(X, Mean, Precision).MaxDiff(new Gaussian(7, 1.0 / 6)) < 1e-10); }
public void GaussianOpPrecision() { Gamma precMsg, precMsg2; Gaussian X, Mean; Gamma Precision; X = Gaussian.FromNatural(-1.5098177152950143E-09, 1.061649960537027E-168); Mean = Gaussian.FromNatural(-3.6177299471249587, 0.11664740799025652); Precision = Gamma.FromShapeAndRate(306.39423695125572, 1.8326832031565403E+170); precMsg = Gamma.PointMass(0); precMsg2 = GaussianOp_Slow.PrecisionAverageConditional(X, Mean, Precision); Assert.True(precMsg.MaxDiff(precMsg2) < 1e-4); precMsg2 = GaussianOp.PrecisionAverageConditional(X, Mean, Precision); Assert.True(precMsg.MaxDiff(precMsg2) < 1e-4); X = Gaussian.FromNatural(-0.55657497231637854, 6.6259783218464713E-141); Mean = Gaussian.FromNatural(-2.9330116542965374, 0.07513822741674292); Precision = Gamma.FromShapeAndRate(308.8184220331475, 4.6489382805051884E+142); precMsg = Gamma.FromShapeAndRate(1.5000000000000628, 3.5279086383286634E+279); precMsg2 = GaussianOp_Slow.PrecisionAverageConditional(X, Mean, Precision); Assert.True(precMsg.MaxDiff(precMsg2) < 1e-4); precMsg2 = GaussianOp.PrecisionAverageConditional(X, Mean, Precision); Assert.True(precMsg.MaxDiff(precMsg2) < 1e-4); X = Gaussian.FromNatural(0, 1.0705890985886898E-153); Mean = Gaussian.PointMass(0); Precision = Gamma.FromShapeAndRate(1.6461630749684018, 1.0021354807958952E+153); precMsg = Gamma.FromShapeAndRate(1.3230815374839406, 5.7102212927459039E+151); precMsg2 = GaussianOp_Slow.PrecisionAverageConditional(X, Mean, Precision); Assert.True(precMsg.MaxDiff(precMsg2) < 1e-4); precMsg2 = GaussianOp.PrecisionAverageConditional(X, Mean, Precision); Assert.True(precMsg.MaxDiff(precMsg2) < 1e-4); GaussianOp.PrecisionAverageConditional(Gaussian.FromNatural(0, 0.00849303091340374), Gaussian.FromNatural(0.303940178036662, 0.0357912415805232), Gamma.FromNatural(0.870172077263786 - 1, 0.241027170904459)); GaussianOp.PrecisionAverageConditional(Gaussian.FromNatural(0, 0.932143343115292), Gaussian.FromNatural(0.803368837946732, 0.096549750816333), Gamma.FromNatural(0.63591693650741 - 1, 0.728459389753854)); GaussianOp.PrecisionAverageConditional(Gaussian.FromNatural(0, 0.799724777601531), Gaussian.FromNatural(0.351882387116497, 0.0795619408970522), Gamma.FromNatural(0.0398852019756498 - 1, 0.260567798400562)); GaussianOp.PrecisionAverageConditional(Gaussian.FromNatural(0, 0.826197353576402), Gaussian.FromNatural(0.655970732055591, 0.125333868956814), Gamma.FromNatural(0.202543332801453 - 1, 0.147645744563847)); precMsg = GaussianOp.PrecisionAverageConditional(new Gaussian(-6.235e+207, 1.947e+209), Gaussian.PointMass(11), Gamma.PointMass(7)); Assert.True(!double.IsNaN(precMsg.Rate)); Gaussian X0 = Gaussian.FromMeanAndVariance(3, 0.5); Gaussian Mean0 = Gaussian.FromMeanAndVariance(7, 1.0 / 3); Gamma Precision0 = Gamma.FromShapeAndScale(3, 3); precMsg = GaussianOp_Slow.PrecisionAverageConditional(Gaussian.FromNatural(0.010158033515400506, 0.0041117304509528533), Gaussian.FromNatural(33.157651455559929, 13.955304749880149), Gamma.FromShapeAndRate(7.1611372018172794, 1.8190207317123008)); precMsg = GaussianOp_Slow.PrecisionAverageConditional(Gaussian.FromNatural(-0.020177353724675218, 0.0080005002339157711), Gaussian.FromNatural(-12.303440746896294, 4.6439574387849714), Gamma.FromShapeAndRate(5.6778922774773992, 1.0667129560350435)); precMsg = GaussianOp_Slow.PrecisionAverageConditional(Gaussian.PointMass(248), Gaussian.FromNatural(0.099086933095776319, 0.00032349393599347853), Gamma.FromShapeAndRate(0.001, 0.001)); precMsg2 = GaussianOp.PrecisionAverageConditional_slow(Gaussian.PointMass(248), Gaussian.FromNatural(0.099086933095776319, 0.00032349393599347853), Gamma.FromShapeAndRate(0.001, 0.001)); Assert.True(precMsg.MaxDiff(precMsg2) < 0.3); precMsg = GaussianOp_Slow.PrecisionAverageConditional(Gaussian.FromNatural(-0.21769764449791806, 0.0000024898838689952023), Gaussian.FromNatural(0, 0.5), Gamma.FromShapeAndRate(5, 5)); precMsg2 = GaussianOp.PrecisionAverageConditional_slow(Gaussian.FromNatural(-0.21769764449791806, 0.0000024898838689952023), Gaussian.FromNatural(0, 0.5), Gamma.FromShapeAndRate(5, 5)); //Console.WriteLine("{0} should be {1}", precMsg2, precMsg); Assert.True(precMsg.MaxDiff(precMsg2) < 1e-4); Gamma precMsg3 = GaussianOp_Laplace.PrecisionAverageConditional_slow(Gaussian.FromNatural(-0.21769764449791806, 0.0000024898838689952023), Gaussian.FromNatural(0, 0.5), Gamma.FromShapeAndRate(5, 5)); precMsg2 = GaussianOp.PrecisionAverageConditional(Gaussian.FromNatural(-0.21769764449791806, 0.0000024898838689952023), Gaussian.FromNatural(0, 0.5), Gamma.FromShapeAndRate(5, 5)); //Console.WriteLine("{0} should be {1}", precMsg2, precMsg); Assert.True(precMsg.MaxDiff(precMsg2) < 1e-4); Assert.True(GaussianOp.PrecisionAverageConditional_slow(Gaussian.FromNatural(-2.3874057896477092, 0.0070584383295080044), Gaussian.FromNatural(1.3999879871144227, 0.547354438587195), Gamma.FromShapeAndRate(3, 1)) .MaxDiff(Gamma.FromShapeAndRate(1.421, 55546)) < 10); // Unknown precision if (GaussianOp.ForceProper) { Assert.True(GaussianOp.PrecisionAverageConditional_slow(X0, Mean0, Precision0).MaxDiff(Gamma.FromShapeAndRate(1, 0.3632)) < 1e-4); } else { Assert.True(GaussianOp.PrecisionAverageConditional_slow(X0, Mean0, Precision0).MaxDiff(Gamma.FromShapeAndRate(-0.96304, -0.092572)) < 1e-4); } if (GaussianOp.ForceProper) { Assert.True(GaussianOp.PrecisionAverageConditional_slow(Gaussian.PointMass(3.0), Mean0, Precision0).MaxDiff(Gamma.FromShapeAndRate(1, 4.13824)) < 1e-4); } else { Assert.True(GaussianOp.PrecisionAverageConditional_slow(Gaussian.PointMass(3.0), Mean0, Precision0).MaxDiff(Gamma.FromShapeAndRate(-0.24693, 2.2797)) < 1e-4); } Assert.True(GaussianOp.PrecisionAverageConditional(3.0, 7.0).MaxDiff(Gamma.FromShapeAndRate(1.5, 8.0)) < 1e-4); Assert.True(GaussianOp.PrecisionAverageConditional_slow(new Gaussian(), Gaussian.PointMass(7.0), Precision0).MaxDiff(Gamma.FromShapeAndRate(1.0, 0.0)) < 1e-4); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DoublePlusOp"]/message_doc[@name="AAverageConditional(double, Gaussian)"]/*'/> public static Gaussian AAverageConditional(double Sum, [SkipIfUniform] Gaussian b) { return(SumAverageConditional(Sum, Gaussian.FromNatural(-b.MeanTimesPrecision, b.Precision))); }
internal void StudentIsPositiveTest2() { GaussianOp.ForceProper = false; double shape = 1; double mean = -1; Gamma precPrior = Gamma.FromShapeAndRate(shape, shape); Gaussian meanPrior = Gaussian.PointMass(mean); double evExpected; Gaussian xExpected = StudentIsPositiveExact(mean, precPrior, out evExpected); Gaussian xF2 = Gaussian.FromMeanAndVariance(-1, 1); // the energy has a stationary point here (min in both dimensions), even though xF0 is improper Gaussian xB0 = new Gaussian(2, 1); xF2 = Gaussian.FromMeanAndVariance(-4.552, 6.484); //xB0 = new Gaussian(1.832, 0.9502); //xB0 = new Gaussian(1.792, 1.558); //xB0 = new Gaussian(1.71, 1.558); //xB0 = new Gaussian(1.792, 1.5); Gaussian xF0 = GaussianOp_Slow.SampleAverageConditional(xB0, meanPrior, precPrior); //Console.WriteLine("xB0 = {0} xF0 = {1}", xB0, xF0); //Console.WriteLine(xF0*xB0); //Console.WriteLine(xF2*xB0); xF2 = new Gaussian(0.8651, 1.173); xB0 = new Gaussian(-4, 2); xB0 = new Gaussian(7, 7); if (false) { xF2 = new Gaussian(mean, 1); double[] xs = EpTests.linspace(0, 100, 1000); double[] logTrue = Util.ArrayInit(xs.Length, i => GaussianOp.LogAverageFactor(xs[i], mean, precPrior)); Normalize(logTrue); xF2 = FindxF4(xs, logTrue, xF2); xF2 = Gaussian.FromNatural(-0.85, 0); xB0 = IsPositiveOp.XAverageConditional(true, xF2); Console.WriteLine("xF = {0} xB = {1}", xF2, xB0); Console.WriteLine("x = {0} should be {1}", xF2 * xB0, xExpected); Console.WriteLine("proj[T*xB] = {0}", GaussianOp_Slow.SampleAverageConditional(xB0, meanPrior, precPrior) * xB0); double ev = System.Math.Exp(IsPositiveOp.LogAverageFactor(true, xF2) + GaussianOp_Slow.LogAverageFactor(xB0, meanPrior, precPrior) - xF2.GetLogAverageOf(xB0)); Console.WriteLine("evidence = {0} should be {1}", ev, evExpected); return; } if (false) { xF2 = new Gaussian(mean, 1); xF2 = FindxF3(xExpected, evExpected, meanPrior, precPrior, xF2); xB0 = IsPositiveOp.XAverageConditional(true, xF2); Console.WriteLine("xF = {0} xB = {1}", xF2, xB0); Console.WriteLine("x = {0} should be {1}", xF2 * xB0, xExpected); //double ev = Math.Exp(IsPositiveOp.LogAverageFactor(true, xF2) + GaussianOp.LogAverageFactor_slow(xB0, meanPrior, precPrior) - xF2.GetLogAverageOf(xB0)); //Console.WriteLine("evidence = {0} should be {1}", ev, evExpected); return; } if (false) { xF2 = new Gaussian(-2, 10); xF2 = FindxF2(meanPrior, precPrior, xF2); xB0 = IsPositiveOp.XAverageConditional(true, xF2); xF0 = GaussianOp_Slow.SampleAverageConditional(xB0, meanPrior, precPrior); Console.WriteLine("xB = {0}", xB0); Console.WriteLine("xF = {0} should be {1}", xF0, xF2); return; } if (false) { xF2 = new Gaussian(-3998, 4000); xF2 = new Gaussian(0.8651, 1.173); xB0 = new Gaussian(-4, 2); xB0 = new Gaussian(2000, 1e-5); xB0 = FindxB(xB0, meanPrior, precPrior, xF2); xF0 = GaussianOp_Slow.SampleAverageConditional(xB0, meanPrior, precPrior); Console.WriteLine("xB = {0}", xB0); Console.WriteLine("xF = {0} should be {1}", xF0, xF2); return; } if (false) { //xF2 = new Gaussian(-7, 10); //xF2 = new Gaussian(-50, 52); xB0 = new Gaussian(-1.966, 5.506e-08); //xF2 = new Gaussian(-3998, 4000); xF0 = FindxF(xB0, meanPrior, precPrior, xF2); Gaussian xB2 = IsPositiveOp.XAverageConditional(true, xF0); Console.WriteLine("xF = {0}", xF0); Console.WriteLine("xB = {0} should be {1}", xB2, xB0); return; } if (true) { xF0 = new Gaussian(-3.397e+08, 5.64e+08); xF0 = new Gaussian(-2.373e+04, 2.8e+04); xB0 = new Gaussian(2.359, 1.392); xF0 = Gaussian.FromNatural(-0.84, 0); //xF0 = Gaussian.FromNatural(-0.7, 0); for (int iter = 0; iter < 10; iter++) { xB0 = FindxB(xB0, meanPrior, precPrior, xF0); Gaussian xFt = GaussianOp_Slow.SampleAverageConditional(xB0, meanPrior, precPrior); Console.WriteLine("xB = {0}", xB0); Console.WriteLine("xF = {0} should be {1}", xFt, xF0); xF0 = FindxF0(xB0, meanPrior, precPrior, xF0); Gaussian xBt = IsPositiveOp.XAverageConditional(true, xF0); Console.WriteLine("xF = {0}", xF0); Console.WriteLine("xB = {0} should be {1}", xBt, xB0); } Console.WriteLine("x = {0} should be {1}", xF0 * xB0, xExpected); double ev = System.Math.Exp(IsPositiveOp.LogAverageFactor(true, xF0) + GaussianOp_Slow.LogAverageFactor(xB0, meanPrior, precPrior) - xF0.GetLogAverageOf(xB0)); Console.WriteLine("evidence = {0} should be {1}", ev, evExpected); return; } //var precs = EpTests.linspace(1e-6, 1e-5, 200); var precs = EpTests.linspace(xB0.Precision / 11, xB0.Precision, 100); //var precs = EpTests.linspace(xF0.Precision/20, xF0.Precision/3, 100); precs = EpTests.linspace(1e-9, 1e-5, 100); //precs = new double[] { xB0.Precision }; var ms = EpTests.linspace(xB0.GetMean() - 1, xB0.GetMean() + 1, 100); //var ms = EpTests.linspace(xF0.GetMean()-1, xF0.GetMean()+1, 100); //precs = EpTests.linspace(1.0/10, 1.0/8, 200); ms = EpTests.linspace(2000, 4000, 100); //ms = new double[] { xB0.GetMean() }; Matrix result = new Matrix(precs.Length, ms.Length); Matrix result2 = new Matrix(precs.Length, ms.Length); //ms = new double[] { 0.7 }; for (int j = 0; j < ms.Length; j++) { double maxZ = double.NegativeInfinity; double minZ = double.PositiveInfinity; Gaussian maxxF = Gaussian.Uniform(); Gaussian minxF = Gaussian.Uniform(); Gaussian maxxB = Gaussian.Uniform(); Gaussian minxB = Gaussian.Uniform(); Vector v = Vector.Zero(3); for (int i = 0; i < precs.Length; i++) { Gaussian xF = Gaussian.FromMeanAndPrecision(ms[j], precs[i]); xF = xF2; Gaussian xB = IsPositiveOp.XAverageConditional(true, xF); xB = Gaussian.FromMeanAndPrecision(ms[j], precs[i]); //xB = xB0; v[0] = IsPositiveOp.LogAverageFactor(true, xF); v[1] = GaussianOp.LogAverageFactor_slow(xB, meanPrior, precPrior); //v[1] = GaussianOp_Slow.LogAverageFactor(xB, meanPrior, precPrior); v[2] = -xF.GetLogAverageOf(xB); double logZ = v.Sum(); double Z = logZ; if (Z > maxZ) { maxZ = Z; maxxF = xF; maxxB = xB; } if (Z < minZ) { minZ = Z; minxF = xF; minxB = xB; } result[i, j] = Z; result2[i, j] = IsPositiveOp.LogAverageFactor(true, xF) + xF0.GetLogAverageOf(xB) - xF.GetLogAverageOf(xB); //Gaussian xF3 = GaussianOp.SampleAverageConditional_slower(xB, meanPrior, precPrior); //result[i, j] = Math.Pow(xF3.Precision - xF.Precision, 2); //result2[i, j] = Math.Pow((xF2*xB).Precision - (xF*xB).Precision, 2); //result2[i, j] = -xF.GetLogAverageOf(xB); //Gaussian xF2 = GaussianOp.SampleAverageConditional_slow(xB, Gaussian.PointMass(0), precPrior); Gaussian xMarginal = xF * xB; //Console.WriteLine("xF = {0} Z = {1} x = {2}", xF, Z.ToString("g4"), xMarginal); } double delta = v[1] - v[2]; //Console.WriteLine("xF = {0} xB = {1} maxZ = {2} x = {3}", maxxF, maxxB, maxZ.ToString("g4"), maxxF*maxxB); //Console.WriteLine("xF = {0} maxZ = {1} delta = {2}", maxxF, maxZ.ToString("g4"), delta.ToString("g4")); Console.WriteLine("xF = {0} xB = {1} minZ = {2} x = {3}", minxF, minxB, minZ.ToString("g4"), minxF * minxB); } //TODO: change path for cross platform using using (var writer = new MatlabWriter(@"..\..\..\Tests\student.mat")) { writer.Write("z", result); writer.Write("z2", result2); writer.Write("precs", precs); writer.Write("ms", ms); } }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MatrixMultiplyOp"]/message_doc[@name="AAverageLogarithm(DistributionStructArray2D{Gaussian, double}, DistributionStructArray2D{Gaussian, double}, DistributionStructArray2D{Gaussian, double}, DistributionStructArray2D{Gaussian, double})"]/*'/> public static GaussianArray2D AAverageLogarithm( [SkipIfUniform] GaussianArray2D matrixMultiply, [Stochastic] GaussianArray2D A, [SkipIfUniform] GaussianArray2D B, GaussianArray2D to_A) { GaussianArray2D result = to_A; if (result == null) { result = new DistributionStructArray2D <Gaussian, double>(A.GetLength(0), A.GetLength(1)); } // E[log N(x[i,j]; a[i,:]*b[:,j], 0)] = -0.5 E[(x[i,j]- sum_k a[i,k]*b[k,j])^2]/0 // = -0.5 (E[x[i,j]^2] - 2 E[x[i,j]] a[i,k] E[b[k,j]] + a[i,k] a[i,k2] E(b[k,j] b[k2,j]))/0 // a[i,k] * (-2 E[x[i,j]] E[b[k,j]] + sum_{k2 not k} E[a[i,k2]] E(b[k,j] b[k2,j])) // a[i,k]^2 * E(b[k,j]^2) // message to a[i,k] = N(a; inv(prec[i,k])*(sum_j E[b[k,j]]*res[i,j,k]/var(x[i,j])), inv(prec[i,k])) // where res[i,j,k] = E[x[i,j]] - sum_{k2 not k} E[a[i,k2]] E[b[k2,j]] // prec[i,k] = sum_j E(b[k,j]^2)/var(x[i,j]) // result.Precision = prec[i,k] // result.MeanTimesPrecision = sum_j E[b[k,j]]*res[i,j,k]/var(x[i,j]) // = sum_j E[b[k,j]]*(X.MeanTimesPrecision - X.precision*(sum_{k2 not k})) int rows = matrixMultiply.GetLength(0); int cols = matrixMultiply.GetLength(1); int inner = A.GetLength(1); double[] ab = new double[cols]; //Gaussian temp = new Gaussian(); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { double sum = 0.0; for (int k = 0; k < inner; k++) { sum += A[i, k].GetMean() * B[k, j].GetMean(); } ab[j] = sum; } for (int k = 0; k < inner; k++) { Gaussian old_result = result[i, k]; Gaussian rik = Gaussian.Uniform(); double Am = A[i, k].GetMean(); for (int j = 0; j < cols; j++) { double Bm, Bv; B[k, j].GetMeanAndVariance(out Bm, out Bv); if (Bm == 0) { continue; } Gaussian x = matrixMultiply[i, j]; ab[j] -= Am * Bm; Gaussian msg; if (x.IsPointMass) { msg = Gaussian.PointMass((x.Point * Bm) / (Bv + Bm * Bm)); } else { double prec = (Bv + Bm * Bm) * x.Precision; //pm += Bm * (x.MeanTimesPrecision - x.Precision * (ab[j] - Am * Bm)); //Replace previous line with: double pm = Bm * (x.MeanTimesPrecision - x.Precision * ab[j]); msg = Gaussian.FromNatural(pm, prec); } rik.SetToProduct(rik, msg); } result[i, k] = rik; Gaussian partial = A[i, k] / old_result; Gaussian newPosterior = partial * rik; Am = newPosterior.GetMean(); for (int j = 0; j < cols; j++) { ab[j] += Am * B[k, j].GetMean(); } } } return(result); }