/// <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); }
/// <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); }
/// <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; }
/// <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)); }
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); }
/// <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); } }
/// <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); }
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); }
//-- 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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
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)); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
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>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()); }
/// <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); }
//-- 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); }
/// <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; }