Exemplo n.º 1
0
def test_space_api():
    space = Space([(0.0, 1.0), (-5, 5),
                   ("a", "b", "c"), (1.0, 5.0, "log-uniform")])

    assert_equal(len(space.dimensions), 4)
    assert_true(isinstance(space.dimensions[0], Real))
    assert_true(isinstance(space.dimensions[1], Integer))
    assert_true(isinstance(space.dimensions[2], Categorical))
    assert_true(isinstance(space.dimensions[3], Real))

    samples = space.rvs(n_samples=10, random_state=0)
    assert_equal(len(samples), 10)
    assert_equal(len(samples[0]), 4)

    samples_transformed = space.transform(samples)
    assert_equal(samples_transformed.shape[0], len(samples))
    assert_equal(samples_transformed.shape[1], 1 + 1 + 3 + 1)
    assert_array_equal(samples, space.inverse_transform(samples_transformed))

    for b1, b2 in zip(space.bounds,
                      [(0.0, 1.0), (-5, 5),
                       np.asarray(["a", "b", "c"]), (1.0, 5.0)]):
        assert_array_equal(b1, b2)

    for b1, b2 in zip(space.transformed_bounds,
                      [(0.0, 1.0), (-5, 5), (0.0, 1.0), (0.0, 1.0), (0.0, 1.0),
                       (np.log10(1.0), np.log10(5.0))]):
        assert_array_equal(b1, b2)
Exemplo n.º 2
0
def hyperband(objective, space, max_iter=100, eta=3, random_state=0,
              verbose=True, n_evaluations=None, rank=0):
    """
    Hyperband algorithm as defined by Kevin Jamieson.

    Parameters:
    ----------
    * `objective`: [function]
        Objective function to be minimized.

    * `space`: [hyperspace.space]
        Hyperparameter search space bounds.

    * `max_iter`: [int]
        Maximum number of iterations.

    * `eta`: [int]

    Returns:
    -------
    * `result` [`OptimizeResult`, scipy object]

    Reference:
    ---------
    http://people.eecs.berkeley.edu/~kjamieson/hyperband.html
    """
    logeta = lambda x: log(x)/log(eta)
    s_max = int(logeta(max_iter))  # number of unique executions of Successive Halving (minus one)
    B = (s_max+1)*max_iter  # total number of iterations (without reuse) per execution of Succesive Halving (n,r)
    # If space is the original list of tuples, convert to Space()
    if isinstance(space, list):
        space = Space(space)
    #### Begin Finite Horizon Hyperband outlerloop. Repeat indefinetely.
    yi = []
    Xi = []
    for s in reversed(range(s_max+1)):
        n = int(ceil(int(B/max_iter/(s+1))*eta**s)) # initial number of configurations
        r = max_iter*eta**(-s) # initial number of iterations to run configurations for
        # Begin Finite Horizon Successive Halving with (n,r)
        for i in range(s+1):
            # Run each of the n_i configs for r_i iterations and keep best n_i/eta
            n_i = ceil(n*eta**(-i))
            r_i = ceil(r*eta**(i))

            T = space.rvs(ceil(n_i), random_state)
            iter_result = [objective(t, r_i) for t in T]
            yi.append(iter_result)
            Xi.append(T)

            # Get next hyperparameter configurations
            T = [ T[i] for i in np.argsort(iter_result)[0:int( n_i/eta )] ]

            if verbose and rank == 0:
                print(f'Iteration number: {i}, Epochs per config: {r_i}, Num configs: {n_i}, Incumbent: {min(iter_result)}')

        result = create_result(Xi, yi, n_evaluations=n_evaluations, space=space, rng=random_state)
        # End Finite Horizon Successive Halving with (n,r)
        return result
Exemplo n.º 3
0
def test_space_api():
    space = Space([(0.0, 1.0), (-5, 5),
                   ("a", "b", "c"), (1.0, 5.0, "log-uniform"), ("e", "f")])

    cat_space = Space([(1, "r"), (1.0, "r")])
    assert isinstance(cat_space.dimensions[0], Categorical)
    assert isinstance(cat_space.dimensions[1], Categorical)

    assert_equal(len(space.dimensions), 5)
    assert_true(isinstance(space.dimensions[0], Real))
    assert_true(isinstance(space.dimensions[1], Integer))
    assert_true(isinstance(space.dimensions[2], Categorical))
    assert_true(isinstance(space.dimensions[3], Real))
    assert_true(isinstance(space.dimensions[4], Categorical))

    samples = space.rvs(n_samples=10, random_state=0)
    assert_equal(len(samples), 10)
    assert_equal(len(samples[0]), 5)

    assert_true(isinstance(samples, list))
    for n in range(4):
        assert_true(isinstance(samples[n], list))

    assert_true(isinstance(samples[0][0], numbers.Real))
    assert_true(isinstance(samples[0][1], numbers.Integral))
    assert_true(isinstance(samples[0][2], str))
    assert_true(isinstance(samples[0][3], numbers.Real))
    assert_true(isinstance(samples[0][4], str))

    samples_transformed = space.transform(samples)
    assert_equal(samples_transformed.shape[0], len(samples))
    assert_equal(samples_transformed.shape[1], 1 + 1 + 3 + 1 + 1)

    # our space contains mixed types, this means we can't use
    # `array_allclose` or similar to check points are close after a round-trip
    # of transformations
    for orig, round_trip in zip(samples,
                                space.inverse_transform(samples_transformed)):
        assert space.distance(orig, round_trip) < 1.e-8

    samples = space.inverse_transform(samples_transformed)
    assert_true(isinstance(samples[0][0], numbers.Real))
    assert_true(isinstance(samples[0][1], numbers.Integral))
    assert_true(isinstance(samples[0][2], str))
    assert_true(isinstance(samples[0][3], numbers.Real))
    assert_true(isinstance(samples[0][4], str))

    for b1, b2 in zip(space.bounds,
                      [(0.0, 1.0), (-5, 5),
                       np.asarray(["a", "b", "c"]), (1.0, 5.0),
                       np.asarray(["e", "f"])]):
        assert_array_equal(b1, b2)

    for b1, b2 in zip(space.transformed_bounds,
                      [(0.0, 1.0), (-5, 5), (0.0, 1.0), (0.0, 1.0), (0.0, 1.0),
                       (np.log10(1.0), np.log10(5.0)), (0.0, 1.0)]):
        assert_array_equal(b1, b2)
