예제 #1
0
        public static NonconjugateGaussian DNonconjugateAverageLogarithm([Proper] Gamma exp, [Proper, SkipIfUniform] Gaussian d, NonconjugateGaussian result)
        {
            var    vf = -1.0;
            var    a = exp.Shape;
            var    v_opt = 1.0 / (a - 1.0);
            var    b = exp.Rate;
            double m = 0.0, v = 0.0;

            d.GetMeanAndVariance(out m, out v);
            if (a > 1)
            {
                var mf = Math.Log((a - 1) / b) - .5 * v_opt;
                if (mf != m)
                {
                    var grad_S_m = -b *Math.Exp(m + v / 2) + a - 1;

                    vf = (mf - m) / grad_S_m;
                    result.MeanTimesPrecision = mf / vf;
                    result.Precision          = 1 / vf;
                }
            }
            //m = (mp + prior_mp)/(p + prior_p);
            if (vf < 0)
            {
                result.Precision          = b * Math.Exp(m + v / 2);
                result.MeanTimesPrecision = (m - 1) * result.Precision + a - 1;
            }

            double bf = -1, afm1 = -1;

            if (a <= 1)
            {
                v_opt = FindMinimumInV(b * Math.Exp(m));
            }
            if (v_opt != v)
            {
                var grad_S_v = -.5 * b * Math.Exp(m + v / 2);
                bf   = v * grad_S_v / (v_opt - v);
                afm1 = v_opt * bf;
            }
            if (afm1 < 0 || bf < 0)
            {
                afm1 = b * v * v * Math.Exp(m + v / 2) / 4;
                bf   = b * (1 + v / 2) * Math.Exp(m + v / 2) / 2;
            }
            result.Shape = afm1 + 1;
            result.Rate  = bf;
            if (!result.IsProper())
            {
                throw new ApplicationException("improper message calculated by ExpOp.DNonconjugateAverageLogarithm");
            }
            return(result);
        }
예제 #2
0
        /// <summary>VMP message to <c>b</c>.</summary>
        /// <param name="ProductExp">Incoming message from <c>productExp</c>. Must be a proper distribution. If uniform, the result will be uniform.</param>
        /// <param name="A">Incoming message from <c>a</c>. Must be a proper distribution. If uniform, the result will be uniform.</param>
        /// <param name="B">Incoming message from <c>b</c>. Must be a proper distribution. If uniform, the result will be uniform.</param>
        /// <param name="to_B">Previous outgoing message to <c>B</c>.</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 average log-factor value, where the average is over all arguments except <c>b</c>. Because the factor is deterministic, <c>productExp</c> is integrated out before taking the logarithm. The formula is <c>exp(sum_(a) p(a) log(sum_productExp p(productExp) factor(productExp,a,b)))</c>.</para>
        /// </remarks>
        /// <exception cref="ImproperMessageException">
        ///   <paramref name="ProductExp" /> is not a proper distribution.</exception>
        /// <exception cref="ImproperMessageException">
        ///   <paramref name="A" /> is not a proper distribution.</exception>
        /// <exception cref="ImproperMessageException">
        ///   <paramref name="B" /> is not a proper distribution.</exception>
        public static NonconjugateGaussian BAverageLogarithm(
            [SkipIfUniform] Gaussian ProductExp, [Proper, SkipIfUniform] Gaussian A, [Proper, SkipIfUniform] Gaussian B, NonconjugateGaussian to_B, NonconjugateGaussian result)
        {
            if (B.IsPointMass)
            {
                return(NonconjugateGaussian.Uniform());
            }
            if (ProductExp.IsPointMass)
            {
                return(BAverageLogarithm(ProductExp.Point, A));
            }
            if (!B.IsProper())
            {
                throw new ImproperMessageException(B);
            }
            // catch uniform case to avoid 0*Inf
            if (ProductExp.IsUniform())
            {
                return(NonconjugateGaussian.Uniform());
            }
            double mx, vx, m, v, mz, vz;

            ProductExp.GetMeanAndVariance(out mz, out vz);
            A.GetMeanAndVariance(out mx, out vx);
            B.GetMeanAndVariance(out m, out v);

            //if (mx * mz < 0)
            //{
            //    Console.WriteLine("Warning: mx*mz < 0, setting to uniform");
            //    result.SetToUniform();
            //    return result;
            //}

            double Ex2        = mx * mx + vx;
            double grad2_S_m2 = -2 * Ex2 * Math.Exp(2 * m + 2 * v) / vz + mx * mz * Math.Exp(m + .5 * v) / vz;
            double grad_m     = -Ex2 *Math.Exp(2 *m + 2 *v) / vz + mx * mz * Math.Exp(m + .5 * v) / vz;

            double threshold = 10;
            double mf, vf, afm1, bf;

            if (grad2_S_m2 >= -threshold && mx * mz > 0)
            {
                mf = Math.Log(mx * mz / Ex2) - 1.5 * v;
                vf = (mf - m) / grad_m;
            }
            else
            {
                vf = -1 / grad2_S_m2;
                mf = m - grad_m / grad2_S_m2;
            }

            Gaussian priorG;

            if (result.IsUniform())
            {
                priorG = B;
            }
            else
            {
                var prior = new NonconjugateGaussian();
                prior.SetToRatio((new NonconjugateGaussian(B)), to_B);
                priorG = prior.GetGaussian();
            }

            result.MeanTimesPrecision = mf / vf;
            result.Precision          = 1 / vf;

            var updatedM = new Gaussian(mf, vf) * priorG;

            m = updatedM.GetMean();

            double grad_S2_v2 = -2 * Ex2 * Math.Exp(2 * m + 2 * v) / vz + .25 * mx * mz * Math.Exp(m + .5 * v) / vz;
            double grad_S_v   = -Ex2 *Math.Exp(2 *m + 2 *v) / vz + .5 * mx * mz * Math.Exp(m + .5 * v) / vz;

            afm1 = -1;
            bf   = -1;
            if (grad2_S_m2 >= -threshold)
            {
                afm1 = -v * v * grad_S2_v2;
                bf   = -grad_S_v + afm1 / v;
            }

            if ((afm1 < 0 || bf < 0) && mx * mz > 0)
            {
                double v_opt = 2 / 3 * (Math.Log(mx * mz / Ex2 / 2) - m);
                if (v_opt != v)
                {
                    bf   = v * grad_S_v / (v_opt - v);
                    afm1 = v_opt * bf;
                }
            }

            if (afm1 < 0 || bf < 0)
            {
                afm1 = -v * v * grad_S2_v2;
                bf   = -grad_S_v + afm1 / v;
            }

            if (afm1 < 0 || bf < 0)
            {
                result.Shape = 1;
                result.Rate  = 0;
            }
            else
            {
                result.Shape = afm1 + 1;
                result.Rate  = bf;
            }

            if (!result.IsProper())
            {
                throw new ApplicationException("improper");
            }
            return(result);
            // REMEMBER TO ADD ENTROPY TERM IN REPLICATE OP
        }
