code: def validate_categorical_input(score_func):
      """Decorator function to validate categorical scoring function input,
      and unifies the input type to pandas.Series.
      """
  
      @functools.wraps(score_func)
      def score_func_wrapper(
          y_true: Union[list, np.array, pd.Series, pd.DataFrame],
          y_pred: Union[list, np.array, pd.Series, pd.DataFrame],
          *args,
          **kwargs,
      ) -> np.array:
          actual = pd.DataFrame(y_true).reset_index(drop=True)
          pred = pd.DataFrame(y_pred).reset_index(drop=True)
          if actual.shape[-1] != 1 or pred.shape[-1] != 1:
              raise ValueError(
                  f"The input for scoring must be 1-D array, found {actual.shape} and {pred.shape}"
              )
          if actual.shape != pred.shape:
              raise ValueError(
                  f"The input lengths must be the same, found {actual.shape} and {pred.shape}"
              )
          actual.columns = [INPUT_COL_NAME]
          pred.columns = [INPUT_COL_NAME]
          # Drop rows with NA values in either actual or pred
          merged_df = pd.concat([actual, pred], axis=1).dropna()
          actual = merged_df.iloc[:, [0]]
          pred = merged_df.iloc[:, [1]]
          category_in_actual_set = set(actual[INPUT_COL_NAME])
          category_in_pred_set = set(pred[INPUT_COL_NAME])
          pred_minus_actual = category_in_pred_set.difference(
              category_in_actual_set
          )
          if pred_minus_actual:
              warnings.warn(
                  f"The following categories do not appear in y_true column, "
                  f"the recall may be undefined.\n{pred_minus_actual}"
              )
          actual_minus_pred = category_in_actual_set.difference(
              category_in_pred_set
          )
          if actual_minus_pred:
              warnings.warn(
                  f"The following categories do not appear in y_pred column, "
                  f"the precision may be undefined.\n{actual_minus_pred}"
              )
          # Adds a list wrapper below since `sklearn >= 1.1` restricts the input types and shapes.
          return score_func(
              y_true=list(
                  actual[INPUT_COL_NAME].reset_index(drop=True)
              ),
              y_pred=list(pred[INPUT_COL_NAME].reset_index(drop=True)),
              *args,
              **kwargs,
          )
  
      return score_func_wrapper
  
imports: import functools
  import warnings
  from typing import Optional
  from typing import Union
  import numpy
  import pandas
  from sklearn import metrics
  from greykite.detection.common.ad_evaluation_utils import compute_range_based_score
  from greykite.detection.common.ad_evaluation_utils import prepare_anomaly_ranges
label_desc: Use image node_id 1 for calling a global function with example usage: validate_categorical_input(score_func) and returns: score_func_wrapper, score_func