Exemplo n.º 4
0
def test_space_api():
    space = Space([(0.0, 1.0), (-5, 5),
                   ("a", "b", "c"), (1.0, 5.0, "log-uniform"), ("e", "f")])

    cat_space = Space([(1, "r"), (1.0, "r")])
    assert isinstance(cat_space.dimensions[0], Categorical)
    assert isinstance(cat_space.dimensions[1], Categorical)

    assert_equal(len(space.dimensions), 5)
    assert_true(isinstance(space.dimensions[0], Real))
    assert_true(isinstance(space.dimensions[1], Integer))
    assert_true(isinstance(space.dimensions[2], Categorical))
    assert_true(isinstance(space.dimensions[3], Real))
    assert_true(isinstance(space.dimensions[4], Categorical))

    samples = space.rvs(n_samples=10, random_state=0)
    assert_equal(len(samples), 10)
    assert_equal(len(samples[0]), 5)

    assert_true(isinstance(samples, list))
    for n in range(4):
        assert_true(isinstance(samples[n], list))

    assert_true(isinstance(samples[0][0], numbers.Real))
    assert_true(isinstance(samples[0][1], numbers.Integral))
    assert_true(isinstance(samples[0][2], str))
    assert_true(isinstance(samples[0][3], numbers.Real))
    assert_true(isinstance(samples[0][4], str))

    samples_transformed = space.transform(samples)
    assert_equal(samples_transformed.shape[0], len(samples))
    assert_equal(samples_transformed.shape[1], 1 + 1 + 3 + 1 + 1)
    assert_array_equal(samples, space.inverse_transform(samples_transformed))

    samples = space.inverse_transform(samples_transformed)
    assert_true(isinstance(samples[0][0], numbers.Real))
    assert_true(isinstance(samples[0][1], numbers.Integral))
    assert_true(isinstance(samples[0][2], str))
    assert_true(isinstance(samples[0][3], numbers.Real))
    assert_true(isinstance(samples[0][4], str))

    for b1, b2 in zip(space.bounds,
                      [(0.0, 1.0), (-5, 5),
                       np.asarray(["a", "b", "c"]), (1.0, 5.0),
                       np.asarray(["e", "f"])]):
        assert_array_equal(b1, b2)

    for b1, b2 in zip(space.transformed_bounds,
                      [(0.0, 1.0), (-5, 5), (0.0, 1.0), (0.0, 1.0), (0.0, 1.0),
                       (np.log10(1.0), np.log10(5.0)), (0.0, 1.0)]):
        assert_array_equal(b1, b2)