예제 #3
0
		/// <summary>
		/// VMP message to 'b'
		/// </summary>
		/// <param name="ProductExp">Incoming message from 'productExp'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
		/// <param name="A">Incoming message from 'a'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
		/// <param name="B">Incoming message from 'b'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
		/// <param name="to_B">Previous outgoing message to 'B'.</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 average log-factor value, where the average is over all arguments except 'b'.
		/// Because the factor is deterministic, 'productExp' is integrated out before taking the logarithm.
		/// The formula is <c>exp(sum_(a) p(a) log(sum_productExp p(productExp) factor(productExp,a,b)))</c>.
		/// </para></remarks>
		/// <exception cref="ImproperMessageException"><paramref name="ProductExp"/> is not a proper distribution</exception>
		/// <exception cref="ImproperMessageException"><paramref name="A"/> is not a proper distribution</exception>
		/// <exception cref="ImproperMessageException"><paramref name="B"/> is not a proper distribution</exception>
		public static NonconjugateGaussian BAverageLogarithm([SkipIfUniform] Gaussian ProductExp, [Proper, SkipIfUniform] Gaussian A, [Proper, SkipIfUniform] Gaussian B, NonconjugateGaussian to_B, NonconjugateGaussian result)
        {
            if (B.IsPointMass) return NonconjugateGaussian.Uniform();
            if (ProductExp.IsPointMass) return BAverageLogarithm(ProductExp.Point, A);
            if (!B.IsProper()) throw new ImproperMessageException(B);
            // catch uniform case to avoid 0*Inf
            if (ProductExp.IsUniform()) return NonconjugateGaussian.Uniform();
            double mx, vx, m, v, mz, vz;
            ProductExp.GetMeanAndVariance(out mz, out vz);
            A.GetMeanAndVariance(out mx, out vx);
            B.GetMeanAndVariance(out m, out v);

            //if (mx * mz < 0)
            //{
            //    Console.WriteLine("Warning: mx*mz < 0, setting to uniform");
            //    result.SetToUniform();
            //    return result;
            //}

            double Ex2 = mx * mx + vx;
            double grad2_S_m2 = -2 * Ex2 * Math.Exp(2 * m + 2 * v) / vz + mx * mz * Math.Exp(m + .5 * v) / vz;
            double grad_m = -Ex2 * Math.Exp(2 * m + 2 * v) / vz + mx * mz * Math.Exp(m + .5 * v) / vz;
            double threshold = 10;
            double mf, vf, afm1, bf;
            if (grad2_S_m2 >= -threshold && mx * mz > 0)
            {
                mf = Math.Log(mx * mz / Ex2) - 1.5 * v;
                vf = (mf - m) / grad_m;
            }
            else
            {
                vf = -1 / grad2_S_m2;
                mf = m - grad_m / grad2_S_m2;
            }
            
            Gaussian priorG;
            if (result.IsUniform())
                priorG = B;
            else
            {
                var prior = new NonconjugateGaussian();
                prior.SetToRatio((new NonconjugateGaussian(B)), to_B);
                priorG = prior.GetGaussian();
            }

            result.MeanTimesPrecision = mf / vf ;
            result.Precision = 1 / vf;

            var updatedM = new Gaussian(mf,vf) * priorG;
            m = updatedM.GetMean(); 
            
            double grad_S2_v2 = -2 * Ex2 * Math.Exp(2 * m + 2 * v) / vz + .25 * mx * mz * Math.Exp(m + .5 * v) / vz;
            double grad_S_v = -Ex2 * Math.Exp(2 * m + 2 * v) / vz + .5 * mx * mz * Math.Exp(m + .5 * v) / vz;

            afm1 = -1;
            bf = -1;
            if (grad2_S_m2 >= -threshold)
            {
                afm1 = -v * v * grad_S2_v2;
                bf = -grad_S_v + afm1 / v;
            }

            if ((afm1 < 0 || bf < 0) && mx * mz > 0)
            {
                double v_opt = 2 / 3 * (Math.Log(mx * mz / Ex2 / 2) - m);
                if (v_opt != v)
                {
                    bf = v * grad_S_v / (v_opt - v);
                    afm1 = v_opt * bf;
                }
            }

            if (afm1 < 0 || bf < 0)
            {
                afm1 = -v * v * grad_S2_v2;
                bf = -grad_S_v + afm1 / v;
            }

            if (afm1 < 0 || bf < 0)
            {
                result.Shape = 1;
                result.Rate = 0; 
            }
            else
            {
                result.Shape = afm1 + 1;
                result.Rate = bf;
            }

            if (!result.IsProper())
                throw new ApplicationException("improper");
            return result;
            // REMEMBER TO ADD ENTROPY TERM IN REPLICATE OP
        }
