Beispiel #1
0
        /// <summary>VMP message to <c>probTrue</c>.</summary>
        /// <param name="sample">Incoming message from <c>sample</c>.</param>
        /// <returns>The outgoing VMP message to the <c>probTrue</c> argument.</returns>
        /// <remarks>
        ///   <para>The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except <c>probTrue</c>. The formula is <c>exp(sum_(sample) p(sample) log(factor(sample,probTrue)))</c>.</para>
        /// </remarks>
        public static Beta ProbTrueAverageLogarithm(Bernoulli sample)
        {
            // E[x*log(p) + (1-x)*log(1-p)] = E[x]*log(p) + (1-E[x])*log(1-p)
            double ex = sample.GetProbTrue();

            return(new Beta(1 + ex, 2 - ex));
        }
 public static Bernoulli AAverageConditional(Bernoulli b, double penalty)
 {
     double penaltyFactor = Math.Exp(-penalty);
     double bProbTrue = b.GetProbTrue();
     double probTrue = (penaltyFactor * (1 - bProbTrue) + bProbTrue) / (penaltyFactor + 1);
     return new Bernoulli(probTrue);
 }
        /// <summary>EP message to <c>sample</c>.</summary>
        /// <param name="choice">Incoming message from <c>choice</c>.</param>
        /// <param name="probTrue0">Constant value for <c>probTrue0</c>.</param>
        /// <param name="probTrue1">Constant value for <c>probTrue1</c>.</param>
        /// <returns>The outgoing EP message to the <c>sample</c> argument.</returns>
        /// <remarks>
        ///   <para>The outgoing message is a distribution matching the moments of <c>sample</c> as the random arguments are varied. The formula is <c>proj[p(sample) sum_(choice) p(choice) factor(sample,choice,probTrue0,probTrue1)]/p(sample)</c>.</para>
        /// </remarks>
        public static Bernoulli SampleAverageConditional(Bernoulli choice, double probTrue0, double probTrue1)
        {
            Bernoulli result = new Bernoulli();

            if (choice.IsPointMass)
            {
                return(SampleConditional(choice.Point, probTrue0, probTrue1));
            }
#if FAST
            result.SetProbTrue(choice.GetProbFalse() * probTrue0 + choice.GetProbTrue() * probTrue1);
#else
            // This method is more numerically stable but slower.
            // let oX = log(p(X)/(1-p(X))
            // let oY = log(p(Y)/(1-p(Y))
            // oX = log( (TT*sigma(oY) + TF*sigma(-oY))/(FT*sigma(oY) + FF*sigma(-oY)) )
            //    = log( (TT*exp(oY) + TF)/(FT*exp(oY) + FF) )
            //    = log( (exp(oY) + TF/TT)/(exp(oY) + FF/FT) ) + log(TT/FT)
            // ay = log(TF/TT)
            // by = log(FF/FT)
            // offset = log(TT/FT)
            if (probTrue0 == 0 || probTrue1 == 0)
            {
                throw new ArgumentException("probTrue is zero");
            }
            double ay     = Math.Log(probTrue0 / probTrue1);
            double by     = Math.Log((1 - probTrue0) / (1 - probTrue1));
            double offset = MMath.Logit(probTrue1);
            result.LogOdds = MMath.DiffLogSumExp(choice.LogOdds, ay, by) + offset;
#endif
            return(result);
        }
        /// <summary>
        /// EP message to 'b'
        /// </summary>
        /// <param name="isGreaterThan">Incoming message from 'isGreaterThan'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
        /// <param name="a">Incoming message from 'a'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'b' as the random arguments are varied.
        /// The formula is <c>proj[p(b) sum_(isGreaterThan,a) p(isGreaterThan,a) factor(isGreaterThan,a,b)]/p(b)</c>.
        /// </para></remarks>
        /// <exception cref="ImproperMessageException"><paramref name="isGreaterThan"/> is not a proper distribution</exception>
        static public Discrete BAverageConditional([SkipIfUniform] Bernoulli isGreaterThan, Discrete a, Discrete result)
        {
            if (a.IsPointMass)
            {
                return(BAverageConditional(isGreaterThan, a.Point, result));
            }
            Vector bProbs    = result.GetWorkspace();
            double probTrue  = isGreaterThan.GetProbTrue();
            double probFalse = 1 - probTrue;

            for (int j = 0; j < bProbs.Count; j++)
            {
                double sum0 = 0.0;
                int    i    = 0;
                for (; (i <= j) && (i < a.Dimension); i++)
                {
                    sum0 += a[i];
                }
                double sum1 = 0.0;
                for (; i < a.Dimension; i++)
                {
                    sum1 += a[i];
                }
                bProbs[j] = probTrue * sum1 + probFalse * sum0;
            }
            result.SetProbs(bProbs);
            return(result);
        }
        private static void Experiment_1()
        {
            // PM erstellen
            Variable <bool> ersteMünzeWurf  = Variable.Bernoulli(0.5);
            Variable <bool> zweiteMünzeWurf = Variable.Bernoulli(0.5);
            Variable <bool> beideMünzenWurf = ersteMünzeWurf & zweiteMünzeWurf;

            // Inferenz-Engine (IE) erstellen
            InferenceEngine engine = new InferenceEngine();

#if SHOW_MODEL
            engine.ShowFactorGraph = true; // PM visualisieren
#endif

            // Inferenz ausführen
            Bernoulli ergebnis = engine.Infer <Bernoulli>(beideMünzenWurf);
            double    beideMünzenZeigenKöpfe = ergebnis.GetProbTrue();


            Console.WriteLine("Die Wahrscheinlichkeit - beide Münzen " +
                              "zeigen Köpfe: {0}", beideMünzenZeigenKöpfe);



            beideMünzenWurf.ObservedValue = false; // Beobachtung einführen - beide Münzen zeigen niemals Kopf gleichzeitig

            Bernoulli ergebnis2 = engine.Infer <Bernoulli>(beideMünzenWurf);
            Bernoulli ergebnis3 = engine.Infer <Bernoulli>(ersteMünzeWurf);
            Console.WriteLine("Die Wahrscheinlichkeit - beide Münzen zeigen Köpfe: {0}", ergebnis2.GetProbTrue());
            Console.WriteLine("Erste Münze zeigt Kopf: {0}", ergebnis3.GetProbTrue());
        }
        /// <summary>
        /// EP message to 'a'
        /// </summary>
        /// <param name="isGreaterThan">Incoming message from 'isGreaterThan'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
        /// <param name="b">Incoming message from 'b'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'a' as the random arguments are varied.
        /// The formula is <c>proj[p(a) sum_(isGreaterThan,b) p(isGreaterThan,b) factor(isGreaterThan,a,b)]/p(a)</c>.
        /// </para></remarks>
        /// <exception cref="ImproperMessageException"><paramref name="isGreaterThan"/> is not a proper distribution</exception>
        static public Discrete AAverageConditional([SkipIfUniform] Bernoulli isGreaterThan, Discrete b, Discrete result)
        {
            if (b.IsPointMass)
            {
                return(AAverageConditional(isGreaterThan, b.Point, result));
            }
            Vector aProbs    = result.GetWorkspace();
            double probTrue  = isGreaterThan.GetProbTrue();
            double probFalse = 1 - probTrue;

            for (int i = 0; i < aProbs.Count; i++)
            {
                double sum1 = 0.0;
                int    j    = 0;
                for (; (j < i) && (j < b.Dimension); j++)
                {
                    sum1 += b[j];
                }
                double sum0 = 0.0;
                for (; j < b.Dimension; j++)
                {
                    sum0 += b[j];
                }
                aProbs[i] = probTrue * sum1 + probFalse * sum0;
            }
            result.SetProbs(aProbs);
            return(result);
        }