class Optimizer(object):
    """Run bayesian optimisation loop.
    An `Optimizer` represents the steps of a bayesian optimisation loop. To
    use it you need to provide your own loop mechanism. The various
    optimisers provided by `skopt` use this class under the hood.
    Use this class directly if you want to control the iterations of your
    bayesian optimisation loop.
    Parameters
    ----------
    * `dimensions` [list, shape=(n_dims,)]:
        List of search space dimensions.
        Each search dimension can be defined either as
        - a `(lower_bound, upper_bound)` tuple (for `Real` or `Integer`
          dimensions),
        - a `(lower_bound, upper_bound, "prior")` tuple (for `Real`
          dimensions),
        - as a list of categories (for `Categorical` dimensions), or
        - an instance of a `Dimension` object (`Real`, `Integer` or
          `Categorical`).
    * `base_estimator` ["GP", "RF", "ET", "GBRT" or sklearn regressor, default="GP"]:
        Should inherit from `sklearn.base.RegressorMixin`.
        In addition the `predict` method, should have an optional `return_std`
        argument, which returns `std(Y | x)`` along with `E[Y | x]`.
        If base_estimator is one of ["GP", "RF", "ET", "GBRT"], a default
        surrogate model of the corresponding type is used corresponding to what
        is used in the minimize functions.
    * `n_random_starts` [int, default=10]:
        DEPRECATED, use `n_initial_points` instead.
    * `n_initial_points` [int, default=10]:
        Number of evaluations of `func` with initialization points
        before approximating it with `base_estimator`. Points provided as
        `x0` count as initialization points. If len(x0) < n_initial_points
        additional points are sampled at random.
    * `acq_func` [string, default=`"gp_hedge"`]:
        Function to minimize over the posterior distribution. Can be either
        - `"LCB"` for lower confidence bound.
        - `"EI"` for negative expected improvement.
        - `"PI"` for negative probability of improvement.
        - `"gp_hedge"` Probabilistically choose one of the above three
          acquisition functions at every iteration.
            - The gains `g_i` are initialized to zero.
            - At every iteration,
                - Each acquisition function is optimised independently to
                  propose an candidate point `X_i`.
                - Out of all these candidate points, the next point `X_best` is
                  chosen by $softmax(\eta g_i)$
                - After fitting the surrogate model with `(X_best, y_best)`,
                  the gains are updated such that $g_i -= \mu(X_i)$
        - `"EIps" for negated expected improvement per second to take into
          account the function compute time. Then, the objective function is
          assumed to return two values, the first being the objective value and
          the second being the time taken in seconds.
        - `"PIps"` for negated probability of improvement per second. The
          return type of the objective function is assumed to be similar to
          that of `"EIps
    * `acq_optimizer` [string, `"sampling"` or `"lbfgs"`, default=`"auto"`]:
        Method to minimize the acquistion function. The fit model
        is updated with the optimal value obtained by optimizing `acq_func`
        with `acq_optimizer`.
        - If set to `"auto"`, then `acq_optimizer` is configured on the
          basis of the base_estimator and the space searched over.
          If the space is Categorical or if the estimator provided based on
          tree-models then this is set to be "sampling"`.
        - If set to `"sampling"`, then `acq_func` is optimized by computing
          `acq_func` at `n_points` randomly sampled points.
        - If set to `"lbfgs"`, then `acq_func` is optimized by
              - Sampling `n_restarts_optimizer` points randomly.
              - `"lbfgs"` is run for 20 iterations with these points as initial
                points to find local minima.
              - The optimal of these local minima is used to update the prior.
    * `random_state` [int, RandomState instance, or None (default)]:
        Set random state to something other than None for reproducible
        results.
    * `acq_func_kwargs` [dict]:
        Additional arguments to be passed to the acquistion function.
    * `acq_optimizer_kwargs` [dict]:
        Additional arguments to be passed to the acquistion optimizer.
    Attributes
    ----------
    * `Xi` [list]:
        Points at which objective has been evaluated.
    * `yi` [scalar]:
        Values of objective at corresponding points in `Xi`.
    * `models` [list]:
        Regression models used to fit observations and compute acquisition
        function.
    * `space`
        An instance of `skopt.space.Space`. Stores parameter search space used
        to sample points, bounds, and type of parameters.
    """
    def __init__(self,
                 dimensions,
                 base_estimator="gp",
                 n_random_starts=None,
                 n_initial_points=10,
                 acq_func="gp_hedge",
                 acq_optimizer="auto",
                 random_state=None,
                 acq_func_kwargs=None,
                 acq_optimizer_kwargs=None):

        self.rng = check_random_state(random_state)

        # Configure acquisition function
        self.acq_func = acq_func
        # monitor runtime

        self.regressiontime = None
        self.actime = None

        self.tt_regressiontime = []
        self.tt_actime = []
        self.randompoints = []

        self.values_ = None

        # Store and creat acquisition function set
        self.acq_func_kwargs = acq_func_kwargs

        allowed_acq_funcs = ["gp_hedge", "EI", "LCB", "PI", "EIps", "PIps"]
        if self.acq_func not in allowed_acq_funcs:
            raise ValueError("expected acq_func to be in %s, got %s" %
                             (",".join(allowed_acq_funcs), self.acq_func))

        # treat hedging method separately
        if self.acq_func == "gp_hedge":
            self.cand_acq_funcs_ = ["EI", "LCB", "PI"]
            self.gains_ = np.zeros(3)
        else:
            self.cand_acq_funcs_ = [self.acq_func]

        if acq_func_kwargs is None:
            acq_func_kwargs = dict()
        self.eta = acq_func_kwargs.get("eta", 1.0)

        # Configure counters of points

        # Check `n_random_starts` deprecation first
        if n_random_starts is not None:
            warnings.warn(("n_random_starts will be removed in favour of "
                           "n_initial_points."), DeprecationWarning)
            n_initial_points = n_random_starts

        if n_initial_points < 0:
            raise ValueError("Expected `n_initial_points` >= 0, got %d" %
                             n_initial_points)
        self._n_initial_points = n_initial_points
        self.n_initial_points_ = n_initial_points

        # Configure estimator

        # build base_estimator if doesn't exist
        if isinstance(base_estimator, str):
            base_estimator = cook_estimator(base_estimator,
                                            space=dimensions,
                                            random_state=self.rng.randint(
                                                0,
                                                np.iinfo(np.int32).max))

        # check if regressor
        if not is_regressor(base_estimator) and base_estimator is not None:
            raise ValueError("%s has to be a regressor." % base_estimator)

        # treat per second acqusition function specially
        is_multi_regressor = isinstance(base_estimator, MultiOutputRegressor)
        if "ps" in self.acq_func and not is_multi_regressor:
            self.base_estimator_ = MultiOutputRegressor(base_estimator)
        else:
            self.base_estimator_ = base_estimator

        # Configure optimizer

        # decide optimizer based on gradient information
        if acq_optimizer == "auto":
            if has_gradients(self.base_estimator_):
                acq_optimizer = "lbfgs"
            else:
                acq_optimizer = "sampling"

        if acq_optimizer not in ["lbfgs", "sampling"]:
            raise ValueError("Expected acq_optimizer to be 'lbfgs' or "
                             "'sampling', got {0}".format(acq_optimizer))

        if (not has_gradients(self.base_estimator_)
                and acq_optimizer != "sampling"):
            raise ValueError("The regressor {0} should run with "
                             "acq_optimizer"
                             "='sampling'.".format(type(base_estimator)))
        self.acq_optimizer = acq_optimizer

        # record other arguments
        if acq_optimizer_kwargs is None:
            acq_optimizer_kwargs = dict()

        self.n_points = acq_optimizer_kwargs.get("n_points", 10000)
        self.n_restarts_optimizer = acq_optimizer_kwargs.get(
            "n_restarts_optimizer", 5)
        n_jobs = acq_optimizer_kwargs.get("n_jobs", 1)
        self.n_jobs = n_jobs
        self.acq_optimizer_kwargs = acq_optimizer_kwargs

        # Configure search space

        # normalize space if GP regressor
        if isinstance(self.base_estimator_, GaussianProcessRegressor):
            dimensions = normalize_dimensions(dimensions)
        self.space = Space(dimensions)

        # record categorical and non-categorical indices
        self._cat_inds = []
        self._non_cat_inds = []
        for ind, dim in enumerate(self.space.dimensions):
            if isinstance(dim, Categorical):
                self._cat_inds.append(ind)
            else:
                self._non_cat_inds.append(ind)

        # Initialize storage for optimization

        self.models = []
        self.Xi = []
        self.yi = []

        # Initialize cache for `ask` method responses

        # This ensures that multiple calls to `ask` with n_points set
        # return same sets of points. Reset to {} at every call to `tell`.
        self.cache_ = {}

    def copy(self, random_state=None):
        """Create a shallow copy of an instance of the optimizer.
        Parameters
        ----------
        * `random_state` [int, RandomState instance, or None (default)]:
            Set the random state of the copy.
        """

        optimizer = Optimizer(
            dimensions=self.space.dimensions,
            base_estimator=self.base_estimator_,
            n_initial_points=self.n_initial_points_,
            acq_func=self.acq_func,
            acq_optimizer=self.acq_optimizer,
            acq_func_kwargs=self.acq_func_kwargs,
            acq_optimizer_kwargs=self.acq_optimizer_kwargs,
            random_state=random_state,
        )

        if hasattr(self, "gains_"):
            optimizer.gains_ = np.copy(self.gains_)

        if self.Xi:
            optimizer._tell(self.Xi, self.yi)

        return optimizer

    def ask(self, n_points=None, nrandom=2, strategy="cl_min"):
        """Query point or multiple points at which objective should be evaluated.
        * `n_points` [int or None, default=None]:
            Number of points returned by the ask method.
            If the value is None, a single point to evaluate is returned.
            Otherwise a list of points to evaluate is returned of size
            n_points. This is useful if you can evaluate your objective in
            parallel, and thus obtain more objective function evaluations per
            unit of time.
        * `strategy` [string, default=`"cl_min"`]:
            Method to use to sample multiple points (see also `n_points`
            description). This parameter is ignored if n_points = None.
            Supported options are `"cl_min"`, `"cl_mean"` or `"cl_max"`.
            - If set to `"cl_min"`, then constant liar strtategy is used
               with lie objective value being minimum of observed objective
               values. `"cl_mean"` and `"cl_max"` means mean and max of values
               respectively. For details on this strategy see:
               https://hal.archives-ouvertes.fr/hal-00732512/document
               With this strategy a copy of optimizer is created, which is
               then asked for a point, and the point is told to the copy of
               optimizer with some fake objective (lie), the next point is
               asked from copy, it is also told to the copy with fake
               objective and so on. The type of lie defines different
               flavours of `cl_x` strategies.
        """
        if n_points is None:
            return self._ask()
        #    if nrandom is None:
        #        return self._ask()
        #   else:
        #        print("You are using serail BO now, the nrandom must be None! Reset nrandom")
        #       nrandom = None
        #       return self._ask()

        supported_strategies = ["cl_min", "cl_mean", "cl_max"]

        if not (isinstance(n_points, int) and n_points > 0):
            raise ValueError("n_points should be int > 1, got " +
                             str(n_points))

        if strategy not in supported_strategies:
            raise ValueError("Expected parallel_strategy to be one of " +
                             str(supported_strategies) + ", " +
                             "got %s" % strategy)

        # Caching the result with n_points not None. If some new parameters
        # are provided to the ask, the cache_ is not used.
        if (n_points, strategy) in self.cache_:
            return self.cache_[(n_points, strategy)]

        # Copy of the optimizer is made in order to manage the
        # deletion of points with "lie" objective (the copy of
        # oiptimizer is simply discarded)
        opt = self.copy(random_state=self.rng.randint(0,
                                                      np.iinfo(np.int32).max))

        X = []
        if n_points > nrandom:
            for i in range(n_points - nrandom):
                x = opt.ask()
                X.append(x)
                #            print(f'1step Selected {len(X)} points')

                ti_available = "ps" in self.acq_func and len(opt.yi) > 0
                ti = [t for (_, t) in opt.yi] if ti_available else None

                if strategy == "cl_min":
                    y_lie = np.min(opt.yi) if opt.yi else 0.0  # CL-min lie
                    t_lie = np.min(ti) if ti is not None else log(
                        sys.float_info.max)
                elif strategy == "cl_mean":
                    y_lie = np.mean(opt.yi) if opt.yi else 0.0  # CL-mean lie
                    t_lie = np.mean(ti) if ti is not None else log(
                        sys.float_info.max)
                else:
                    y_lie = np.max(opt.yi) if opt.yi else 0.0  # CL-max lie
                    t_lie = np.max(ti) if ti is not None else log(
                        sys.float_info.max)

                # Lie to the optimizer.
                if "ps" in self.acq_func:
                    # Use `_tell()` instead of `tell()` to prevent repeated
                    # log transformations of the computation times.
                    opt._tell(x, (y_lie, t_lie))
                else:
                    opt._tell(x, y_lie)
                #print(f'Selected {len(X)} evaluated points')
            if nrandom == 0:
                pass
            elif nrandom > 0:
                for j in range(nrandom):
                    x_random = opt._ask_random()
                    X.append(x_random)
                    self.randompoints.append(x_random)
            else:
                ValueError("nrandom muss be nonnegative integer, but got ",
                           nrandom)
            #print(f'Selected {len(X)} points')

        else:
            for i in range(n_points):
                x = opt.ask()
                X.append(x)

                ti_available = "ps" in self.acq_func and len(opt.yi) > 0
                ti = [t for (_, t) in opt.yi] if ti_available else None

                if strategy == "cl_min":
                    y_lie = np.min(opt.yi) if opt.yi else 0.0  # CL-min lie
                    t_lie = np.min(ti) if ti is not None else log(
                        sys.float_info.max)
                elif strategy == "cl_mean":
                    y_lie = np.mean(opt.yi) if opt.yi else 0.0  # CL-mean lie
                    t_lie = np.mean(ti) if ti is not None else log(
                        sys.float_info.max)
                else:
                    y_lie = np.max(opt.yi) if opt.yi else 0.0  # CL-max lie
                    t_lie = np.max(ti) if ti is not None else log(
                        sys.float_info.max)

                # Lie to the optimizer.
                if "ps" in self.acq_func:
                    # Use `_tell()` instead of `tell()` to prevent repeated
                    # log transformations of the computation times.
                    opt._tell(x, (y_lie, t_lie))
                else:
                    opt._tell(x, y_lie)
            #print(f'Selected {len(X)} points')
        self.cache_ = {(n_points, strategy): X}  # cache_ the result

        return X

    def _ask(self):
        """Suggest next point at which to evaluate the objective.
        Return a random point while not at least `n_initial_points`
        observations have been `tell`ed, after that `base_estimator` is used
        to determine the next point.
        """
        if self._n_initial_points > 0 or self.base_estimator_ is None:
            # this will not make a copy of `self.rng` and hence keep advancing
            # our random state.
            return self.space.rvs(random_state=self.rng)[0]

        else:
            if not self.models:
                raise RuntimeError("Random evaluations exhausted and no "
                                   "model has been fit.")

            next_x = self._next_x
            min_delta_x = min(
                [self.space.distance(next_x, xi) for xi in self.Xi])
            if abs(min_delta_x) <= 1e-8:
                warnings.warn("The objective has been evaluated "
                              "at this point before.")

            # return point computed from last call to tell()
            return next_x

    def _ask_random(self):
        """Suggest next point at which to evaluate the objective.
        Return a random point while not at least `n_initial_points`
        observations have been `tell`ed, after that `base_estimator` is used
        to determine the next point.
        """
        X = self.space.transform(
            self.space.rvs(n_samples=self.n_points, random_state=self.rng))

        next_xs_ = []
        for cand_acq_func in self.cand_acq_funcs_:
            # Find the minimum of the acquisition function by randomly
            # sampling points from the space
            next_x = X[np.argmin(self.values_)]
            transformed_bounds = np.array(self.space.transformed_bounds)
            if not self.space.is_categorical:
                next_x = np.clip(next_x, transformed_bounds[:, 0],
                                 transformed_bounds[:, 1])
            next_xs_.append(next_x)

        next_x = next_xs_[0]
        # note the need for [0] at the end
        _next_x = self.space.inverse_transform(next_x.reshape((1, -1)))[0]

        # if not self.models:
        #     raise RuntimeError("Random evaluations exhausted and no "
        #                        "model has been fit.")

        next_x = _next_x
        min_delta_x = min([self.space.distance(next_x, xi) for xi in self.Xi])
        if abs(min_delta_x) <= 1e-8:
            warnings.warn("The objective has been evaluated "
                          "at this point before.")

        # return point computed from last call to tell()
        return next_x

    def tell(self, x, y, fit=True):
        """Record an observation (or several) of the objective function.
        Provide values of the objective function at points suggested by `ask()`
        or other points. By default a new model will be fit to all
        observations. The new model is used to suggest the next point at
        which to evaluate the objective. This point can be retrieved by calling
        `ask()`.
        To add observations without fitting a new model set `fit` to False.
        To add multiple observations in a batch pass a list-of-lists for `x`
        and a list of scalars for `y`.
        Parameters
        ----------
        * `x` [list or list-of-lists]:
            Point at which objective was evaluated.
        * `y` [scalar or list]:
            Value of objective at `x`.
        * `fit` [bool, default=True]
            Fit a model to observed evaluations of the objective. A model will
            only be fitted after `n_initial_points` points have been told to
            the optimizer irrespective of the value of `fit`.
        """
        check_x_in_space(x, self.space)
        self._check_y_is_valid(x, y)

        # take the logarithm of the computation times
        if "ps" in self.acq_func:
            if is_2Dlistlike(x):
                y = [[val, log(t)] for (val, t) in y]
            elif is_listlike(x):
                y = list(y)
                y[1] = log(y[1])

        return self._tell(x, y, fit=fit)

    def _tell(self, x, y, fit=True):
        """Perform the actual work of incorporating one or more new points.
        See `tell()` for the full description.
        This method exists to give access to the internals of adding points
        by side stepping all input validation and transformation."""

        if "ps" in self.acq_func:
            if is_2Dlistlike(x):
                self.Xi.extend(x)
                self.yi.extend(y)
                self._n_initial_points -= len(y)
            elif is_listlike(x):
                self.Xi.append(x)
                self.yi.append(y)
                self._n_initial_points -= 1
        # if y isn't a scalar it means we have been handed a batch of points
        elif is_listlike(y) and is_2Dlistlike(x):
            self.Xi.extend(x)
            self.yi.extend(y)
            self._n_initial_points -= len(y)
        elif is_listlike(x):
            self.Xi.append(x)
            self.yi.append(y)
            self._n_initial_points -= 1
        else:
            raise ValueError("Type of arguments `x` (%s) and `y` (%s) "
                             "not compatible." % (type(x), type(y)))

        # optimizer learned something new - discard cache
        self.cache_ = {}

        # after being "told" n_initial_points we switch from sampling
        # random points to using a surrogate model
        #mprint("starting fit gpr......")

        if (fit and self._n_initial_points <= 0
                and self.base_estimator_ is not None):
            #print('start finding next x.....')
            transformed_bounds = np.array(self.space.transformed_bounds)
            est = clone(self.base_estimator_)
            start_clock = time.time()
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                est.fit(self.space.transform(self.Xi), self.yi)
            self.regressiontime = time.time() - start_clock
            self.tt_regressiontime.append(self.regressiontime)
            if hasattr(self, "next_xs_") and self.acq_func == "gp_hedge":
                self.gains_ -= est.predict(np.vstack(self.next_xs_))
            self.models.append(est)

            #mprint("finished fit gpr......")

            # even with BFGS as optimizer we want to sample a large number
            # of points and then pick the best ones as starting points
            start_clock_ac = time.time()
            X = self.space.transform(
                self.space.rvs(n_samples=self.n_points, random_state=self.rng))

            self.next_xs_ = []
            for cand_acq_func in self.cand_acq_funcs_:
                values = _gaussian_acquisition(
                    X=X,
                    model=est,
                    y_opt=np.min(self.yi),
                    acq_func=cand_acq_func,
                    acq_func_kwargs=self.acq_func_kwargs)
                self.values = values
                # Find the minimum of the acquisition function by randomly
                # sampling points from the space
                if self.acq_optimizer == "sampling":
                    next_x = X[np.argmin(values)]

                # Use BFGS to find the mimimum of the acquisition function, the
                # minimization starts from `n_restarts_optimizer` different
                # points and the best minimum is used
                elif self.acq_optimizer == "lbfgs":
                    x0 = X[np.argsort(values)[:self.n_restarts_optimizer]]

                    with warnings.catch_warnings():
                        warnings.simplefilter("ignore")
                        results = Parallel(n_jobs=self.n_jobs)(
                            delayed(fmin_l_bfgs_b)(
                                gaussian_acquisition_1D,
                                x,
                                args=(est, np.min(self.yi), cand_acq_func,
                                      self.acq_func_kwargs),
                                bounds=self.space.transformed_bounds,
                                approx_grad=False,
                                maxiter=20) for x in x0)

                    cand_xs = np.array([r[0] for r in results])
                    cand_acqs = np.array([r[1] for r in results])
                    next_x = cand_xs[np.argmin(cand_acqs)]
                self.actime = start_clock_ac - time.time()
                self.tt_actime.append(self.actime)
                # lbfgs should handle this but just in case there are
                # precision errors.
                if not self.space.is_categorical:
                    next_x = np.clip(next_x, transformed_bounds[:, 0],
                                     transformed_bounds[:, 1])
                self.next_xs_.append(next_x)

            if self.acq_func == "gp_hedge":
                logits = np.array(self.gains_)
                logits -= np.max(logits)
                exp_logits = np.exp(self.eta * logits)
                probs = exp_logits / np.sum(exp_logits)
                next_x = self.next_xs_[np.argmax(self.rng.multinomial(
                    1, probs))]
            else:
                next_x = self.next_xs_[0]

            # note the need for [0] at the end
            self._next_x = self.space.inverse_transform(next_x.reshape(
                (1, -1)))[0]

        # Pack results
        return create_result(self.Xi,
                             self.yi,
                             self.space,
                             self.rng,
                             models=self.models)

    def _check_y_is_valid(self, x, y):
        """Check if the shape and types of x and y are consistent."""

        if "ps" in self.acq_func:
            if is_2Dlistlike(x):
                if not (np.ndim(y) == 2 and np.shape(y)[1] == 2):
                    raise TypeError("expected y to be a list of (func_val, t)")
            elif is_listlike(x):
                if not (np.ndim(y) == 1 and len(y) == 2):
                    raise TypeError("expected y to be (func_val, t)")

        # if y isn't a scalar it means we have been handed a batch of points
        elif is_listlike(y) and is_2Dlistlike(x):
            for y_value in y:
                if not isinstance(y_value, Number):
                    raise ValueError("expected y to be a list of scalars")

        elif is_listlike(x):
            if not isinstance(y, Number):
                print(type(y))
                raise ValueError("`func` should return a scalar")

        else:
            raise ValueError("Type of arguments `x` (%s) and `y` (%s) "
                             "not compatible." % (type(x), type(y)))

    def run(self, func, n_iter=1):
        """Execute ask() + tell() `n_iter` times"""
        for _ in range(n_iter):
            x = self.ask()
            self.tell(x, func(x))

        return create_result(self.Xi,
                             self.yi,
                             self.space,
                             self.rng,
                             models=self.models)

    def get_regressiontime(self):
        return (self.regressiontime)

    def get_acntime(self):
        return (self.actime)

    def get_randompoint(self):
        return (self.randompoints)
