class_docstr: Base class for hyper parameter search with cross-validation.
docstr: Runs the ``fit()`` method of the algorithm for all parameter
  combinations, over different splits given by the ``cv`` parameter.
  
  Args:
      data (:obj:`Dataset <surprise.dataset.Dataset>`): The dataset on
          which to evaluate the algorithm, in parallel.
docstr_tok: ["Runs","the","``","fit","(",")","``","method","of","the","algorithm","for","all","parameter","combinations",",","over","different","splits","given","by","the","``","cv","``","parameter",".","Args",":","data","(",":","obj",":","`","Dataset","<","surprise.dataset.Dataset",">","`",")",":","The","dataset","on","which","to","evaluate","the","algorithm",",","in","parallel","."]
code: def fit(self, data):
      """Runs the ``fit()`` method of the algorithm for all parameter
      combinations, over different splits given by the ``cv`` parameter.
  
      Args:
          data (:obj:`Dataset <surprise.dataset.Dataset>`): The dataset on
              which to evaluate the algorithm, in parallel.
      """
  
      if self.refit and isinstance(data, DatasetUserFolds):
          raise ValueError(
              "refit cannot be used when data has been "
              "loaded with load_from_folds()."
          )
  
      cv = get_cv(self.cv)
  
      delayed_list = (
          delayed(fit_and_score)(
              self.algo_class(**params),
              trainset,
              testset,
              self.measures,
              self.return_train_measures,
          )
          for params, (trainset, testset) in product(
              self.param_combinations, cv.split(data)
          )
      )
      out = Parallel(
          n_jobs=self.n_jobs,
          pre_dispatch=self.pre_dispatch,
          verbose=self.joblib_verbose,
      )(delayed_list)
  
      (
          test_measures_dicts,
          train_measures_dicts,
          fit_times,
          test_times,
      ) = zip(*out)
  
      # test_measures_dicts is a list of dict like this:
      # [{'mae': 1, 'rmse': 2}, {'mae': 2, 'rmse': 3} ...]
      # E.g. for 5 splits, the first 5 dicts are for the first param
      # combination, the next 5 dicts are for the second param combination,
      # etc...
      # We convert it into a dict of list:
      # {'mae': [1, 2, ...], 'rmse': [2, 3, ...]}
      # Each list is still of size n_parameters_combinations * n_splits.
      # Then, reshape each list to have 2-D arrays of shape
      # (n_parameters_combinations, n_splits). This way we can easily compute
      # the mean and std dev over all splits or over all param comb.
      test_measures = dict()
      train_measures = dict()
      new_shape = (len(self.param_combinations), cv.get_n_folds())
      for m in self.measures:
          test_measures[m] = np.asarray(
              [d[m] for d in test_measures_dicts]
          )
          test_measures[m] = test_measures[m].reshape(new_shape)
          if self.return_train_measures:
              train_measures[m] = np.asarray(
                  [d[m] for d in train_measures_dicts]
              )
              train_measures[m] = train_measures[m].reshape(new_shape)
  
      cv_results = dict()
      best_index = dict()
      best_params = dict()
      best_score = dict()
      best_estimator = dict()
      for m in self.measures:
          # cv_results: set measures for each split and each param comb
          for split in range(cv.get_n_folds()):
              cv_results[f"split{split}_test_{m}"] = test_measures[m][
                  :, split
              ]
              if self.return_train_measures:
                  cv_results[
                      f"split{split}_train_{m}"
                  ] = train_measures[m][:, split]
  
          # cv_results: set mean and std over all splits (testset and
          # trainset) for each param comb
          mean_test_measures = test_measures[m].mean(axis=1)
          cv_results[f"mean_test_{m}"] = mean_test_measures
          cv_results[f"std_test_{m}"] = test_measures[m].std(axis=1)
          if self.return_train_measures:
              mean_train_measures = train_measures[m].mean(axis=1)
              cv_results[f"mean_train_{m}"] = mean_train_measures
              cv_results[f"std_train_{m}"] = train_measures[m].std(
                  axis=1
              )
  
          # cv_results: set rank of each param comb
          # also set best_index, and best_xxxx attributes
          indices = cv_results[f"mean_test_{m}"].argsort()
          cv_results[f"rank_test_{m}"] = np.empty_like(indices)
          if m in ("mae", "rmse", "mse"):
              cv_results[f"rank_test_{m}"][indices] = (
                  np.arange(len(indices)) + 1
              )  # sklearn starts at 1 as well
              best_index[m] = mean_test_measures.argmin()
          elif m in ("fcp",):
              cv_results[f"rank_test_{m}"][indices] = np.arange(
                  len(indices), 0, -1
              )
              best_index[m] = mean_test_measures.argmax()
          best_params[m] = self.param_combinations[best_index[m]]
          best_score[m] = mean_test_measures[best_index[m]]
          best_estimator[m] = self.algo_class(**best_params[m])
  
      # Cv results: set fit and train times (mean, std)
      fit_times = np.array(fit_times).reshape(new_shape)
      test_times = np.array(test_times).reshape(new_shape)
      for s, times in zip(("fit", "test"), (fit_times, test_times)):
          cv_results[f"mean_{s}_time"] = times.mean(axis=1)
          cv_results[f"std_{s}_time"] = times.std(axis=1)
  
      # cv_results: set params key and each param_* values
      cv_results["params"] = self.param_combinations
      for param in self.param_combinations[0]:
          cv_results["param_" + param] = [
              comb[param] for comb in self.param_combinations
          ]
  
      if self.refit:
          best_estimator[self.refit].fit(data.build_full_trainset())
  
      self.best_index = best_index
      self.best_params = best_params
      self.best_score = best_score
      self.best_estimator = best_estimator
      self.cv_results = cv_results
  
imports: from abc import ABC, abstractmethod
  from itertools import product
  import numpy
  from joblib import delayed, Parallel
  from ..dataset import DatasetUserFolds
  from ..utils import get_rng
  from .split import get_cv
  from .validation import fit_and_score
label_desc: Use image node_id 3 for calling the BaseSearchCV obj's underlying member method code with example usage: obj.fit(data) without return types