Beispiel #7
0
        /// <summary>
        /// Computes the point estimate for a <see cref="Bernoulli"/> distribution using a specified loss function.
        /// </summary>
        /// <param name="distribution">The <see cref="Bernoulli"/> distribution.</param>
        /// <param name="lossFunction">The loss function.</param>
        /// <returns>The point estimate.</returns>
        public static bool GetEstimate(Bernoulli distribution, Func <bool, bool, double> lossFunction)
        {
            if (lossFunction == null)
            {
                throw new ArgumentNullException(nameof(lossFunction));
            }

            bool   argminRisk = false;
            double minRisk    = double.PositiveInfinity;
            double probTrue   = distribution.GetProbTrue();
            double probFalse  = 1 - probTrue;

            foreach (bool truth in new[] { true, false })
            {
                double risk = 0;
                foreach (bool estimate in new[] { true, false })
                {
                    risk += (estimate ? probTrue : probFalse) * lossFunction(truth, estimate);

                    // Early bailout
                    if (risk > minRisk)
                    {
                        break;
                    }
                }

                if (risk < minRisk)
                {
                    minRisk    = risk;
                    argminRisk = truth;
                }
            }

            return(argminRisk);
        }
Beispiel #8
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="BooleanAreEqualOp"]/message_doc[@name="AAverageLogarithm(Bernoulli, Bernoulli)"]/*'/>
 public static Bernoulli AAverageLogarithm([SkipIfUniform] Bernoulli areEqual, [SkipIfUniform] Bernoulli B)
 {
     if (areEqual.IsPointMass)
     {
         return(AAverageLogarithm(areEqual.Point, B));
     }
     // when AreEqual is marginalized, the factor is proportional to exp((A==B)*areEqual.LogOdds)
     return(Bernoulli.FromLogOdds(areEqual.LogOdds * (2 * B.GetProbTrue() - 1)));
 }
		/// <summary>
		/// Evidence message for VMP.
		/// </summary>
		/// <param name="sample">Incoming message from sample</param>
		/// <param name="logOdds">Incoming message from logOdds</param>
		/// <returns><c>sum_x marginal(x)*log(factor(x))</c></returns>
		/// <remarks><para>
		/// The formula for the result is <c>int log(f(x)) q(x) dx</c>
		/// where <c>x = (sample,logOdds)</c>.
		/// </para></remarks>
		public static double AverageLogFactor(Bernoulli sample, [Proper, SkipIfUniform] Gaussian logOdds)
		{
			if (logOdds.IsUniform()) return 0.0;
			double m, v;
			logOdds.GetMeanAndVariance(out m, out v);
			double t = Math.Sqrt(m * m + v);
			double s = 2 * sample.GetProbTrue() - 1;  // probTrue - probFalse
			return MMath.LogisticLn(t) + (s * m - t) / 2;
		}
Beispiel #10
0
        /// <summary>Evidence message for VMP.</summary>
        /// <param name="sample">Incoming message from <c>sample</c>.</param>
        /// <param name="logOdds">Incoming message from <c>logOdds</c>. Must be a proper distribution. If uniform, the result will be uniform.</param>
        /// <returns>Average of the factor's log-value across the given argument distributions.</returns>
        /// <remarks>
        ///   <para>The formula for the result is <c>sum_(sample,logOdds) p(sample,logOdds) log(factor(sample,logOdds))</c>. Adding up these values across all factors and variables gives the log-evidence estimate for VMP.</para>
        /// </remarks>
        /// <exception cref="ImproperMessageException">
        ///   <paramref name="logOdds" /> is not a proper distribution.</exception>
        public static double AverageLogFactor(Bernoulli sample, [Proper, SkipIfUniform] Gaussian logOdds)
        {
            // f(sample,logOdds) = exp(sample*logOdds)/(1 + exp(logOdds))
            // log f(sample,logOdds) = sample*logOdds - log(1 + exp(logOdds))
            double m, v;

            logOdds.GetMeanAndVariance(out m, out v);
            return(sample.GetProbTrue() * m - MMath.Log1PlusExpGaussian(m, v));
        }
Beispiel #11
0
        public void EulerProject205()
        {
            // Peter has nine four-sided (pyramidal) dice, each with faces numbered 1, 2, 3, 4.
            // Colin has six six-sided (cubic) dice, each with faces numbered 1, 2, 3, 4, 5, 6.
            //
            // Peter and Colin roll their dice and compare totals: the highest total wins.
            // The result is a draw if the totals are equal.
            //
            // What is the probability that Pyramidal Pete beats Cubic Colin?
            // http://projecteuler.net/index.php?section=problems&id=205

            // We encode this problem by using variables sum[0] for Peter and sum[1] for Colin.
            // Ideally, we want to add up dice variables that range from 1-4 and 1-6.
            // However, integers in Infer.NET must start from 0.
            // One approach is to use dice that range from 0-4 and 0-6, with zero probability on the value 0.
            // Another approach is to use dice that range 0-3 and 0-5, and add an offset at the end.
            // We use the second approach here.

            int[] numSides = new int[2] {
                4, 6
            };
            Vector[] probs = new Vector[2];
            for (int i = 0; i < 2; i++)
            {
                probs[i] = Vector.Constant(numSides[i], 1.0 / numSides[i]);
            }
            int[]            numDice = new int[] { 9, 6 };
            Variable <int>[] sum     = new Variable <int> [2];
            for (int i = 0; i < 2; i++)
            {
                sum[i] = Variable.Discrete(probs[i]).Named("die" + i + "0");
                for (int j = 1; j < numDice[i]; j++)
                {
                    sum[i] += Variable.Discrete(probs[i]).Named("die" + i + j);
                }
            }
            for (int i = 0; i < 2; i++)
            {
                // add an offset due to zero-based integers
                sum[i] += numDice[i];
            }
            sum[0].Name = "sum0";
            sum[1].Name = "sum1";
            Variable <bool> win = sum[0] > sum[1];

            win.Name = "win";
            InferenceEngine engine = new InferenceEngine();

            engine.NumberOfIterations = 1; // Only one iteration needed
            Bernoulli winMarginal = engine.Infer <Bernoulli>(win);

            Console.WriteLine("{0:0.0000000}", winMarginal.GetProbTrue());
            Bernoulli winExpected = new Bernoulli(0.5731441);

            Assert.True(winExpected.MaxDiff(winMarginal) < 1e-7);
        }
        /// <summary>
        /// Gets the distribution over class labels in the standard data format.
        /// </summary>
        /// <param name="nativeLabelDistribution">The distribution over class labels in the native data format.</param>
        /// <returns>The class label distribution in standard data format.</returns>
        protected override IDictionary <TLabel, double> GetStandardLabelDistribution(Bernoulli nativeLabelDistribution)
        {
            var labelDistribution = new Dictionary <TLabel, double>
            {
                { this.GetStandardLabel(true), nativeLabelDistribution.GetProbTrue() },
                { this.GetStandardLabel(false), nativeLabelDistribution.GetProbFalse() }
            };

            return(labelDistribution);
        }
Beispiel #13
0
        /// <summary>EP message to <c>probTrue</c>.</summary>
        /// <param name="sample">Incoming message from <c>sample</c>. Must be a proper distribution. If uniform, the result will be uniform.</param>
        /// <param name="probTrue">Incoming message from <c>probTrue</c>.</param>
        /// <returns>The outgoing EP message to the <c>probTrue</c> argument.</returns>
        /// <remarks>
        ///   <para>The outgoing message is a distribution matching the moments of <c>probTrue</c> as the random arguments are varied. The formula is <c>proj[p(probTrue) sum_(sample) p(sample) factor(sample,probTrue)]/p(probTrue)</c>.</para>
        /// </remarks>
        /// <exception cref="ImproperMessageException">
        ///   <paramref name="sample" /> is not a proper distribution.</exception>
        public static Beta ProbTrueAverageConditional([SkipIfUniform] Bernoulli sample, Beta probTrue)
        {
            // this code is similar to DiscreteFromDirichletOp.PAverageConditional()
            if (probTrue.IsPointMass)
            {
                return(Beta.Uniform());
            }
            if (sample.IsPointMass)
            {
                // shortcut
                return(ProbTrueConditional(sample.Point));
            }
            if (!probTrue.IsProper())
            {
                throw new ImproperMessageException(probTrue);
            }
            // q(x) is the distribution stored in this.X.
            // q(p) is the distribution stored in this.P.
            // f(x,p) is the factor.
            // Z = sum_x q(x) int_p f(x,p)*q(p) = q(false)*E[1-p] + q(true)*E[p]
            // Ef[p] = 1/Z sum_x q(x) int_p p*f(x,p)*q(p) = 1/Z (q(false)*E[p(1-p)] + q(true)*E[p^2])
            // Ef[p^2] = 1/Z sum_x q(x) int_p p^2*f(x,p)*q(p) = 1/Z (q(false)*E[p^2(1-p)] + q(true)*E[p^3])
            // var_f(p) = Ef[p^2] - Ef[p]^2
            double mo  = probTrue.GetMean();
            double m2o = probTrue.GetMeanSquare();
            double pT  = sample.GetProbTrue();
            double pF  = sample.GetProbFalse();
            double Z   = pF * (1 - mo) + pT * mo;
            double m   = pF * (mo - m2o) + pT * m2o;

            m = m / Z;
            if (!Beta.AllowImproperSum)
            {
                if (pT < 0.5)
                {
                    double inc = probTrue.TotalCount * (mo / m - 1);
                    return(new Beta(1, 1 + inc));
                }
                else
                {
                    double inc = probTrue.TotalCount * ((1 - mo) / (1 - m) - 1);
                    return(new Beta(1 + inc, 1));
                }
            }
            else
            {
                double m3o = probTrue.GetMeanCube();
                double m2  = pF * (m2o - m3o) + pT * m3o;
                m2 = m2 / Z;
                Beta result = Beta.FromMeanAndVariance(m, m2 - m * m);
                result.SetToRatio(result, probTrue);
                return(result);
            }
        }
Beispiel #14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="sample">Incoming message from 'sample'.</param>
        /// <param name="index">Incoming message from 'index'.</param>
        /// <param name="ProbTrue">Constant value for 'probTrue'.</param>
        /// <returns></returns>
        /// <remarks><para>
        ///
        /// </para></remarks>
        public static double AverageValueLn(Bernoulli sample, Discrete index, double[] ProbTrue)
        {
            double p = 0;

            for (int i = 0; i < ProbTrue.Length; i++)
            {
                p += ProbTrue[i] * index[i];
            }
            double b = sample.GetProbTrue();

            return(Math.Log(b * p + (1 - b) * (1 - p)));
        }
        /// <summary>VMP message to <c>sample</c>.</summary>
        /// <param name="choice">Incoming message from <c>choice</c>.</param>
        /// <param name="probTrue0">Constant value for <c>probTrue0</c>.</param>
        /// <param name="probTrue1">Constant value for <c>probTrue1</c>.</param>
        /// <returns>The outgoing VMP message to the <c>sample</c> argument.</returns>
        /// <remarks>
        ///   <para>The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except <c>sample</c>. The formula is <c>exp(sum_(choice) p(choice) log(factor(sample,choice,probTrue0,probTrue1)))</c>.</para>
        /// </remarks>
        public static Bernoulli SampleAverageLogarithm(Bernoulli choice, double probTrue0, double probTrue1)
        {
            Bernoulli result = new Bernoulli();

            if (choice.IsPointMass)
            {
                return(SampleConditional(choice.Point, probTrue0, probTrue1));
            }
            // log(p(X=true)/p(X=false)) = sum_k p(Y=k) log(ProbTrue[k]/(1-ProbTrue[k]))
            result.LogOdds = choice.GetProbFalse() * MMath.Logit(probTrue0) + choice.GetProbTrue() * MMath.Logit(probTrue1);
            return(result);
        }
Beispiel #16
0
        double ComputePairProbability(double scoreA, double scoreB)
        {
            XPrior = new Gaussian(scoreA, noise);
            YPrior = new Gaussian(scoreB, noise);

            XParam.ObservedValue = XPrior;
            YParam.ObservedValue = YPrior;

            Bernoulli probXBeatsY = engine.Infer <Bernoulli>(XBeatsY);

            return(probXBeatsY.GetProbTrue());
        }
        /// <summary>
        /// EP message to 'b'
        /// </summary>
        /// <param name="isGreaterThan">Incoming message from 'isGreaterThan'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
        /// <param name="a">Constant value for 'a'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'b' as the random arguments are varied.
        /// The formula is <c>proj[p(b) sum_(isGreaterThan) p(isGreaterThan) factor(isGreaterThan,a,b)]/p(b)</c>.
        /// </para></remarks>
        /// <exception cref="ImproperMessageException"><paramref name="isGreaterThan"/> is not a proper distribution</exception>
        static public Discrete BAverageConditional([SkipIfUniform] Bernoulli isGreaterThan, int a, Discrete result)
        {
            Vector bProbs    = result.GetWorkspace();
            double probTrue  = isGreaterThan.GetProbTrue();
            double probFalse = 1 - probTrue;

            for (int j = 0; j < bProbs.Count; j++)
            {
                bProbs[j] = (a > j) ? probTrue : probFalse;
            }
            result.SetProbs(bProbs);
            return(result);
        }
        /// <summary>
        /// EP message to 'a'
        /// </summary>
        /// <param name="isGreaterThan">Incoming message from 'isGreaterThan'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
        /// <param name="b">Constant value for 'b'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'a' as the random arguments are varied.
        /// The formula is <c>proj[p(a) sum_(isGreaterThan) p(isGreaterThan) factor(isGreaterThan,a,b)]/p(a)</c>.
        /// </para></remarks>
        /// <exception cref="ImproperMessageException"><paramref name="isGreaterThan"/> is not a proper distribution</exception>
        static public Discrete AAverageConditional([SkipIfUniform] Bernoulli isGreaterThan, int b, Discrete result)
        {
            double probTrue  = isGreaterThan.GetProbTrue();
            double probFalse = 1 - probTrue;
            Vector aProbs    = result.GetWorkspace();

            for (int i = 0; i < aProbs.Count; i++)
            {
                aProbs[i] = (i > b) ? probTrue : probFalse;
            }
            result.SetProbs(aProbs);
            return(result);
        }
Beispiel #19
0
        //-- VMP -------------------------------------------------------------------------------------------

        /// <summary>Evidence message for VMP.</summary>
        /// <param name="sample">Incoming message from <c>sample</c>.</param>
        /// <param name="probTrue">Incoming message from <c>probTrue</c>. Must be a proper distribution. If uniform, the result will be uniform.</param>
        /// <returns>Average of the factor's log-value across the given argument distributions.</returns>
        /// <remarks>
        ///   <para>The formula for the result is <c>sum_(sample,probTrue) p(sample,probTrue) log(factor(sample,probTrue))</c>. Adding up these values across all factors and variables gives the log-evidence estimate for VMP.</para>
        /// </remarks>
        /// <exception cref="ImproperMessageException">
        ///   <paramref name="probTrue" /> is not a proper distribution.</exception>
        public static double AverageLogFactor(Bernoulli sample, [Proper] Beta probTrue)
        {
            if (sample.IsPointMass)
            {
                return(AverageLogFactor(sample.Point, probTrue));
            }
            double eLogP, eLog1MinusP;

            probTrue.GetMeanLogs(out eLogP, out eLog1MinusP);
            double p = sample.GetProbTrue();

            return(p * eLogP + (1 - p) * eLog1MinusP);
        }
Beispiel #20
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DiscreteAreEqualOp"]/message_doc[@name="AAverageConditional(Bernoulli, int, Discrete)"]/*'/>
        public static Discrete AAverageConditional([SkipIfUniform] Bernoulli areEqual, int B, Discrete result)
        {
            if (areEqual.IsPointMass)
            {
                return(AAverageConditional(areEqual.Point, B, result));
            }
            Vector probs = result.GetWorkspace();
            double p     = areEqual.GetProbTrue();

            probs.SetAllElementsTo(1 - p);
            probs[B] = p;
            result.SetProbs(probs);
            return(result);
        }
Beispiel #21
0
        /// <summary>
        /// Evidence message for VMP.
        /// </summary>
        /// <param name="sample">Incoming message from sample</param>
        /// <param name="logOdds">Incoming message from logOdds</param>
        /// <returns><c>sum_x marginal(x)*log(factor(x))</c></returns>
        /// <remarks><para>
        /// The formula for the result is <c>int log(f(x)) q(x) dx</c>
        /// where <c>x = (sample,logOdds)</c>.
        /// </para></remarks>
        public static double AverageLogFactor(Bernoulli sample, [Proper, SkipIfUniform] Gaussian logOdds)
        {
            if (logOdds.IsUniform())
            {
                return(0.0);
            }
            double m, v;

            logOdds.GetMeanAndVariance(out m, out v);
            double t = Math.Sqrt(m * m + v);
            double s = 2 * sample.GetProbTrue() - 1;              // probTrue - probFalse

            return(MMath.LogisticLn(t) + (s * m - t) / 2);
        }
Beispiel #22
0
        /// <summary>
        /// VMP message to LogOdds
        /// </summary>
        /// <param name="sample">Incoming message from sample</param>
        /// <param name="logOdds">Incoming message from logOdds</param>
        /// <returns><c>sum_x marginal(x)*log(factor(x))</c></returns>
        /// <remarks><para>
        /// The outgoing message is the exponential of the integral of the log-factor times incoming messages, over all arguments except 'logOdds'.
        /// The formula is <c>int log(f(logOdds,x)) q(x) dx</c> where <c>x = (sample)</c>.
        /// </para></remarks>
        public static Gaussian LogOddsAverageLogarithm(Bernoulli sample, [Proper, SkipIfUniform] Gaussian logOdds)
        {
            if (logOdds.IsUniform())
            {
                return(logOdds);
            }
            double m, v;

            logOdds.GetMeanAndVariance(out m, out v);
            double t      = Math.Sqrt(m * m + v);
            double lambda = (t == 0) ? 0.25 : Math.Tanh(t / 2) / (2 * t);

            return(Gaussian.FromNatural(sample.GetProbTrue() - 0.5, lambda));
        }
        /// <summary>EP message to <c>choice</c>.</summary>
        /// <param name="sample">Incoming message from <c>sample</c>. Must be a proper distribution. If uniform, the result will be uniform.</param>
        /// <param name="probTrue0">Constant value for <c>probTrue0</c>.</param>
        /// <param name="probTrue1">Constant value for <c>probTrue1</c>.</param>
        /// <returns>The outgoing EP message to the <c>choice</c> argument.</returns>
        /// <remarks>
        ///   <para>The outgoing message is a distribution matching the moments of <c>choice</c> as the random arguments are varied. The formula is <c>proj[p(choice) sum_(sample) p(sample) factor(sample,choice,probTrue0,probTrue1)]/p(choice)</c>.</para>
        /// </remarks>
        /// <exception cref="ImproperMessageException">
        ///   <paramref name="sample" /> is not a proper distribution.</exception>
        public static Bernoulli ChoiceAverageConditional([SkipIfUniform] Bernoulli sample, double probTrue0, double probTrue1)
        {
            Bernoulli result = new Bernoulli();

            if (sample.IsPointMass)
            {
                return(ChoiceConditional(sample.Point, probTrue0, probTrue1));
            }
#if FAST
            double p1  = sample.GetProbFalse() * (1 - probTrue1) + sample.GetProbTrue() * probTrue1;
            double p0  = sample.GetProbFalse() * (1 - probTrue0) + sample.GetProbTrue() * probTrue0;
            double sum = p0 + p1;
            if (sum == 0.0)
            {
                throw new AllZeroException();
            }
            else
            {
                result.SetProbTrue(p1 / sum);
            }
#else
            // This method is more numerically stable but slower.
            // ax = log(FT/TT)
            // bx = log(FF/TF)
            // offset = log(TT/TF)
            if (probTrue0 == 0 || probTrue1 == 0)
            {
                throw new ArgumentException("probTrue is zero");
            }
            double ax     = -MMath.Logit(probTrue1);
            double bx     = -MMath.Logit(probTrue0);
            double offset = Math.Log(probTrue1 / probTrue0);
            result.LogOdds = MMath.DiffLogSumExp(sample.LogOdds, ax, bx) + offset;
#endif
            return(result);
        }
Beispiel #24
0
        /// <summary>
        /// EP message to 'index'.
        /// </summary>
        /// <param name="sample">Incoming message from 'sample'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
        /// <param name="ProbTrue">Constant value for 'probTrue'.</param>
        /// <param name="result">Modified to contain the outgoing message.</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is the integral of the factor times incoming messages, over all arguments except 'index'.
        /// The formula is <c>int f(index,x) q(x) dx</c> where <c>x = (sample,probTrue)</c>.
        /// </para></remarks>
        /// <exception cref="ImproperMessageException"><paramref name="sample"/> is not a proper distribution</exception>
        public static Discrete IndexAverageConditional([SkipIfUniform] Bernoulli sample, double[] ProbTrue, Discrete result)
        {
            if (result == default(Discrete))
            {
                result = Discrete.Uniform(ProbTrue.Length);
            }
            // p(Y) = ProbTrue[Y]*p(X=true) + (1-ProbTrue[Y])*p(X=false)
            Vector probs = result.GetWorkspace();
            double p     = sample.GetProbTrue();

            probs.SetTo(ProbTrue);
            probs.SetToProduct(probs, 2.0 * p - 1.0);
            probs.SetToSum(probs, 1.0 - p);
            result.SetProbs(probs);
            return(result);
        }
Beispiel #25
0
        public static Beta ProbTrueAverageConditional([SkipIfUniform] Bernoulli sample, double probTrue)
        {
            // f(x,p) = q(T) p + q(F) (1-p)
            // dlogf/dp = (q(T) - q(F))/f(x,p)
            // ddlogf/dp^2 = -(q(T) - q(F))^2/f(x,p)^2
            double qT        = sample.GetProbTrue();
            double qF        = sample.GetProbFalse();
            double pTT       = qT * probTrue;
            double probFalse = 1 - probTrue;
            double pFF       = qF * probFalse;
            double Z         = pTT + pFF;
            double dlogp     = (qT - qF) / Z;
            double ddlogp    = -dlogp * dlogp;

            return(Beta.FromDerivatives(probTrue, dlogp, ddlogp, !Beta.AllowImproperSum));
        }
Beispiel #26
0
        /// <summary>
        /// VMP message to 'index'.
        /// </summary>
        /// <param name="sample">Incoming message from 'sample'.</param>
        /// <param name="ProbTrue">Constant value for 'probTrue'.</param>
        /// <param name="result">Modified to contain the outgoing message.</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is the exponential of the integral of the log-factor times incoming messages, over all arguments except 'index'.
        /// The formula is <c>int log(f(index,x)) q(x) dx</c> where <c>x = (sample,probTrue)</c>.
        /// </para></remarks>
        public static Discrete IndexAverageLogarithm(Bernoulli sample, double[] ProbTrue, Discrete result)
        {
            if (result == default(Discrete))
            {
                result = Discrete.Uniform(ProbTrue.Length);
            }
            // E[sum_k I(Y=k) (X*log(ProbTrue[k]) + (1-X)*log(1-ProbTrue[k]))]
            // = sum_k I(Y=k) (p(X=true)*log(ProbTrue[k]) + p(X=false)*log(1-ProbTrue[k]))
            // p(Y=k) =propto ProbTrue[k]^p(X=true) (1-ProbTrue[k])^p(X=false)
            Vector probs = result.GetWorkspace();
            double p     = sample.GetProbTrue();

            probs.SetTo(ProbTrue);
            probs.SetToFunction(probs, x => Math.Pow(x, p) * Math.Pow(1.0 - x, 1.0 - p));
            result.SetProbs(probs);
            return(result);
        }
        /// <summary>VMP message to <c>choice</c>.</summary>
        /// <param name="sample">Incoming message from <c>sample</c>.</param>
        /// <param name="probTrue0">Constant value for <c>probTrue0</c>.</param>
        /// <param name="probTrue1">Constant value for <c>probTrue1</c>.</param>
        /// <returns>The outgoing VMP message to the <c>choice</c> argument.</returns>
        /// <remarks>
        ///   <para>The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except <c>choice</c>. The formula is <c>exp(sum_(sample) p(sample) log(factor(sample,choice,probTrue0,probTrue1)))</c>.</para>
        /// </remarks>
        public static Bernoulli ChoiceAverageLogarithm(Bernoulli sample, double probTrue0, double probTrue1)
        {
            Bernoulli result = new Bernoulli();

            if (sample.IsPointMass)
            {
                return(ChoiceConditional(sample.Point, probTrue0, probTrue1));
            }
            // p(Y=k) =propto ProbTrue[k]^p(X=true) (1-ProbTrue[k])^p(X=false)
            // log(p(Y=true)/p(Y=false)) = p(X=true)*log(ProbTrue[1]/ProbTrue[0]) + p(X=false)*log((1-ProbTrue[1])/(1-ProbTrue[0]))
            //                           = p(X=false)*(log(ProbTrue[0]/(1-ProbTrue[0]) - log(ProbTrue[1]/(1-ProbTrue[1]))) + log(ProbTrue[1]/ProbTrue[0])
            if (probTrue0 == 0 || probTrue1 == 0)
            {
                throw new ArgumentException("probTrue is zero");
            }
            result.LogOdds = sample.GetProbTrue() * Math.Log(probTrue1 / probTrue0) + sample.GetProbFalse() * Math.Log((1 - probTrue1) / (1 - probTrue0));
            return(result);
        }
Beispiel #28
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="IsGreaterThanOp"]/message_doc[@name="AAverageConditional(Bernoulli, Poisson, int)"]/*'/>
        public static Poisson AAverageConditional([SkipIfUniform] Bernoulli isGreaterThan, [Proper] Poisson a, int b)
        {
            if (a.IsPointMass || !a.IsProper())
            {
                return(Poisson.Uniform());
            }
            double aMean = a.GetMean();
            double sum   = 0;
            double asum  = 0;

            if (a.Precision == 1)
            {
                if (b >= 0)
                {
                    sum  = MMath.GammaUpper(b + 1, a.Rate);
                    asum = (sum - Math.Exp(a.GetLogProb(b))) * a.Rate;
                }
            }
            else
            {
                for (int i = 0; i <= b; i++)
                {
                    double p = Math.Exp(a.GetLogProb(i));
                    sum  += p;
                    asum += i * p;
                }
                if (sum > 1)
                {
                    sum = 1; // this can happen due to round-off errors
                }
                if (asum > aMean)
                {
                    asum = aMean;
                }
            }
            double  pT     = isGreaterThan.GetProbTrue();
            double  pF     = 1 - pT;
            double  Z      = pF * sum + pT * (1 - sum);
            double  aZ     = pF * asum + pT * (aMean - asum);
            Poisson result = new Poisson(aZ / Z);

            result.SetToRatio(result, a, false);
            return(result);
        }
Beispiel #29
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="IsGreaterThanOp"]/message_doc[@name="AAverageConditional(Bernoulli, Poisson, int)"]/*'/>
        public static Poisson BAverageConditional([SkipIfUniform] Bernoulli isGreaterThan, int a, [Proper] Poisson b)
        {
            if (b.IsPointMass || !b.IsProper())
            {
                return(Poisson.Uniform());
            }
            double bMean = b.GetMean();
            double sum   = 0;
            double bsum  = 0;

            if (b.Precision == 1)
            {
                if (a > 0)
                {
                    sum  = MMath.GammaUpper(a, b.Rate);
                    bsum = (sum - Math.Exp(b.GetLogProb(a - 1))) * b.Rate;
                }
            }
            else
            {
                for (int i = 0; i < a; i++)
                {
                    double p = Math.Exp(b.GetLogProb(i));
                    sum  += p;
                    bsum += i * p;
                }
                if (sum > 1)
                {
                    sum = 1; // this can happen due to round-off errors
                }
                if (bsum > bMean)
                {
                    bsum = bMean;
                }
            }
            double  pT     = isGreaterThan.GetProbTrue();
            double  pF     = 1 - pT;
            double  Z      = pT * sum + pF * (1 - sum);
            double  bZ     = pT * bsum + pF * (bMean - bsum);
            Poisson result = new Poisson(bZ / Z);

            result.SetToRatio(result, b, false);
            return(result);
        }
Beispiel #30
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DiscreteAreEqualOp"]/message_doc[@name="AAverageConditional(Bernoulli, Discrete, Discrete)"]/*'/>
        public static Discrete AAverageConditional([SkipIfUniform] Bernoulli areEqual, Discrete B, Discrete result)
        {
            if (areEqual.IsPointMass)
            {
                return(AAverageConditional(areEqual.Point, B, result));
            }
            if (result == default(Discrete))
            {
                result = Distributions.Discrete.Uniform(B.Dimension, B.Sparsity);
            }
            double p     = areEqual.GetProbTrue();
            Vector probs = result.GetWorkspace();

            probs = B.GetProbs(probs);
            probs.SetToProduct(probs, 2.0 * p - 1.0);
            probs.SetToSum(probs, 1.0 - p);
            result.SetProbs(probs);
            return(result);
        }
Beispiel #31
0
        public static double AverageLogFactor(Bernoulli sample, Gaussian logOdds)
        {
            // This is the non-conjugate VMP update using the Saul and Jordan (1999) bound.
            double m, v;

            logOdds.GetMeanAndVariance(out m, out v);
            double a = 0.5;

            // TODO: use a buffer to store the value of 'a', so it doesn't need to be re-optimised each time.
            for (int iter = 0; iter < 10; iter++)
            {
                double aOld = a;
                a = MMath.Logistic(m + (1 - 2 * a) * v * 0.5);
                if (Math.Abs(a - aOld) < 1e-8)
                {
                    break;
                }
            }
            return(sample.GetProbTrue() * m - .5 * a * a * v - MMath.Log1PlusExp(m + (1 - 2 * a) * v * 0.5));
        }
Beispiel #32
0
 /// <summary>Evidence message for VMP.</summary>
 /// <param name="sample">Incoming message from <c>sample</c>.</param>
 /// <param name="logOdds">Constant value for <c>logOdds</c>.</param>
 /// <returns>Average of the factor's log-value across the given argument distributions.</returns>
 /// <remarks>
 ///   <para>The formula for the result is <c>sum_(sample) p(sample) log(factor(sample,logOdds))</c>. Adding up these values across all factors and variables gives the log-evidence estimate for VMP.</para>
 /// </remarks>
 public static double AverageLogFactor(Bernoulli sample, double logOdds)
 {
     if (sample.IsPointMass)
     {
         return(AverageLogFactor(sample.Point, logOdds));
     }
     // probTrue*log(sigma(logOdds)) + probFalse*log(sigma(-logOdds))
     // = -log(1+exp(-logOdds)) + probFalse*(-logOdds)
     // = probTrue*logOdds - log(1+exp(logOdds))
     if (logOdds >= 0)
     {
         double probFalse = sample.GetProbFalse();
         return(-probFalse * logOdds - MMath.Log1PlusExp(-logOdds));
     }
     else
     {
         double probTrue = sample.GetProbTrue();
         return(probTrue * logOdds - MMath.Log1PlusExp(logOdds));
     }
 }
 public static double AverageLogFactor(Bernoulli sample, Gaussian logOdds)
 {
     // This is the non-conjugate VMP update using the Saul and Jordan (1999) bound.
     double m, v;
     logOdds.GetMeanAndVariance(out m, out v);
     double a = 0.5;
     // TODO: use a buffer to store the value of 'a', so it doesn't need to be re-optimised each time.
     for (int iter = 0; iter < 10; iter++)
     {
         double aOld = a;
         a = MMath.Logistic(m + (1 - 2 * a) * v * 0.5);
         if (Math.Abs(a - aOld) < 1e-8) break;
     }
     return sample.GetProbTrue() * m - .5 * a * a * v - MMath.Log1PlusExp(m + (1 - 2 * a) * v * 0.5);
 }
        /// <summary>
        /// EP message to 'sample'.
        /// </summary>
        /// <param name="choice">Incoming message from 'choice'.</param>
        /// <param name="probTrue0">Constant value for 'probTrue0'.</param>
        /// <param name="probTrue1">Constant value for 'probTrue1'.</param>
        /// <returns>The outgoing EP message to the 'sample' argument.</returns>
        /// <remarks><para>
        /// The outgoing message is the integral of the factor times incoming messages, over all arguments except 'sample'.
        /// The formula is <c>int f(sample,x) q(x) dx</c> where <c>x = (choice,probTrue0,probTrue1)</c>.
        /// </para></remarks>
        public static Bernoulli SampleAverageConditional(Bernoulli choice, double probTrue0, double probTrue1)
		{
            Bernoulli result = new Bernoulli();
			if(choice.IsPointMass) return SampleConditional(choice.Point,probTrue0,probTrue1);
#if FAST
			result.SetProbTrue(choice.GetProbFalse() * probTrue0 + choice.GetProbTrue() * probTrue1);
#else
			// This method is more numerically stable but slower.
			// let oX = log(p(X)/(1-p(X))
			// let oY = log(p(Y)/(1-p(Y))
			// oX = log( (TT*sigma(oY) + TF*sigma(-oY))/(FT*sigma(oY) + FF*sigma(-oY)) )
			//    = log( (TT*exp(oY) + TF)/(FT*exp(oY) + FF) )
			//    = log( (exp(oY) + TF/TT)/(exp(oY) + FF/FT) ) + log(TT/FT)
			// ay = log(TF/TT)
			// by = log(FF/FT)
			// offset = log(TT/FT)
			if (probTrue0 == 0 || probTrue1 == 0) throw new ArgumentException("probTrue is zero");
			double ay = Math.Log(probTrue0 / probTrue1);
			double by = Math.Log((1 - probTrue0) / (1 - probTrue1));
			double offset = MMath.Logit(probTrue1);
			result.LogOdds = MMath.DiffLogSumExp(choice.LogOdds, ay, by) + offset;
#endif
			return result;
		}
        /// <summary>
        /// VMP message to 'sample'.
        /// </summary>
        /// <param name="choice">Incoming message from 'choice'.</param>
        /// <param name="probTrue0">Constant value for 'probTrue0'.</param>
        /// <param name="probTrue1">Constant value for 'probTrue1'.</param>
        /// <returns>The outgoing VMP message to the 'sample' argument.</returns>
        /// <remarks><para>
        /// The outgoing message is the exponential of the integral of the log-factor times incoming messages, over all arguments except 'sample'.
        /// The formula is <c>int log(f(sample,x)) q(x) dx</c> where <c>x = (choice,probTrue0,probTrue1)</c>.
        /// </para></remarks>
        public static Bernoulli SampleAverageLogarithm(Bernoulli choice, double probTrue0, double probTrue1)
		{
            Bernoulli result = new Bernoulli();
			if(choice.IsPointMass) return SampleConditional(choice.Point,probTrue0,probTrue1);
			// log(p(X=true)/p(X=false)) = sum_k p(Y=k) log(ProbTrue[k]/(1-ProbTrue[k]))
			result.LogOdds = choice.GetProbFalse() * MMath.Logit(probTrue0) + choice.GetProbTrue() * MMath.Logit(probTrue1);
			return result;
		}
		/// <summary>
		/// VMP message to 'a'.
		/// </summary>
		/// <param name="and">Incoming message from 'and'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
		/// <param name="B">Incoming message from 'b'.</param>
		/// <returns>The outgoing VMP message to the 'a' argument.</returns>
		/// <remarks><para>
		/// The outgoing message is the exponential of the integral of the log-factor times incoming messages, over all arguments except 'a'.
		/// The formula is <c>int log(f(a,x)) q(x) dx</c> where <c>x = (and,b)</c>.
		/// </para></remarks>
		/// <exception cref="ImproperMessageException"><paramref name="and"/> is not a proper distribution</exception>
		public static Bernoulli AAverageLogarithm([SkipIfUniform] Bernoulli and, Bernoulli B)
		{
			// when 'and' is marginalized, the factor is proportional to exp(A*B*and.LogOdds)
			return Bernoulli.FromLogOdds(and.LogOdds * B.GetProbTrue());
		}
Beispiel #37
0
		/// <summary>
		/// Evidence message for EP
		/// </summary>
		/// <param name="isBetween">Incoming message from 'isBetween'.</param>
		/// <param name="X">Incoming message from 'x'.</param>
		/// <param name="lowerBound">Incoming message from 'lowerBound'.</param>
		/// <param name="upperBound">Incoming message from 'upperBound'.</param>
		/// <returns>Logarithm of the factor's average value across the given argument distributions</returns>
		/// <remarks><para>
		/// The formula for the result is <c>log(sum_(isBetween,x,lowerBound,upperBound) p(isBetween,x,lowerBound,upperBound) factor(isBetween,x,lowerBound,upperBound))</c>.
		/// </para></remarks>
		public static double LogAverageFactor(Bernoulli isBetween, Gaussian X, Gaussian lowerBound, Gaussian upperBound)
		{
			if (isBetween.LogOdds == 0.0) return -MMath.Ln2;
			else
			{
#if true
				double logitProbBetween = MMath.LogitFromLog(LogProbBetween(X, lowerBound, upperBound));
				return Bernoulli.LogProbEqual(isBetween.LogOdds, logitProbBetween);
#else
			double d_p = isBetween.GetProbTrue() - isBetween.GetProbFalse();
			return Math.Log(d_p * Math.Exp(LogProbBetween()) + isBetween.GetProbFalse());
#endif
			}
		}
		/// <summary>
		/// VMP message to LogOdds
		/// </summary>
		/// <param name="sample">Incoming message from sample</param>
		/// <param name="logOdds">Incoming message from logOdds</param>
		/// <returns><c>sum_x marginal(x)*log(factor(x))</c></returns>
		/// <remarks><para>
		/// The outgoing message is the exponential of the integral of the log-factor times incoming messages, over all arguments except 'logOdds'.
		/// The formula is <c>int log(f(logOdds,x)) q(x) dx</c> where <c>x = (sample)</c>.
		/// </para></remarks>
		public static Gaussian LogOddsAverageLogarithm(Bernoulli sample, [Proper, SkipIfUniform] Gaussian logOdds)
		{
			if (logOdds.IsUniform()) return logOdds;
			double m, v;
			logOdds.GetMeanAndVariance(out m, out v);
			double t = Math.Sqrt(m * m + v);
			double lambda = (t == 0) ? 0.25 : Math.Tanh(t / 2) / (2 * t);
			return Gaussian.FromNatural(sample.GetProbTrue() - 0.5, lambda);
		}
Beispiel #39
0
		//-- VMP -------------------------------------------------------------------------------------------

		/// <summary>
		/// Evidence message for VMP
		/// </summary>
		/// <param name="sample">Incoming message from 'sample'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
		/// <param name="probTrue">Incoming message from 'probTrue'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
		/// <returns>Average of the factor's log-value across the given argument distributions</returns>
		/// <remarks><para>
		/// The formula for the result is <c>sum_(sample,probTrue) p(sample,probTrue) log(factor(sample,probTrue))</c>.
		/// Adding up these values across all factors and variables gives the log-evidence estimate for VMP.
		/// </para></remarks>
		/// <exception cref="ImproperMessageException"><paramref name="sample"/> is not a proper distribution</exception>
		/// <exception cref="ImproperMessageException"><paramref name="probTrue"/> is not a proper distribution</exception>
		public static double AverageLogFactor(Bernoulli sample, [Proper] Beta probTrue)
		{
			if (sample.IsPointMass) return AverageLogFactor(sample.Point, probTrue);
			double eLogP, eLog1MinusP;
			probTrue.GetMeanLogs(out eLogP, out eLog1MinusP);
			double p = sample.GetProbTrue();
			return p * eLogP + (1 - p) * eLog1MinusP;
		}
        private static Gaussian ShapeAverageConditional(
            Vector point, Bernoulli label, Gaussian shapeX, Gaussian shapeY, PositiveDefiniteMatrix shapeOrientation, bool resultForXCoord)
        {
            if (shapeX.IsPointMass && shapeY.IsPointMass)
            {
                double labelProbTrue = label.GetProbTrue();
                double labelProbFalse = 1.0 - labelProbTrue;
                double probDiff = labelProbTrue - labelProbFalse;

                Vector shapeLocation = Vector.FromArray(shapeX.Point, shapeY.Point);
                Vector diff = point - shapeLocation;
                Vector orientationTimesDiff = shapeOrientation * diff;
                Matrix orientationTimesDiffOuter = orientationTimesDiff.Outer(orientationTimesDiff);

                double factorValue = Math.Exp(-0.5 * shapeOrientation.QuadraticForm(diff));
                double funcValue = factorValue * probDiff + labelProbFalse;

                Vector dFunc = probDiff * factorValue * orientationTimesDiff;
                Vector dLogFunc = 1.0 / funcValue * dFunc;
                Matrix ddLogFunc =
                    ((orientationTimesDiffOuter + shapeOrientation) * factorValue * funcValue - orientationTimesDiffOuter * probDiff * factorValue * factorValue)
                    * (probDiff / (funcValue * funcValue));

                double x = resultForXCoord ? shapeX.Point : shapeY.Point;
                double d = resultForXCoord ? dLogFunc[0] : dLogFunc[1];
                double dd = resultForXCoord ? ddLogFunc[0, 0] : ddLogFunc[1, 1];
                return Gaussian.FromDerivatives(x, d, dd, forceProper: true);
            }
            else if (!shapeX.IsPointMass && !shapeY.IsPointMass)
            {
                VectorGaussian shapeLocationTimesFactor = ShapeLocationTimesFactor(point, shapeX, shapeY, shapeOrientation);
                double labelProbFalse = label.GetProbFalse();
                double shapeLocationWeight = labelProbFalse;
                double shapeLocationTimesFactorWeight =
                    Math.Exp(shapeLocationTimesFactor.GetLogNormalizer() - shapeX.GetLogNormalizer() - shapeY.GetLogNormalizer() - 0.5 * shapeOrientation.QuadraticForm(point)) *
                    (1 - 2 * labelProbFalse);

                var projectionOfSum = new Gaussian();
                projectionOfSum.SetToSum(
                    shapeLocationWeight,
                    resultForXCoord ? shapeX : shapeY,
                    shapeLocationTimesFactorWeight,
                    shapeLocationTimesFactor.GetMarginal(resultForXCoord ? 0 : 1));
                Gaussian result = new Gaussian();
                result.SetToRatio(projectionOfSum, resultForXCoord ? shapeX : shapeY);

                return result;
            }
            else
            {
                throw new NotSupportedException();
            }
        }
		/// <summary>
		/// 
		/// </summary>
		/// <param name="sample">Incoming message from 'sample'.</param>
		/// <param name="index">Incoming message from 'index'.</param>
		/// <param name="ProbTrue">Constant value for 'probTrue'.</param>
		/// <returns></returns>
		/// <remarks><para>
		/// 
		/// </para></remarks>
		public static double AverageValueLn(Bernoulli sample, Discrete index, double[] ProbTrue)
		{
			double p = 0;
			for (int i = 0; i < ProbTrue.Length; i++)
			{
				p += ProbTrue[i] * index[i];
			}
			double b = sample.GetProbTrue();
			return Math.Log(b * p + (1 - b) * (1 - p));
		}
		/// <summary>
		/// VMP message to 'index'.
		/// </summary>
		/// <param name="sample">Incoming message from 'sample'.</param>
		/// <param name="ProbTrue">Constant value for 'probTrue'.</param>
		/// <param name="result">Modified to contain the outgoing message.</param>
		/// <returns><paramref name="result"/></returns>
		/// <remarks><para>
		/// The outgoing message is the exponential of the integral of the log-factor times incoming messages, over all arguments except 'index'.
		/// The formula is <c>int log(f(index,x)) q(x) dx</c> where <c>x = (sample,probTrue)</c>.
		/// </para></remarks>
		public static Discrete IndexAverageLogarithm(Bernoulli sample, double[] ProbTrue, Discrete result)
		{
			if (result == default(Discrete)) result = Discrete.Uniform(ProbTrue.Length);
			// E[sum_k I(Y=k) (X*log(ProbTrue[k]) + (1-X)*log(1-ProbTrue[k]))]
			// = sum_k I(Y=k) (p(X=true)*log(ProbTrue[k]) + p(X=false)*log(1-ProbTrue[k]))
			// p(Y=k) =propto ProbTrue[k]^p(X=true) (1-ProbTrue[k])^p(X=false)
			Vector probs = result.GetWorkspace();
			double p = sample.GetProbTrue();
			probs.SetTo(ProbTrue);
			probs.SetToFunction(probs, x => Math.Pow(x, p) * Math.Pow(1.0 - x, 1.0 - p));
			result.SetProbs(probs);
			return result;
		}
		/// <summary>
		/// Evidence message for VMP.
		/// </summary>
		/// <param name="sample">Incoming message from sample</param>
		/// <param name="logOdds">Fixed value for logOdds</param>
		/// <returns><c>sum_x marginal(x)*log(factor(x))</c></returns>
		/// <remarks><para>
		/// The formula for the result is <c>int log(f(x)) q(x) dx</c>
		/// where <c>x = (sample,logOdds)</c>.
		/// </para></remarks>
		public static double AverageLogFactor(Bernoulli sample, double logOdds)
		{
			if (sample.IsPointMass) return AverageLogFactor(sample.Point, logOdds);
			// probTrue*log(sigma(logOdds)) + probFalse*log(sigma(-logOdds))
			// = -log(1+exp(-logOdds)) + probFalse*(-logOdds)
			// = probTrue*logOdds - log(1+exp(logOdds))
			if (logOdds >= 0) {
				double probFalse = sample.GetProbFalse();
				return -probFalse * logOdds - MMath.Log1PlusExp(-logOdds);
			} else {
				double probTrue = sample.GetProbTrue();
				return probTrue * logOdds - MMath.Log1PlusExp(logOdds);
			}
		}
        public static Wishart ShapeOrientationAverageConditional(
            Vector point, Bernoulli label, Gaussian shapeX, Gaussian shapeY, Wishart shapeOrientation, Wishart result)
        {
            if (shapeOrientation.IsPointMass && shapeX.IsPointMass && shapeY.IsPointMass)
            {
                double labelProbTrue = label.GetProbTrue();
                double labelProbFalse = 1.0 - labelProbTrue;
                double probDiff = labelProbTrue - labelProbFalse;

                Vector shapeLocation = Vector.FromArray(shapeX.Point, shapeY.Point);
                Vector diff = shapeLocation - point;
                Matrix diffOuter = diff.Outer(diff);
                Matrix orientationTimesDiffOuter = shapeOrientation.Point * diffOuter;
                double trace = orientationTimesDiffOuter.Trace();

                double factorValue = Math.Exp(-0.5 * shapeOrientation.Point.QuadraticForm(diff));
                double funcValue = factorValue * probDiff + labelProbFalse;

                PositiveDefiniteMatrix dLogFunc = new PositiveDefiniteMatrix(diffOuter * (-0.5 * probDiff * factorValue / funcValue));
                double xxddLogFunc =
                    -0.5 * probDiff * (-0.5 * labelProbFalse * factorValue * trace * trace / (funcValue * funcValue) + factorValue * trace / funcValue);

                LowerTriangularMatrix cholesky = new LowerTriangularMatrix(2, 2);
                cholesky.SetToCholesky(shapeOrientation.Point);
                PositiveDefiniteMatrix inverse = shapeOrientation.Point.Inverse();
                result.SetDerivatives(cholesky, inverse, dLogFunc, xxddLogFunc, forceProper: true);
                return result;
            }
            else
            {
                throw new NotSupportedException();
            }
        }
		/// <summary>
		/// Evidence message for VMP.
		/// </summary>
		/// <param name="sample">Incoming message from 'sample'.</param>
		/// <param name="logOdds">Incoming message from 'logOdds'.</param>
		/// <returns><c>sum_x marginal(x)*log(factor(x))</c></returns>
		/// <remarks><para>
		/// The formula for the result is <c>int log(f(x)) q(x) dx</c>
		/// </para></remarks>
		public static double AverageLogFactor(Bernoulli sample, [Proper, SkipIfUniform] Gaussian logOdds)
		{
			// f(sample,logOdds) = exp(sample*logOdds)/(1 + exp(logOdds))
			// log f(sample,logOdds) = sample*logOdds - log(1 + exp(logOdds))
			double m, v;
			logOdds.GetMeanAndVariance(out m, out v);
			return sample.GetProbTrue() * m - MMath.Log1PlusExpGaussian(m, v);
		}
Beispiel #46
0
		/// <summary>
		/// VMP message to 'probTrue'
		/// </summary>
		/// <param name="sample">Incoming message from 'sample'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
		/// <returns>The outgoing VMP message to the 'probTrue' argument</returns>
		/// <remarks><para>
		/// The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except 'probTrue'.
		/// The formula is <c>exp(sum_(sample) p(sample) log(factor(sample,probTrue)))</c>.
		/// </para></remarks>
		/// <exception cref="ImproperMessageException"><paramref name="sample"/> is not a proper distribution</exception>
		public static Beta ProbTrueAverageLogarithm(Bernoulli sample)
		{
			// E[x*log(p) + (1-x)*log(1-p)] = E[x]*log(p) + (1-E[x])*log(1-p)
			double ex = sample.GetProbTrue();
			return new Beta(1 + ex, 2 - ex);
		}
        /// <summary>
        /// VMP message to 'choice'.
        /// </summary>
        /// <param name="sample">Incoming message from 'sample'.</param>
        /// <param name="probTrue0">Constant value for 'probTrue0'.</param>
        /// <param name="probTrue1">Constant value for 'probTrue1'.</param>
        /// <returns>The outgoing VMP message to the 'choice' argument.</returns>
        /// <remarks><para>
        /// The outgoing message is the exponential of the integral of the log-factor times incoming messages, over all arguments except 'choice'.
        /// The formula is <c>int log(f(choice,x)) q(x) dx</c> where <c>x = (sample,probTrue0,probTrue1)</c>.
        /// </para></remarks>
		public static Bernoulli ChoiceAverageLogarithm(Bernoulli sample, double probTrue0, double probTrue1)
		{
            Bernoulli result = new Bernoulli();
			if(sample.IsPointMass) return ChoiceConditional(sample.Point,probTrue0,probTrue1);
			// p(Y=k) =propto ProbTrue[k]^p(X=true) (1-ProbTrue[k])^p(X=false)
			// log(p(Y=true)/p(Y=false)) = p(X=true)*log(ProbTrue[1]/ProbTrue[0]) + p(X=false)*log((1-ProbTrue[1])/(1-ProbTrue[0]))
			//                           = p(X=false)*(log(ProbTrue[0]/(1-ProbTrue[0]) - log(ProbTrue[1]/(1-ProbTrue[1]))) + log(ProbTrue[1]/ProbTrue[0])
			if (probTrue0 == 0 || probTrue1 == 0) throw new ArgumentException("probTrue is zero");
			result.LogOdds = sample.GetProbTrue() * Math.Log(probTrue1 / probTrue0) + sample.GetProbFalse() * Math.Log((1 - probTrue1) / (1 - probTrue0));
			return result;
		}