Exemplo n.º 6
0
def test_space_consistency():
    # Reals (uniform)

    s1 = Space([Real(0.0, 1.0)])
    s2 = Space([Real(0.0, 1.0)])
    s3 = Space([Real(0, 1)])
    s4 = Space([(0.0, 1.0)])
    s5 = Space([(0.0, 1.0, "uniform")])
    a1 = s1.rvs(n_samples=10, random_state=0)
    a2 = s2.rvs(n_samples=10, random_state=0)
    a3 = s3.rvs(n_samples=10, random_state=0)
    a4 = s4.rvs(n_samples=10, random_state=0)
    a5 = s5.rvs(n_samples=10, random_state=0)
    assert_equal(s1, s2)
    assert_equal(s1, s3)
    assert_equal(s1, s4)
    assert_equal(s1, s5)
    assert_array_equal(a1, a2)
    assert_array_equal(a1, a3)
    assert_array_equal(a1, a4)
    assert_array_equal(a1, a5)

    # Reals (log-uniform)
    s1 = Space([Real(10**-3.0, 10**3.0, prior="log-uniform")])
    s2 = Space([Real(10**-3.0, 10**3.0, prior="log-uniform")])
    s3 = Space([Real(10**-3, 10**3, prior="log-uniform")])
    s4 = Space([(10**-3.0, 10**3.0, "log-uniform")])
    a1 = s1.rvs(n_samples=10, random_state=0)
    a2 = s2.rvs(n_samples=10, random_state=0)
    a3 = s3.rvs(n_samples=10, random_state=0)
    a4 = s4.rvs(n_samples=10, random_state=0)
    assert_equal(s1, s2)
    assert_equal(s1, s3)
    assert_equal(s1, s4)
    assert_array_equal(a1, a2)
    assert_array_equal(a1, a3)
    assert_array_equal(a1, a4)

    # Integers
    s1 = Space([Integer(1, 5)])
    s2 = Space([Integer(1.0, 5.0)])
    s3 = Space([(1, 5)])
    a1 = s1.rvs(n_samples=10, random_state=0)
    a2 = s2.rvs(n_samples=10, random_state=0)
    a3 = s3.rvs(n_samples=10, random_state=0)
    assert_equal(s1, s2)
    assert_equal(s1, s3)
    assert_array_equal(a1, a2)
    assert_array_equal(a1, a3)

    # Categoricals
    s1 = Space([Categorical(["a", "b", "c"])])
    s2 = Space([Categorical(["a", "b", "c"])])
    a1 = s1.rvs(n_samples=10, random_state=0)
    a2 = s2.rvs(n_samples=10, random_state=0)
    assert_equal(s1, s2)
    assert_array_equal(a1, a2)
