Exemplo 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));
        }
Exemplo n.º 2
0
        private static IValueGenerator[] ConvertToValueGenerators(IEnumerable <SweepableParam> hps)
        {
            var results = new IValueGenerator[hps.Count()];

            for (int i = 0; i < hps.Count(); i++)
            {
                switch (hps.ElementAt(i))
                {
                case SweepableDiscreteParam dp:
                    var dpArgs = new DiscreteParamArguments()
                    {
                        Name   = dp.Name,
                        Values = dp.Options.Select(o => o.ToString()).ToArray()
                    };
                    results[i] = new DiscreteValueGenerator(dpArgs);
                    break;

                case SweepableFloatParam fp:
                    var fpArgs = new FloatParamArguments()
                    {
                        Name    = fp.Name,
                        Min     = fp.Min,
                        Max     = fp.Max,
                        LogBase = fp.IsLogScale,
                    };
                    if (fp.NumSteps.HasValue)
                    {
                        fpArgs.NumSteps = fp.NumSteps.Value;
                    }
                    if (fp.StepSize.HasValue)
                    {
                        fpArgs.StepSize = fp.StepSize.Value;
                    }
                    results[i] = new FloatValueGenerator(fpArgs);
                    break;

                case SweepableLongParam lp:
                    var lpArgs = new LongParamArguments()
                    {
                        Name    = lp.Name,
                        Min     = lp.Min,
                        Max     = lp.Max,
                        LogBase = lp.IsLogScale
                    };
                    if (lp.NumSteps.HasValue)
                    {
                        lpArgs.NumSteps = lp.NumSteps.Value;
                    }
                    if (lp.StepSize.HasValue)
                    {
                        lpArgs.StepSize = lp.StepSize.Value;
                    }
                    results[i] = new LongValueGenerator(lpArgs);
                    break;
                }
            }
            return(results);
        }
Exemplo 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));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Computes a single-mutation neighborhood (one param at a time) for a given configuration. For
        /// numeric parameters, samples K mutations (i.e., creates K neighbors based on that paramater).
        /// </summary>
        /// <param name="parent">Starting configuration.</param>
        /// <returns>A set of configurations that each differ from parent in exactly one parameter.</returns>
        private ParameterSet[] GetOneMutationNeighborhood(ParameterSet parent)
        {
            List <ParameterSet>     neighbors = new List <ParameterSet>();
            SweeperProbabilityUtils spu       = new SweeperProbabilityUtils();

            for (int i = 0; i < _sweepParameters.Length; i++)
            {
                // This allows us to query possible values of this parameter.
                IValueGenerator sweepParam = _sweepParameters[i];

                // This holds the actual value for this parameter, chosen in this parameter set.
                IParameterValue pset = parent[sweepParam.Name];

                AutoMlUtils.Assert(pset != null);

                DiscreteValueGenerator parameterDiscrete = sweepParam as DiscreteValueGenerator;
                if (parameterDiscrete != null)
                {
                    // Create one neighbor for every discrete parameter.
                    Float[] neighbor = SweeperProbabilityUtils.ParameterSetAsFloatArray(_sweepParameters, parent, false);

                    int hotIndex = -1;
                    for (int j = 0; j < parameterDiscrete.Count; j++)
                    {
                        if (parameterDiscrete[j].Equals(pset))
                        {
                            hotIndex = j;
                            break;
                        }
                    }

                    AutoMlUtils.Assert(hotIndex >= 0);

                    Random r           = new Random();
                    int    randomIndex = r.Next(0, parameterDiscrete.Count - 1);
                    randomIndex += randomIndex >= hotIndex ? 1 : 0;
                    neighbor[i]  = randomIndex;
                    neighbors.Add(SweeperProbabilityUtils.FloatArrayAsParameterSet(_sweepParameters, neighbor, false));
                }
                else
                {
                    INumericValueGenerator parameterNumeric = sweepParam as INumericValueGenerator;
                    AutoMlUtils.Assert(parameterNumeric != null, "SMAC sweeper can only sweep over discrete and numeric parameters");

                    // Create k neighbors (typically 4) for every numerical parameter.
                    for (int j = 0; j < _args.NumNeighborsForNumericalParams; j++)
                    {
                        Float[] neigh  = SweeperProbabilityUtils.ParameterSetAsFloatArray(_sweepParameters, parent, false);
                        double  newVal = spu.NormalRVs(1, neigh[i], 0.2)[0];
                        while (newVal <= 0.0 || newVal >= 1.0)
                        {
                            newVal = spu.NormalRVs(1, neigh[i], 0.2)[0];
                        }
                        neigh[i] = (Float)newVal;
                        ParameterSet neighbor = SweeperProbabilityUtils.FloatArrayAsParameterSet(_sweepParameters, neigh, false);
                        neighbors.Add(neighbor);
                    }
                }
            }
            return(neighbors.ToArray());
        }