def METHOD_NAME(self, parameter_id, **kwargs):
    if not self._model_initialized:
        return _random_config(self.searchspace_json, self.random_state)
    else:
        # random samples and pick best with model
        candidate_x = [_random_config(self.searchspace_json, self.random_state) for _ in range(self.sample_size)]
        # The model has NaN issue when all the candidates are same
        # Also we can save the predict time when this happens
        if all(x == candidate_x[0] for x in candidate_x):
            return candidate_x[0]
        x_test = np.array([np.array(list(xi.values())) for xi in candidate_x])
        m, v = self.model.predict(x_test)
        # The model has NaN issue when all the candidates are very close
        if np.isnan(m).any() or np.isnan(v).any():
            return candidate_x[0]
        mean = torch.Tensor(m)
        sigma = torch.Tensor(v)
        u = (mean - torch.Tensor([0.95]).expand_as(mean)) / sigma
        normal = Normal(torch.zeros_like(u), torch.ones_like(u))
        ucdf = normal.cdf(u)
        updf = torch.exp(normal.log_prob(u))
        ei = sigma * (updf + u * ucdf)
        if self.optimize_mode == 'maximize':
            ind = torch.argmax(ei)
        else:
            ind = torch.argmin(ei)
        new_x = candidate_x[ind]
        return new_x