Exemplo n.º 7
0
class RandomStepOptimizer():
    """
    A method that arised from the empirical evaluation of the 
    performance of GeneticOptimizer class.

    It appears that on the set of benchmarks that are used in
    this library, the mutation operation when used alone, that
    is, without the crossover step, yields the best performing
    results. This surprising observation was obtained by running 
    optimization of ga_optimize parameters using Bayesian 
    Optimization. 
    For  more details, refer to find_hypers_ga.py file in this folder.
    The result was that Bayesian Optimization algorithm 
    consistently selected the tournament size to being 1.0,
    which is equivalent to always work on top performing vector,
    and disabling the crossover procedure. The optimization
    of the GA hyperparameters was done on ~30 tasks of the 
    evalset set of benchmarks, and then was validated on the
    rest of ~20 tasks. The ranking of the algorithm was
    fairly close on both partitions of functions:
    - "training" partition: ranking of 2.1 (less is better)
    - testing partition: ranking of ~2.5
    - max ranking was obtained with dummy optimizer of ~5.5

    Parameters
    ----------
    * `n_random_starts` [int]:
        Size of initial population, generated at random. After
        this number of fitness values is reported for individuals
        (points), the actual algorithm starts.

    * `mutation_rate` [float]:
        Probability of a value of dimension of a point (gene of 
        individual) to be randomly changed. 
        
    """
    def __init__(self, dimensions, n_random_starts=10, mutation_rate=0.05):
        self.Xi = []
        self.yi = []
        self.space = Space(dimensions)
        self.n_random_starts = n_random_starts
        self.n_random_starts_ = n_random_starts
        self.mutation_rate = mutation_rate

    def rnd(self, prob=None):
        """Returns true with probability given by 'prob' """
        if prob is None:
            prob = self.mutation_rate

        return np.random.rand() < prob

    def mutate(self, point):
        """Perform random mutation on the point"""

        finished = False
        while not finished:
            # there is a large chance that the point will not be mutated.
            # but it does not really makes sense to evaluate the same point
            # multiple times (at least for noiseless case) hence the point
            # should necessary be mutated.
            result = []
            for i in range(len(point)):
                dim = self.space.dimensions[i]
                v = point[i]

                if isinstance(dim, Categorical) and self.rnd():
                    # record that there has been a change to the point
                    finished = True
                    i = np.random.randint(len(dim.categories))
                    v = dim.categories[i]

                if isinstance(dim, Real) or isinstance(dim, Integer):
                    # one could represent real value as a sequence
                    # of binary values. however, here mutation is done
                    # explicity with numbers.
                    a, b = dim.low, dim.high
                    for i in range(-16, 1):
                        if self.rnd():
                            # record that there has been a change to the point
                            finished = True
                            # amount of change, proportional to the size of the dimension
                            scale = 2.0**i

                            # determine the direction of change - towards a or b
                            if self.rnd(0.5):
                                v += (b - v) * scale
                            else:
                                v -= (v - a) * scale

                            # it should always hold that a <= v <= b.
                            if v < a:
                                v = a

                            if v > b:
                                v = b

                    # round the number if integer dimension
                    if isinstance(dim, Integer):
                        v = round(v)

                result.append(v)

        return result

    def ask(self):
        # a standard random initialization
        if self.n_random_starts_ > 0:
            sample = self.space.rvs()[0]
            return sample

        # find the best point
        c = min(zip(self.Xi, self.yi), key=lambda t: t[-1])[0]

        # mutate the point
        c = self.mutate(c)
        return c

    def tell(self, x, y):
        self.n_random_starts_ = max(0, self.n_random_starts_ - 1)
        self.Xi.append(x)
        self.yi.append(y)
