code: def grid_search(
      cv_results_,
      change,
      subset=None,
      kind="line",
      cmap=None,
      ax=None,
      sort=True,
  ):
      """
      Plot results from a sklearn grid search by changing two parameters at most.
  
      Parameters
      ----------
      cv_results_ : list of named tuples
          Results from a sklearn grid search (get them using the
          `cv_results_` parameter)
      change : str or iterable with len<=2
          Parameter to change
      subset : dictionary-like
          parameter-value(s) pairs to subset from grid_scores.
          (e.g. ``{'n_estimators': [1, 10]}``), if None all combinations will be
          used.
      kind : ['line', 'bar']
          This only applies whe change is a single parameter. Changes the
          type of plot
      cmap : matplotlib Colormap
          This only applies when change are two parameters. Colormap used for
          the matrix. If None uses a modified version of matplotlib's OrRd
          colormap.
      ax: matplotlib Axes
          Axes object to draw the plot onto, otherwise uses current Axes
      sort: bool
          If True sorts the results in alphabetical order.
  
      Returns
      -------
      ax: matplotlib Axes
          Axes containing the plot
  
      Examples
      --------
  
      .. plot:: ../examples/grid_search.py
  
      """
      if change is None:
          raise ValueError(
              (
                  "change can't be None, you need to select at least"
                  " one value to make the plot."
              )
          )
  
      if ax is None:
          ax = plt.gca()
  
      if cmap is None:
          cmap = default_heatmap()
  
      # FIXME: convert cv_results_ to the old list of namedtuples format so
      # this still works on sklearn >= 0.20. I need to refactor the code
      # so it works with the new format
      gs = collections.namedtuple(
          "grid_scores_",
          ["parameters", "mean_validation_score", "std_test_score"],
      )
  
      grid_scores = [
          gs(p, m, s)
          for p, m, s in zip(
              cv_results_["params"],
              cv_results_["mean_test_score"],
              cv_results_["std_test_score"],
          )
      ]
  
      if isinstance(change, string_types) or len(change) == 1:
          return _grid_search_single(
              grid_scores, change, subset, kind, ax, sort
          )
      elif len(change) == 2:
          return _grid_search_double(
              grid_scores, change, subset, cmap, ax, sort
          )
      else:
          raise ValueError(
              "change must have length 1 or 2 or be a string"
          )
  
file_path: sklearn-evaluation/src/sklearn_evaluation/plot/grid_search.py
imports: import collections
  import matplotlib.pyplot
  import numpy
  from six import string_types
  from ..telemetry import SKLearnEvaluationLogger
  from sklearn_evaluation.plot.matplotlib.bar import BarShifter
  from ploomber_core.exceptions import modify_exceptions
  from ..util import _group_by, _get_params_value, _mapping_to_tuple_pairs, default_heatmap, _sorted_map_iter, _flatten_list
label_desc: Use image node_id 1 for calling a global function with example usage: grid_search(cv_results_, change, subset, kind, cmap, ax, sort) and returns: _grid_search_single, _grid_search_double