Ejemplo n.º 1
0
        /// <summary>
        /// REVIEW: This was the original CategoriesToWeights function. Should be deprecated once we can validate the new function works
        /// better. It contains a subtle issue, such that categories with poor performance but which are seen a lot will have
        /// high weight. New function addresses this issue, while also improving exploration capability of algorithm.
        /// </summary>
        /// <param name="param"></param>
        /// <param name="previousRuns"></param>
        /// <returns></returns>
        private double[] CategoriesToWeightsOld(DiscreteValueGenerator param, IEnumerable <IRunResult> previousRuns)
        {
            double[] weights = new double[param.Count];
            Dictionary <string, int> labelToIndex = new Dictionary <string, int>();

            // Map categorical values to their index.
            for (int j = 0; j < param.Count; j++)
            {
                labelToIndex[param[j].ValueText] = j;
            }

            // Add pseudo-observations, to account for unobserved parameter settings.
            for (int i = 0; i < weights.Length; i++)
            {
                weights[i] = 0.1;
            }

            // Sum up the results for each category value.
            bool isMaximizing = true;

            foreach (RunResult r in previousRuns)
            {
                weights[labelToIndex[r.ParameterSet[param.Name].ValueText]] += r.MetricValue;
                isMaximizing = r.IsMetricMaximizing;
            }

            // Normalize weights to sum to one and return
            return(isMaximizing ? SweeperProbabilityUtils.Normalize(weights) : SweeperProbabilityUtils.InverseNormalize(weights));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Converts a set of history into a set of weights, one for each run in the history.
        /// </summary>
        /// <param name="history">Input set of historical runs.</param>
        /// <param name="n">Number of total runs (history may be truncated)</param>
        /// <param name="rMean">Mean metric value of previous random runs.</param>
        /// <param name="rVar">Metric value empirical variance of previous random runs.</param>
        /// <returns>Array of weights.</returns>
        private double[] HistoryToWeights(IRunResult[] history, int n, double rMean, double rVar)
        {
            // Extract weights and normalize.
            double[] weights = new double[history.Length];

            for (int i = 0; i < history.Length; i++)
            {
                weights[i] = (double)history[i].MetricValue;
            }

            // Fitness proportional scaling constant.
            bool   isMinimizing   = history.Length > 0 && !history[0].IsMetricMaximizing;
            double currentMaxPerf = isMinimizing ? SweeperProbabilityUtils.NormalCdf(2 * rMean - weights.Min(), rMean, rVar) : SweeperProbabilityUtils.NormalCdf(weights.Max(), rMean, rVar);

            // Normalize weights to sum to one. Automatically Takes care of case where all are equal to zero.
            weights = isMinimizing ? SweeperProbabilityUtils.InverseNormalize(weights) : SweeperProbabilityUtils.Normalize(weights);

            // Scale weights. (Concentrates mass on good points, depending on how good the best currently is.)
            for (int i = 0; i < weights.Length; i++)
            {
                weights[i] = _args.Simple ? Math.Pow(weights[i], Math.Min(Math.Sqrt(n), 100)) : Math.Pow(weights[i], _args.WeightRescalingPower * currentMaxPerf);
            }

            weights = SweeperProbabilityUtils.Normalize(weights);

            return(weights);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// New version of CategoryToWeights method, which fixes an issue where we could
        /// potentially assign a lot of mass to bad categories.
        /// </summary>
        private double[] CategoriesToWeights(DiscreteValueGenerator param, IRunResult[] previousRuns)
        {
            double[] weights = new double[param.Count];
            Dictionary <string, int> labelToIndex = new Dictionary <string, int>();

            int[] counts = new int[param.Count];

            // Map categorical values to their index.
            for (int j = 0; j < param.Count; j++)
            {
                labelToIndex[param[j].ValueText] = j;
            }

            // Add mass according to performance
            bool isMaximizing = true;

            foreach (RunResult r in previousRuns)
            {
                weights[labelToIndex[r.ParameterSet[param.Name].ValueText]] += r.MetricValue;
                counts[labelToIndex[r.ParameterSet[param.Name].ValueText]]++;
                isMaximizing = r.IsMetricMaximizing;
            }

            // Take average mass for each category
            for (int i = 0; i < weights.Length; i++)
            {
                weights[i] /= (counts[i] > 0 ? counts[i] : 1);
            }

            // If any learner has not been seen, default its average to
            // best value to encourage exploration of untried algorithms.
            double bestVal = isMaximizing ?
                             previousRuns.Cast <RunResult>().Where(r => r.HasMetricValue).Max(r => r.MetricValue) :
                             previousRuns.Cast <RunResult>().Where(r => r.HasMetricValue).Min(r => r.MetricValue);

            for (int i = 0; i < weights.Length; i++)
            {
                weights[i] += counts[i] == 0 ? bestVal : 0;
            }

            // Normalize weights to sum to one and return
            return(isMaximizing ? SweeperProbabilityUtils.Normalize(weights) : SweeperProbabilityUtils.InverseNormalize(weights));
        }