Exemplo n.º 8
0
class GeneticOptimizer:
    """
    Simplistic genetic optimizer. Based on general description of 
    GA algorithm given in p.3 of Konak, Abdullah, David W. Coit, 
    and Alice E. Smith. "Multi-objective optimization using genetic
    algorithms: A tutorial." Reliability Engineering & System Safety 
    91.9 (2006): 992-1007.

    Tournament selection is used for selection of points to do 
    crossover with:
    https://en.wikipedia.org/wiki/Tournament_selection
    This way, scaling of objective does not have any effect on
    selection procedure, compared to for example Fitness proportionate 
    selection.

    Parameters
    ----------
    * `n_random_starts` [int]:
        Size of initial population, generated at random. After
        this number of fitness values is reported for individuals
        (points), the actual GA algorithm starts.

    * `tournament_fraction` [float]:
        Size of random subset of available population from where
        the fittest individual (point).
        https://en.wikipedia.org/wiki/Tournament_selection
        
    * `mutation_rate` [float]:
        Probability of a value of dimension of a point (gene of 
        individual) to be randomly changed. 
        
    """
    def __init__(self,
                 dimensions,
                 n_random_starts=10,
                 tournament_fraction=0.2,
                 mutation_rate=0.05):
        self.Xi = []
        self.yi = []
        self.space = Space(dimensions)
        self.n_random_starts = n_random_starts
        self.n_random_starts_ = n_random_starts
        self.tournament_fraction = tournament_fraction
        self.mutation_rate = mutation_rate

    def tournament(self):
        """Returns an individual that wins a randomized tournament"""

        yi = self.yi
        Xi = self.Xi

        size = len(self.yi) * self.tournament_fraction

        # select points for tournament
        selected = {}
        while len(selected) < size:
            i = np.random.randint(len(yi))
            selected[i] = 1

        # select the fittest individual in the tournament
        x, y = Xi[i], yi[i]
        for k in selected:
            if yi[k] < y:
                x = Xi[k]
                y = yi[k]

        # return the selected individual
        return x

    def rnd(self, prob=None):
        """Returns true with probability given by 'prob' """
        if prob is None:
            prob = self.mutation_rate

        return np.random.rand() < prob

    def crossover(self, a, b):
        """done simply by selecting at random
        values of point a or b for offspring. """
        c = []
        for av, bv in zip(a, b):
            if self.rnd(0.5):
                c.append(av)
            else:
                c.append(bv)
        return c

    def mutate(self, point):
        """Perform random mutation on the point"""
        result = []

        for i in range(len(point)):
            dim = self.space.dimensions[i]
            v = point[i]

            if isinstance(dim, Categorical) and self.rnd():
                i = np.random.randint(len(dim.categories))
                v = dim.categories[i]

            if isinstance(dim, Real) or isinstance(dim, Integer):
                # one could represent real value as a sequence
                # of binary values. however, here mutation is done
                # explicity with numbers.
                a, b = dim.low, dim.high
                for i in range(16):
                    if self.rnd():
                        # amount of change, proportional to the size of the dimension
                        scale = 2.0**(-1.0 * i)

                        # determine the direction of change - towards a or b
                        if self.rnd(0.5):
                            v += (b - v) * scale
                        else:
                            v -= (v - a) * scale

                        # it should always hold that a <= v <= b.
                        if v < a:
                            v = a

                        if v > b:
                            v = b

                # round the number if integer dimension
                if isinstance(dim, Integer):
                    v = round(v)

            result.append(v)

        return result

    def ask(self):
        # initialization of the genetic algorithm
        if self.n_random_starts_ > 0:
            sample = self.space.rvs()[0]
            return sample

        # select two points to cross - over
        a = self.tournament()
        b = self.tournament()

        # produce offspring
        c = self.crossover(a, b)

        # mutate the point
        c = self.mutate(c)
        return c

    def tell(self, x, y):
        self.n_random_starts_ = max(0, self.n_random_starts_ - 1)
        self.Xi.append(x)
        self.yi.append(y)
    ax.set_xlabel("X1")
    ax.set_xlim([-5, 10])
    ax.set_ylabel("X2")
    ax.set_ylim([0, 15])
    plt.title(title)


