private static double[] LognormalLpdf(double x, double[] weights, double[] mus, double[] sigmas) { double[] ret = new double[weights.Length]; for (int i = 0; i < ret.Length; i++) { double sigma = Math.Max(sigmas[i], eps); double z = sigma * x * Math.Sqrt(2 * Math.PI); double e = 0.5 * ArrayMath.Square((Math.Log(x) - mus[i]) / sigma); ret[i] = -e - Math.Log(z) + Math.Log(weights[i]); } return(ret); }
private static (double[], double[], double[]) AdaptiveParzenNormal(double[] mus, double priorMu, double priorSigma) { int[] order = ArrayMath.ArgSort(mus); double[] sortedMus = ArrayMath.Index(mus, order); int priorPos = ArrayMath.SearchSorted(sortedMus, priorMu); sortedMus = ArrayMath.Insert(sortedMus, priorPos, priorMu); int length = mus.Length; double[] sigma = new double[length + 1]; if (length == 0) { sigma[0] = priorSigma; } else if (length == 1) { sigma[priorPos] = priorSigma; sigma[1 - priorPos] = priorSigma * 0.5; } else { sigma[0] = sortedMus[1] - sortedMus[0]; sigma[length] = sortedMus[length] - sortedMus[length - 1]; for (int i = 1; i < length; i++) { sigma[i] = Math.Max(sortedMus[i] - sortedMus[i - 1], sortedMus[i + 1] - sortedMus[i]); } } double maxSigma = priorSigma / 1.0; double minSigma = priorSigma / Math.Min(100.0, length + 2); sigma = ArrayMath.Clip(sigma, minSigma, maxSigma); sigma[priorPos] = priorSigma; double[] sortedWeights; if (lf < length) { sortedWeights = ArrayMath.Index(LinearForgettingWeights(length), order); } else { sortedWeights = Enumerable.Repeat(1.0, length).ToArray(); } sortedWeights = ArrayMath.Insert(sortedWeights, priorPos, priorWeight); sortedWeights = ArrayMath.DivSum(sortedWeights); return(sortedWeights, sortedMus, sigma); }
private static double[] NormalLpdf(double x, double[] weights, double[] mus, double[] sigmas, double pAccept) { double[] ret = new double[weights.Length]; for (int i = 0; i < ret.Length; i++) { double sigma = Math.Max(sigmas[i], eps); double dist = x - mus[i]; double mahal = ArrayMath.Square(dist / sigma); double z = Math.Sqrt(2 * Math.PI) * sigmas[i]; double coef = weights[i] / z / pAccept; ret[i] = -0.5 * mahal + Math.Log(coef); } return(ret); }
private static double[] Gmm1Lpdf(double[] samples, double[] weights, double[] mus, double[] sigmas, double low, double high, bool log, bool integer) { double pAccept = ArrayMath.Mul(weights, ArrayMath.Sub(NormalCdf(high, mus, sigmas), NormalCdf(low, mus, sigmas))).Sum(); double[] ret = new double[samples.Length]; for (int i = 0; i < samples.Length; i++) { if (!integer) { if (log) { ret[i] = LogSum(LognormalLpdf(samples[i], weights, mus, sigmas)); } else { ret[i] = LogSum(NormalLpdf(samples[i], weights, mus, sigmas, pAccept)); } } else { double prob = 0; double ubound; double lbound; if (log) { ubound = Math.Log(Math.Min(samples[i] + 0.5, Math.Exp(high))); lbound = Math.Log(Math.Max(samples[i] - 0.5, Math.Exp(low))); } else { ubound = Math.Min(samples[i] + 0.5, high); lbound = Math.Max(samples[i] - 0.5, low); } prob += ArrayMath.Mul(weights, NormalCdf(ubound, mus, sigmas)).Sum(); prob -= ArrayMath.Mul(weights, NormalCdf(lbound, mus, sigmas)).Sum(); ret[i] = Math.Log(prob) - Math.Log(pAccept); } } return(ret); }
private static int SuggestCategorical(List <Result> history, string tag, int size) { if (history.Count < nStartupJobs) { return(rng.Integer(size)); } var(obsBelow, obsAbove) = ApSplitTrials(history, tag); double[] weights = LinearForgettingWeights(obsBelow.Length); double[] counts = Bincount(obsBelow, weights, size); double[] p = ArrayMath.DivSum(ArrayMath.Add(counts, priorWeight)); int[] sample = rng.Categorical(p, nEiCandidates); double[] belowLLik = ArrayMath.Log(ArrayMath.Index(p, sample)); weights = LinearForgettingWeights(obsAbove.Length); counts = Bincount(obsAbove, weights, size); p = ArrayMath.DivSum(ArrayMath.Add(counts, priorWeight)); double[] aboveLLik = ArrayMath.Log(ArrayMath.Index(p, sample)); return(FindBest(sample, belowLLik, aboveLLik)); }
private static double SuggestNumerical(List <Result> history, string tag, double low, double high, bool log, bool integer) { if (history.Count < nStartupJobs) { double x = rng.Uniform(low, high); if (log) { x = Math.Exp(x); } if (integer) { x = Math.Round(x); } return(x); } var(obsBelow, obsAbove) = ApSplitTrials(history, tag); if (log) { obsBelow = ArrayMath.Log(obsBelow); obsAbove = ArrayMath.Log(obsAbove); } double priorMu = 0.5 * (high + low); double priorSigma = high - low; var(weights, mus, sigmas) = AdaptiveParzenNormal(obsBelow, priorMu, priorSigma); double[] samples = Gmm1(weights, mus, sigmas, low, high, log, integer); double[] belowLLik = Gmm1Lpdf(samples, weights, mus, sigmas, low, high, log, integer); (weights, mus, sigmas) = AdaptiveParzenNormal(obsAbove, priorMu, priorSigma); double[] aboveLLik = Gmm1Lpdf(samples, weights, mus, sigmas, low, high, log, integer); return(FindBest(samples, belowLLik, aboveLLik)); }
private static T FindBest <T>(T[] samples, double[] belowLLik, double[] aboveLLik) { int best = ArrayMath.ArgMax(ArrayMath.Sub(belowLLik, aboveLLik)); return(samples[best]); }