code: def cross_validate(
      model: ModelBridge,
      folds: int = -1,
      # pyre-fixme[24]: Generic type `Callable` expects 2 type parameters.
      test_selector: Optional[Callable] = None,
  ) -> List[CVResult]:
      """Cross validation for model predictions.
  
      Splits the model's training data into train/test folds and makes
      out-of-sample predictions on the test folds.
  
      Train/test splits are made based on arm names, so that repeated
      observations of a arm will always be in the train or test set
      together.
  
      The test set can be limited to a specific set of observations by passing in
      a test_selector callable. This function should take in an Observation
      and return a boolean indiciating if it should be used in the test set or
      not. For example, we can limit the test set to arms with trial 0 with
      test_selector = lambda obs: obs.features.trial_index == 0
      If not provided, all observations will be available for the test set.
  
      Args:
          model: Fitted model (ModelBridge) to cross validate.
          folds: Number of folds. Use -1 for leave-one-out, otherwise will be
              k-fold.
          test_selector: Function for selecting observations for the test set.
  
      Returns:
          A CVResult for each observation in the training data.
      """
      # Get in-design training points
      training_data = [
          obs
          for i, obs in enumerate(model.get_training_data())
          if model.training_in_design[i]
      ]
      arm_names = {obs.arm_name for obs in training_data}
      n = len(arm_names)
      if folds > n:
          raise ValueError(
              f"Training data only has {n} arms, which is less than folds"
          )
      elif n == 0:
          raise ValueError(
              f"{model.__class__.__name__} has no training data.  Either it has been "
              "incorrectly initialized or should not be cross validated."
          )
      elif folds < 2 and folds != -1:
          raise ValueError("Folds must be -1 for LOO, or > 1.")
      elif folds == -1:
          folds = n
  
      arm_names_rnd = np.array(list(arm_names))
      np.random.shuffle(arm_names_rnd)
      result = []
      for train_names, test_names in _gen_train_test_split(
          folds=folds, arm_names=arm_names_rnd
      ):
          # Construct train/test data
          cv_training_data = []
          cv_test_data = []
          cv_test_points = []
          for obs in training_data:
              if obs.arm_name in train_names:
                  cv_training_data.append(obs)
              elif obs.arm_name in test_names and (
                  test_selector is None or test_selector(obs)
              ):
                  cv_test_points.append(obs.features)
                  cv_test_data.append(obs)
          if len(cv_test_points) == 0:
              continue
          # Make the prediction
          cv_test_predictions = model.cross_validate(
              cv_training_data=cv_training_data,
              cv_test_points=cv_test_points,
          )
          # Form CVResult objects
          for i, obs in enumerate(cv_test_data):
              result.append(
                  CVResult(
                      observed=obs, predicted=cv_test_predictions[i]
                  )
              )
      return result
  
imports: from abc import ABC, abstractmethod
  from collections import defaultdict
  from enum import Enum
  from functools import partial
  from logging import Logger
  from numbers import Number
  from typing import Any, Callable, Dict, Iterable, List, NamedTuple, Optional, Set, Tuple
  import numpy
  from ax.core.observation import Observation, ObservationData
  from ax.core.optimization_config import OptimizationConfig
  from ax.modelbridge.base import ModelBridge
  from ax.utils.common.logger import get_logger
  from ax.utils.stats.model_fit_stats import _correlation_coefficient, _fisher_exact_test_p, _log_likelihood, _mape, _mean_prediction_ci, _rank_correlation, _total_raw_effect, _wmape, compute_model_fit_metrics
label_desc: Use image node_id 1 for calling a global function with example usage: cross_validate(model, folds, test_selector) and returns: result