n_samples = 10

space = Space([(-5., 10.), (0., 15.)])
# space.set_transformer("normalize")

#############################################################################
# Random sampling
# ---------------
x = space.rvs(n_samples)
plot_searchspace(x, "Random samples")
pdist_data = []
x_label = []
pdist_data.append(pdist(x).flatten())
x_label.append("random")

#############################################################################
# Sobol'
# ------

sobol = Sobol()
x = sobol.generate(space.dimensions, n_samples)
plot_searchspace(x, "Sobol'")
pdist_data.append(pdist(x).flatten())
x_label.append("sobol'")
Exemplo n.º 10
0
def test_space_consistency():
    # Reals (uniform)

    s1 = Space([Real(0.0, 1.0)])
    s2 = Space([Real(0.0, 1.0)])
    s3 = Space([Real(0, 1)])
    s4 = Space([(0.0, 1.0)])
    s5 = Space([(0.0, 1.0, "uniform")])
    s6 = Space([(0, 1.0)])
    s7 = Space([(np.float64(0.0), 1.0)])
    s8 = Space([(0, np.float64(1.0))])
    a1 = s1.rvs(n_samples=10, random_state=0)
    a2 = s2.rvs(n_samples=10, random_state=0)
    a3 = s3.rvs(n_samples=10, random_state=0)
    a4 = s4.rvs(n_samples=10, random_state=0)
    a5 = s5.rvs(n_samples=10, random_state=0)
    assert_equal(s1, s2)
    assert_equal(s1, s3)
    assert_equal(s1, s4)
    assert_equal(s1, s5)
    assert_equal(s1, s6)
    assert_equal(s1, s7)
    assert_equal(s1, s8)
    assert_array_equal(a1, a2)
    assert_array_equal(a1, a3)
    assert_array_equal(a1, a4)
    assert_array_equal(a1, a5)

    # Reals (log-uniform)
    s1 = Space([Real(10**-3.0, 10**3.0, prior="log-uniform")])
    s2 = Space([Real(10**-3.0, 10**3.0, prior="log-uniform")])
    s3 = Space([Real(10**-3, 10**3, prior="log-uniform")])
    s4 = Space([(10**-3.0, 10**3.0, "log-uniform")])
    s5 = Space([(np.float64(10**-3.0), 10**3.0, "log-uniform")])
    a1 = s1.rvs(n_samples=10, random_state=0)
    a2 = s2.rvs(n_samples=10, random_state=0)
    a3 = s3.rvs(n_samples=10, random_state=0)
    a4 = s4.rvs(n_samples=10, random_state=0)
    assert_equal(s1, s2)
    assert_equal(s1, s3)
    assert_equal(s1, s4)
    assert_equal(s1, s5)
    assert_array_equal(a1, a2)
    assert_array_equal(a1, a3)
    assert_array_equal(a1, a4)

    # Integers
    s1 = Space([Integer(1, 5)])
    s2 = Space([Integer(1.0, 5.0)])
    s3 = Space([(1, 5)])
    s4 = Space([(np.int64(1.0), 5)])
    s5 = Space([(1, np.int64(5.0))])
    a1 = s1.rvs(n_samples=10, random_state=0)
    a2 = s2.rvs(n_samples=10, random_state=0)
    a3 = s3.rvs(n_samples=10, random_state=0)
    assert_equal(s1, s2)
    assert_equal(s1, s3)
    assert_equal(s1, s4)
    assert_equal(s1, s5)
    assert_array_equal(a1, a2)
    assert_array_equal(a1, a3)

    # Categoricals
    s1 = Space([Categorical(["a", "b", "c"])])
    s2 = Space([Categorical(["a", "b", "c"])])
    s3 = Space([["a", "b", "c"]])
    a1 = s1.rvs(n_samples=10, random_state=0)
    a2 = s2.rvs(n_samples=10, random_state=0)
    a3 = s3.rvs(n_samples=10, random_state=0)
    assert_equal(s1, s2)
    assert_array_equal(a1, a2)
    assert_equal(s1, s3)
    assert_array_equal(a1, a3)

    s1 = Space([(True, False)])
    s2 = Space([Categorical([True, False])])
    s3 = Space([np.array([True, False])])
    assert s1 == s2 == s3
