Пример #1
0
        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);
            }
        }
Пример #2
0
        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));
        }
Пример #3
0
        /// <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));
            }
        }
Пример #4
0
        /// <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));
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        /// <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));
        }
Пример #8
0
        /// <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));
        }
Пример #10
0
        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);
        }
Пример #12
0
        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);
        }
Пример #13
0
        /// <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);
        }
Пример #14
0
        /// <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);
            }
        }
Пример #15
0
        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);
        }
Пример #16
0
        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);
        }
Пример #17
0
        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;
            }
        }
Пример #19
0
        /// <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);
        }
Пример #20
0
        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);
        }
Пример #21
0
        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);
        }
Пример #22
0
 /// <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)));
 }
Пример #23
0
        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);
            }
        }
Пример #24
0
        /// <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);
        }