/// <summary>EP message to <c>func</c>.</summary> /// <param name="y">Incoming message from <c>y</c>. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="func">Incoming message from <c>func</c>. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="x">Constant value for <c>x</c>.</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 <c>func</c> as the random arguments are varied. The formula is <c>proj[p(func) sum_(y) p(y) factor(y,func,x)]/p(func)</c>.</para> /// </remarks> /// <exception cref="ImproperMessageException"> /// <paramref name="y" /> is not a proper distribution.</exception> /// <exception cref="ImproperMessageException"> /// <paramref name="func" /> is not a proper distribution.</exception> public static SparseGP FuncAverageConditional([SkipIfUniform] Gaussian y, [SkipIfUniform] SparseGP func, Vector x, SparseGP result) { if (y.IsUniform() || func.IsUniform()) { result.SetToUniform(); return(result); } result.FixedParameters = func.FixedParameters; result.IncludePrior = false; double vf = func.Variance(x); double my, vy; y.GetMeanAndVariance(out my, out vy); Vector kbx = func.FixedParameters.KernelOf_X_B(x); Vector proj = func.FixedParameters.InvKernelOf_B_B * kbx; double prec = 1.0 / (vy + vf - func.Var_B_B.QuadraticForm(proj)); result.InducingDist.Precision.SetToOuter(proj, proj); result.InducingDist.Precision.Scale(prec); result.InducingDist.MeanTimesPrecision.SetTo(proj); result.InducingDist.MeanTimesPrecision.Scale(prec * my); result.ClearCachedValues(); return(result); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="SparseGPOp"]/message_doc[@name="FuncAverageConditional(Gaussian, SparseGP, Vector, SparseGP)"]/*'/> public static SparseGP FuncAverageConditional([SkipIfUniform] Gaussian y, [SkipIfUniform] SparseGP func, Vector x, SparseGP result) { if (y.IsUniform() || func.IsUniform()) { result.SetToUniform(); return(result); } result.FixedParameters = func.FixedParameters; result.IncludePrior = false; Vector kbx = func.FixedParameters.KernelOf_X_B(x); Vector proj = func.FixedParameters.InvKernelOf_B_B * kbx; // To avoid computing Var_B_B: // vf - func.Var_B_B.QuadraticForm(proj) = kxx - kbx'*beta*kbx - kbx'*inv(K)*Var_B_B*inv(K)*kbx // = kxx - kbx'*(beta + inv(K)*Var_B_B*inv(K))*kbx // = kxx - kbx'*(beta + inv(K)*(K - K*Beta*K)*inv(K))*kbx // = kxx - kbx'*inv(K)*kbx // Since Var_B_B = K - K*Beta*K double kxx = func.FixedParameters.Prior.Variance(x); if (y.Precision == 0) { result.InducingDist.Precision.SetAllElementsTo(0); result.InducingDist.MeanTimesPrecision.SetTo(proj); result.InducingDist.MeanTimesPrecision.Scale(y.MeanTimesPrecision); } else { double my, vy; y.GetMeanAndVariance(out my, out vy); double prec = 1.0 / (vy + kxx - kbx.Inner(proj)); //Console.WriteLine($"{vf - func.Var_B_B.QuadraticForm(proj)} {func.FixedParameters.Prior.Variance(x) - func.FixedParameters.InvKernelOf_B_B.QuadraticForm(kbx)}"); if (prec > double.MaxValue || prec < 0) { int i = proj.IndexOfMaximum(); result.InducingDist.Precision.SetAllElementsTo(0); result.InducingDist.Precision[i, i] = double.PositiveInfinity; result.InducingDist.MeanTimesPrecision.SetAllElementsTo(0); result.InducingDist.MeanTimesPrecision[i] = my; } else { result.InducingDist.Precision.SetToOuter(proj, proj); result.InducingDist.Precision.Scale(prec); result.InducingDist.MeanTimesPrecision.SetTo(proj); result.InducingDist.MeanTimesPrecision.Scale(prec * my); } } result.ClearCachedValues(); return(result); }
/// <summary> /// EP message to 'func' /// </summary> /// <param name="y">Incoming message from 'y'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="func">Incoming message from 'func'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="x">Constant value for 'x'.</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 'func' as the random arguments are varied. /// The formula is <c>proj[p(func) sum_(y) p(y) factor(y,func,x)]/p(func)</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="y"/> is not a proper distribution</exception> /// <exception cref="ImproperMessageException"><paramref name="func"/> is not a proper distribution</exception> public static SparseGP FuncAverageConditional([SkipIfUniform] Gaussian y, [SkipIfUniform] SparseGP func, Vector x, SparseGP result) { if (y.IsUniform() || func.IsUniform()) { result.SetToUniform(); return result; } result.FixedParameters = func.FixedParameters; result.IncludePrior = false; double vf = func.Variance(x); double my, vy; y.GetMeanAndVariance(out my, out vy); Vector kbx = func.FixedParameters.KernelOf_X_B(x); Vector proj = func.FixedParameters.InvKernelOf_B_B * kbx; double prec = 1.0/(vy + vf - func.Var_B_B.QuadraticForm(proj)); result.InducingDist.Precision.SetToOuter(proj, proj); result.InducingDist.Precision.Scale(prec); result.InducingDist.MeanTimesPrecision.SetTo(proj); result.InducingDist.MeanTimesPrecision.Scale(prec*my); result.ClearCachedValues(); return result; }