예제 #4
0
파일: Exp.cs 프로젝트: prgoodwin/HabilisX
		public static NonconjugateGaussian DNonconjugateAverageLogarithm([Proper] Gamma exp, [Proper, SkipIfUniform] Gaussian d, NonconjugateGaussian result)
		{
			var vf = -1.0;
			var a = exp.Shape;
			var v_opt = 1.0 / (a - 1.0);
			var b = exp.Rate;
			double m = 0.0, v = 0.0;
			d.GetMeanAndVariance(out m, out v);
			if (a > 1) {
				var mf = Math.Log((a - 1) / b) - .5 * v_opt;
				if (mf != m) {
					var grad_S_m = -b * Math.Exp(m + v / 2) + a - 1;
					vf = (mf - m) / grad_S_m;
					result.MeanTimesPrecision = mf / vf;
					result.Precision = 1 / vf;
				}
			}
			//m = (mp + prior_mp)/(p + prior_p);
			if (vf < 0) {
				result.Precision = b * Math.Exp(m + v / 2);
				result.MeanTimesPrecision = (m - 1) * result.Precision + a - 1;
			}

			double bf = -1, afm1 = -1;
			if (a <= 1)
				v_opt = FindMinimumInV(b * Math.Exp(m));
			if (v_opt != v) {
				var grad_S_v = -.5 * b * Math.Exp(m + v / 2);
				bf = v * grad_S_v / (v_opt - v);
				afm1 = v_opt * bf;
			}
			if (afm1 < 0 || bf < 0) {
				afm1 = b * v * v * Math.Exp(m + v / 2) / 4;
				bf = b * (1 + v / 2) * Math.Exp(m + v / 2) / 2;
			}
			result.Shape = afm1 + 1;
			result.Rate = bf;
			if (!result.IsProper())
				throw new ApplicationException("improper message calculated by ExpOp.DNonconjugateAverageLogarithm");
			return result;

		}