/// <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> /// 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>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); }
/// <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); }
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)); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="StringsAreEqualOp"]/message_doc[@name="Str1AverageConditional(StringDistribution, Bernoulli, StringDistribution)"]/*'/> public static StringDistribution Str1AverageConditional( StringDistribution str2, [SkipIfUniform] Bernoulli areEqual, StringDistribution result) { StringDistribution uniform = StringDistribution.Any(); double probNotEqual = areEqual.GetProbFalse(); if (probNotEqual > 0.5) { throw new NotImplementedException("Non-equality case is not yet supported."); } double logWeight1 = Math.Log(1 - (2 * probNotEqual)); double logWeight2 = Math.Log(probNotEqual) + uniform.GetLogNormalizer(); result.SetToSumLog(logWeight1, str2, logWeight2, uniform); return(result); }
/// <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)); } }
/// <summary> /// Evidence message for EP. /// </summary> /// <param name="cases">Incoming message from 'cases'.</param> /// <param name="b">Incoming message from 'b'.</param> public static double LogEvidenceRatio(IList <Bernoulli> cases, Bernoulli b) { // result = log (p(data|b=true) p(b=true) + p(data|b=false) p(b=false)) // log (p(data|b=true) p(b=true) + p(data|b=false) (1-p(b=true)) // log ((p(data|b=true) - p(data|b=false)) p(b=true) + p(data|b=false)) // log ((p(data|b=true)/p(data|b=false) - 1) p(b=true) + 1) + log p(data|b=false) // where cases[0].LogOdds = log p(data|b=true) // cases[1].LogOdds = log p(data|b=false) if (b.IsPointMass) { return(b.Point ? cases[0].LogOdds : cases[1].LogOdds); } //else return MMath.LogSumExp(cases[0].LogOdds + b.GetLogProbTrue(), cases[1].LogOdds + b.GetLogProbFalse()); else { // the common case is when cases[0].LogOdds == cases[1].LogOdds. we must not introduce rounding error in that case. if (cases[0].LogOdds >= cases[1].LogOdds) { if (Double.IsNegativeInfinity(cases[1].LogOdds)) { return(cases[0].LogOdds + b.GetLogProbTrue()); } else { return(cases[1].LogOdds + MMath.Log1Plus(b.GetProbTrue() * MMath.ExpMinus1(cases[0].LogOdds - cases[1].LogOdds))); } } else { if (Double.IsNegativeInfinity(cases[0].LogOdds)) { return(cases[1].LogOdds + b.GetLogProbFalse()); } else { return(cases[0].LogOdds + MMath.Log1Plus(b.GetProbFalse() * MMath.ExpMinus1(cases[1].LogOdds - cases[0].LogOdds))); } } } }
/// <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; }
/// <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); } }
/// <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); }
public static VectorGaussianWishart ShapeParamsAverageConditional( Vector point, Bernoulli label, [Proper] VectorGaussianWishart shapeParams, VectorGaussianWishart result) { VectorGaussianWishart shapeParamsTimesFactor = DistributionTimesFactor(point, shapeParams); double labelProbFalse = label.GetProbFalse(); double shapeParamsWeight = labelProbFalse; double shapeParamsTimesFactorWeight = Math.Exp(shapeParamsTimesFactor.GetLogNormalizer() - shapeParams.GetLogNormalizer()) * (1 - 2 * labelProbFalse); var projectionOfSum = new VectorGaussianWishart(2); projectionOfSum.SetToSum(shapeParamsWeight, shapeParams, shapeParamsTimesFactorWeight, shapeParamsTimesFactor); Debug.Assert(projectionOfSum.IsProper()); // TODO: remove me result.SetToRatio(projectionOfSum, shapeParams); return result; }
public static double LogAverageFactor(Bernoulli label, Vector point, GaussianGamma shapeParamsX, GaussianGamma shapeParamsY) { GaussianGamma shapeParamsXDistrTimesFactor = DistributionTimesFactor(point[0], shapeParamsX); GaussianGamma shapeParamsYDistrTimesFactor = DistributionTimesFactor(point[1], shapeParamsY); double labelProbFalse = label.GetProbFalse(); double normalizerProduct = Math.Exp( shapeParamsXDistrTimesFactor.GetLogNormalizer() - shapeParamsX.GetLogNormalizer() + shapeParamsYDistrTimesFactor.GetLogNormalizer() - shapeParamsY.GetLogNormalizer()); double averageFactor = labelProbFalse + (1 - 2 * labelProbFalse) * normalizerProduct; Debug.Assert(averageFactor > 0); return Math.Log(averageFactor); }
private static GaussianGamma ShapeParamsAverageConditional( double coord, double otherCoord, Bernoulli label, GaussianGamma shapeParamsDistr, GaussianGamma otherShapeParamsDistr, GaussianGamma result) { GaussianGamma shapeParamsDistrTimesFactor = DistributionTimesFactor(coord, shapeParamsDistr); GaussianGamma otherShapeParamsDistrTimesFactor = DistributionTimesFactor(otherCoord, otherShapeParamsDistr); double labelProbFalse = label.GetProbFalse(); double weight1 = labelProbFalse; double weight2 = Math.Exp( shapeParamsDistrTimesFactor.GetLogNormalizer() - shapeParamsDistr.GetLogNormalizer() + otherShapeParamsDistrTimesFactor.GetLogNormalizer() - otherShapeParamsDistr.GetLogNormalizer()) * (1 - 2 * labelProbFalse); var projectionOfSum = new GaussianGamma(); projectionOfSum.SetToSum(weight1, shapeParamsDistr, weight2, shapeParamsDistrTimesFactor); result.SetToRatio(projectionOfSum, shapeParamsDistr); return result; }
/// <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 } }
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>VMP message to <c>a</c>.</summary> /// <param name="or">Incoming message from <c>or</c>. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="B">Incoming message from <c>b</c>.</param> /// <returns>The outgoing VMP message to the <c>a</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>a</c>. Because the factor is deterministic, <c>or</c> is integrated out before taking the logarithm. The formula is <c>exp(sum_(b) p(b) log(sum_or p(or) factor(or,a,b)))</c>.</para> /// </remarks> /// <exception cref="ImproperMessageException"> /// <paramref name="or" /> is not a proper distribution.</exception> public static Bernoulli AAverageLogarithm([SkipIfUniform] Bernoulli or, Bernoulli B) { // when 'or' is marginalized, the factor is proportional to exp((A|B)*or.LogOdds) return(Bernoulli.FromLogOdds(or.LogOdds * B.GetProbFalse())); }
/// <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> /// 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 'a' /// </summary> /// <param name="or">Incoming message from 'or'. 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 average log-factor value, where the average is over all arguments except 'a'. /// Because the factor is deterministic, 'or' is integrated out before taking the logarithm. /// The formula is <c>exp(sum_(b) p(b) log(sum_or p(or) factor(or,a,b)))</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="or"/> is not a proper distribution</exception> public static Bernoulli AAverageLogarithm([SkipIfUniform] Bernoulli or, Bernoulli B) { // when 'or' is marginalized, the factor is proportional to exp((A|B)*or.LogOdds) return Bernoulli.FromLogOdds(or.LogOdds * B.GetProbFalse()); }
/// <summary> /// Tests EP and BP gate enter ops for Bernoulli random variable for correctness given message parameters. /// </summary> /// <param name="valueProbTrue">Probability of being true for the variable entering the gate.</param> /// <param name="enterOneProbTrue">Probability of being true for the variable approximation inside the gate when the selector is true.</param> /// <param name="selectorProbTrue">Probability of being true for the selector variable.</param> private void DoBernoulliEnterTest(double valueProbTrue, double enterOneProbTrue, double selectorProbTrue) { var value = new Bernoulli(valueProbTrue); var enterOne = new Bernoulli(enterOneProbTrue); var selector = new Bernoulli(selectorProbTrue); var selectorInverse = new Bernoulli(selector.GetProbFalse()); var discreteSelector = new Discrete(selector.GetProbTrue(), selector.GetProbFalse()); var discreteSelectorInverse = new Discrete(selector.GetProbFalse(), selector.GetProbTrue()); var cases = new[] { Bernoulli.FromLogOdds(selector.GetLogProbTrue()), Bernoulli.FromLogOdds(selector.GetLogProbFalse()) }; // Compute expected message double logShift = enterOne.GetLogNormalizer() + value.GetLogNormalizer() - (value * enterOne).GetLogNormalizer(); double expectedProbTrue = selector.GetProbFalse() + (selector.GetProbTrue() * enterOne.GetProbTrue() * Math.Exp(logShift)); double expectedProbFalse = selector.GetProbFalse() + (selector.GetProbTrue() * enterOne.GetProbFalse() * Math.Exp(logShift)); double expectedNormalizer = expectedProbTrue + expectedProbFalse; expectedProbTrue /= expectedNormalizer; Bernoulli value1, value2; // Enter partial (bernoulli selector, first case) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne }, selector, value, new[] { 0 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne }, selector, value, new[] { 0 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial (bernoulli selector, second case) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne }, selectorInverse, value, new[] { 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne }, selectorInverse, value, new[] { 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial (bernoulli selector, both cases) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, selector, value, new[] { 0, 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, selector, value, new[] { 0, 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial (discrete selector, first case) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne }, discreteSelector, value, new[] { 0 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne }, discreteSelector, value, new[] { 0 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial (discrete selector, second case) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne }, discreteSelectorInverse, value, new[] { 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne }, discreteSelectorInverse, value, new[] { 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial (discrete selector, both cases) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, discreteSelector, value, new[] { 0, 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, discreteSelector, value, new[] { 0, 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter one (discrete selector, first case) value1 = GateEnterOneOp <bool> .ValueAverageConditional( enterOne, discreteSelector, value, 0, new Bernoulli()); value2 = BeliefPropagationGateEnterOneOp.ValueAverageConditional( enterOne, discreteSelector, value, 0, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter one (discrete selector, second case) value1 = GateEnterOneOp <bool> .ValueAverageConditional( enterOne, discreteSelectorInverse, value, 1, new Bernoulli()); value2 = BeliefPropagationGateEnterOneOp.ValueAverageConditional( enterOne, discreteSelectorInverse, value, 1, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial two (first case) value1 = GateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne }, cases[0], cases[1], value, new[] { 0 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne }, cases[0], cases[1], value, new[] { 0 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial two (second case) value1 = GateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne }, cases[1], cases[0], value, new[] { 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne }, cases[1], cases[0], value, new[] { 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial two (both cases) value1 = GateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, cases[0], cases[1], value, new[] { 0, 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, cases[0], cases[1], value, new[] { 0, 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter (discrete selector) value1 = GateEnterOp <bool> .ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, discreteSelector, value, new Bernoulli()); value2 = BeliefPropagationGateEnterOp.ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, discreteSelector, value, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); }
public static double LogAverageFactor( Bernoulli label, Vector point, Gaussian shapeX, Gaussian shapeY, PositiveDefiniteMatrix shapeOrientation) { VectorGaussian shapeLocationTimesFactor = ShapeLocationTimesFactor(point, shapeX, shapeY, shapeOrientation); double labelProbFalse = label.GetProbFalse(); double normalizerProduct = Math.Exp( shapeLocationTimesFactor.GetLogNormalizer() - 0.5 * shapeOrientation.QuadraticForm(point) - shapeX.GetLogNormalizer() - shapeY.GetLogNormalizer()); double averageFactor = labelProbFalse + (1 - 2 * labelProbFalse) * normalizerProduct; Debug.Assert(averageFactor > 0); return Math.Log(averageFactor); }