Exemplo n.º 11
0
def main():
    # Training settings
    parser = argparse.ArgumentParser(description='PyTorch MNIST Example')
    parser.add_argument('--batch-size',
                        type=int,
                        default=64,
                        metavar='N',
                        help='input batch size for training (default: 64)')
    parser.add_argument('--test-batch-size',
                        type=int,
                        default=1000,
                        metavar='N',
                        help='input batch size for testing (default: 1000)')
    parser.add_argument('--epochs',
                        type=int,
                        default=10,
                        metavar='N',
                        help='number of epochs to train (default: 10)')
    parser.add_argument('--lr',
                        type=float,
                        default=0.01,
                        metavar='LR',
                        help='learning rate (default: 0.01)')
    parser.add_argument('--momentum',
                        type=float,
                        default=0.5,
                        metavar='M',
                        help='SGD momentum (default: 0.5)')
    parser.add_argument('--no-cuda',
                        action='store_true',
                        default=False,
                        help='disables CUDA training')
    parser.add_argument('--seed',
                        type=int,
                        default=42,
                        metavar='S',
                        help='random seed (default: 42)')
    parser.add_argument(
        '--log-interval',
        type=int,
        default=10,
        metavar='N',
        help='how many batches to wait before logging training status')
    parser.add_argument('--fp16-allreduce',
                        action='store_true',
                        default=False,
                        help='use fp16 compression during allreduce')
    parser.add_argument('--results_path',
                        type=str,
                        help="Path to store results")
    args = parser.parse_args()
    args.cuda = not args.no_cuda and torch.cuda.is_available()

    # Horovod: initialize library.
    hvd.init()
    torch.manual_seed(args.seed)

    if args.cuda:
        # Horovod: pin GPU to local rank.
        torch.cuda.set_device(hvd.local_rank())
        torch.cuda.manual_seed(args.seed)

    kwargs = {'num_workers': 1, 'pin_memory': True} if args.cuda else {}
    train_dataset = \
        datasets.MNIST('data-%d' % hvd.rank(), train=True, download=True,
                    transform=transforms.Compose([
                        transforms.ToTensor(),
                        transforms.Normalize((0.1307,), (0.3081,))
                    ]))

    # Horovod: use DistributedSampler to partition the training data.
    train_sampler = torch.utils.data.distributed.DistributedSampler(
        train_dataset, num_replicas=hvd.size(), rank=hvd.rank())
    train_loader = torch.utils.data.DataLoader(train_dataset,
                                               batch_size=args.batch_size,
                                               sampler=train_sampler,
                                               **kwargs)

    test_dataset = \
        datasets.MNIST('data-%d' % hvd.rank(), train=False, transform=transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.1307,), (0.3081,))
        ]))

    # Horovod: use DistributedSampler to partition the test data.
    test_sampler = torch.utils.data.distributed.DistributedSampler(
        test_dataset, num_replicas=hvd.size(), rank=hvd.rank())
    test_loader = torch.utils.data.DataLoader(test_dataset,
                                              batch_size=args.test_batch_size,
                                              sampler=test_sampler,
                                              **kwargs)

    model = Net()

    if args.cuda:
        # Move model to GPU.
        model.cuda()

    # Horovod: broadcast parameters.
    hvd.broadcast_parameters(model.state_dict(), root_rank=0)

    global optimizer
    # Horovod: scale learning rate by the number of GPUs.
    optimizer = optim.SGD(model.parameters(),
                          lr=args.lr * hvd.size(),
                          momentum=args.momentum)

    # Horovod: (optional) compression algorithm.
    compression = hvd.Compression.fp16 if args.fp16_allreduce else hvd.Compression.none

    # Horovod: wrap optimizer with DistributedOptimizer.
    optimizer = hvd.DistributedOptimizer(
        optimizer,
        named_parameters=model.named_parameters(),
        compression=compression)

    #for epoch in range(1, args.epochs + 1):
    #    train(epoch, model, optimizer, train_sampler, train_loader, args)
    #    test(model, test_sampler, test_loader, args)

    checkpoint_file = os.path.join(args.results_path, f'skopt_torch_results')
    checkpoint_saver = CheckpointSaver(checkpoint_file, compress=9)

    space = Space([(2, 8)])

    try:
        res = load(checkpoint_file)
        x0 = res.x_iters
        y0 = res.func_vals
    except FileNotFoundError:
        print(f'No previous save point.')
        # Need to randomly sample the bounds to prime the optimization.
        x0 = space.rvs(1)
        y0 = None

    gp_minimize(
        lambda x: objective(x, model, train_sampler, train_loader, args
                            ),  # the function to minimize
        space,  # the bounds on each dimension of x
        x0=x0,  # already examined values for x
        y0=y0,  # observed values for x0
        acq_func="LCB",  # the acquisition function (optional)
        n_calls=20,  # the number of evaluations of f including at x0
        n_random_starts=0,  # the number of random initialization points
        callback=[checkpoint_saver],
        random_state=777)
Exemplo n.º 12
0
def SkoptCMAoptimizer(
        func,
        dimensions,
        n_calls,
        verbose=False,
        callback=(),
        x0=None,
        sigma0=.5,
        normalize=True,
):
    '''
    Optmizer based on CMA-ES algorithm.
    This is essentially a wrapper fuction for the cma library function
    to align the interface with skopt library.

    Args:
        func (callable): function to optimize
        dimensions: list of tuples.  search dimensions
        n_calls: the number of samples.
        verbose: if this func should be verbose
        callback: the list of callback functions.
        x0: inital values
            if None, random point will be sampled
        sigma0: initial standard deviation
        normalize: whether optimization domain should be normalized

    Returns:
        `res` skopt.OptimizeResult object
        The optimization result returned as a dict object.
        Important attributes are:
        - `x` [list]: location of the minimum.
        - `fun` [float]: function value at the minimum.
        - `x_iters` [list of lists]: location of function evaluation for each
           iteration.
        - `func_vals` [array]: function value for each iteration.
        - `space` [Space]: the optimization space.
    '''
    specs = {
        'args': copy.copy(inspect.currentframe().f_locals),
        'function': inspect.currentframe().f_code.co_name,
    }

    if normalize:
        dimensions = list(
            map(lambda x: check_dimension(x, 'normalize'), dimensions))
    space = Space(dimensions)
    if x0 is None: x0 = space.transform(space.rvs())[0]

    tempdir = tempfile.mkdtemp()
    xi, yi = [], []
    options = {
        'bounds': np.array(space.transformed_bounds).transpose().tolist(),
        'verb_filenameprefix': tempdir,
    }

    def delete_tempdir(self, *args, **kargs):
        os.removedirs(tempdir)
        return

    model = cma.CMAEvolutionStrategy(x0, sigma0, options)
    model.logger.__del__ = delete_tempdir
    for i in range(n_calls):
        if model.stop(): break
        new_xi = model.ask()
        new_xi_denorm = space.inverse_transform(np.array(new_xi))
        new_yi = [func(x) for x in new_xi_denorm]

        model.tell(new_xi, new_yi)
        model.logger.add()
        if verbose: model.disp()

        xi += new_xi_denorm
        yi += new_yi
        results = create_result(xi, yi)
        for f in callback:
            f(results)

    results = create_result(xi, yi, space)
    model.logger.load()
    results.cma_logger = model.logger
    results.specs = specs
    return results
Exemplo n.º 13
0
import STP_aux as aux
import MoNeT_MGDrivE as monet

from skopt.space import Space
from skopt.sampler import Lhs


space = Space([
    (0.0395, 0.0790, 0.1185, 0.0000), 
    (0, 1e-2, 1e-4, 1e-8), 
    (0.08750, 0.13125, 0.17500, 0.21875, 0.26250, 0.00000)
])

n_samples = 100

rand = space.rvs(NSAMP)
len(rand)


lhs = Lhs(lhs_type="centered", criterion=None)
lhs.generate(space.dimensions, n_samples)

# if monet.isNotebook():
#     (USR, LND) = ('dsk', 'PAN')
# else:
#     (USR, LND) = (sys.argv[1], sys.argv[2])
# EXPS = aux.getExps(LND)
# (PT_ROT, _, _, _, _, _) = aux.selectPath(USR, EXPS[0], LND)
# expsToPlot = aux.EXPS_TO_PLOT
###############################################################################
# Generate keycards