code: def test_classifier_pred_contrib(output, task, cluster):
      with Client(cluster) as client:
          X, y, w, _, dX, dy, dw, _ = _create_data(
              objective=task, output=output
          )
  
          params = {"n_estimators": 10, "num_leaves": 10}
  
          dask_classifier = lgb.DaskLGBMClassifier(
              client=client, time_out=5, tree_learner="data", **params
          )
          dask_classifier = dask_classifier.fit(
              dX, dy, sample_weight=dw
          )
          preds_with_contrib = dask_classifier.predict(
              dX, pred_contrib=True
          )
  
          local_classifier = lgb.LGBMClassifier(**params)
          local_classifier.fit(X, y, sample_weight=w)
          local_preds_with_contrib = local_classifier.predict(
              X, pred_contrib=True
          )
  
          # shape depends on whether it is binary or multiclass classification
          num_features = dask_classifier.n_features_
          num_classes = dask_classifier.n_classes_
          if num_classes == 2:
              expected_num_cols = num_features + 1
          else:
              expected_num_cols = (num_features + 1) * num_classes
  
          # in the special case of multi-class classification using scipy sparse matrices,
          # the output of `.predict(..., pred_contrib=True)` is a list of sparse matrices (one per class)
          #
          # since that case is so different than all other cases, check the relevant things here
          # and then return early
          if (
              output.startswith("scipy")
              and task == "multiclass-classification"
          ):
              if output == "scipy_csr_matrix":
                  expected_type = csr_matrix
              elif output == "scipy_csc_matrix":
                  expected_type = csc_matrix
              else:
                  raise ValueError(
                      f"Unrecognized output type: {output}"
                  )
              assert isinstance(preds_with_contrib, list)
              assert all(
                  isinstance(arr, da.Array)
                  for arr in preds_with_contrib
              )
              assert all(
                  isinstance(arr._meta, expected_type)
                  for arr in preds_with_contrib
              )
              assert len(preds_with_contrib) == num_classes
              assert len(preds_with_contrib) == len(
                  local_preds_with_contrib
              )
              for i in range(num_classes):
                  computed_preds = preds_with_contrib[i].compute()
                  assert isinstance(computed_preds, expected_type)
                  assert computed_preds.shape[1] == num_classes
                  assert (
                      computed_preds.shape
                      == local_preds_with_contrib[i].shape
                  )
                  assert len(np.unique(computed_preds[:, -1])) == 1
                  # raw scores will probably be different, but at least check that all predicted classes are the same
                  pred_classes = np.argmax(
                      computed_preds.toarray(), axis=1
                  )
                  local_pred_classes = np.argmax(
                      local_preds_with_contrib[i].toarray(), axis=1
                  )
                  np.testing.assert_array_equal(
                      pred_classes, local_pred_classes
                  )
              return
  
          preds_with_contrib = preds_with_contrib.compute()
          if output.startswith("scipy"):
              preds_with_contrib = preds_with_contrib.toarray()
  
          # be sure LightGBM actually used at least one categorical column,
          # and that it was correctly treated as a categorical feature
          if output == "dataframe-with-categorical":
              cat_cols = [
                  col
                  for col in dX.columns
                  if dX.dtypes[col].name == "category"
              ]
              tree_df = dask_classifier.booster_.trees_to_dataframe()
              node_uses_cat_col = tree_df["split_feature"].isin(
                  cat_cols
              )
              assert node_uses_cat_col.sum() > 0
              assert (
                  tree_df.loc[
                      node_uses_cat_col, "decision_type"
                  ].unique()[0]
                  == "=="
              )
  
          # * shape depends on whether it is binary or multiclass classification
          # * matrix for binary classification is of the form [feature_contrib, base_value],
          #   for multi-class it's [feat_contrib_class1, base_value_class1, feat_contrib_class2, base_value_class2, etc.]
          # * contrib outputs for distributed training are different than from local training, so we can just test
          #   that the output has the right shape and base values are in the right position
          assert preds_with_contrib.shape[1] == expected_num_cols
          assert (
              preds_with_contrib.shape == local_preds_with_contrib.shape
          )
  
          if num_classes == 2:
              assert (
                  len(np.unique(preds_with_contrib[:, num_features]))
                  == 1
              )
          else:
              for i in range(num_classes):
                  base_value_col = num_features * (i + 1) + i
                  assert len(
                      np.unique(preds_with_contrib[:, base_value_col])
                      == 1
                  )
  
imports: import inspect
  import random
  import socket
  from itertools import groupby
  from os import getenv
  from platform import machine
  from sys import platform
  from urllib.parse import urlparse
  import pytest
  from sklearn.metrics import accuracy_score, r2_score
  import lightgbm
  from .utils import sklearn_multiclass_custom_objective
  import dask.array
  import dask.dataframe
  import numpy
  import pandas
  import sklearn.utils.estimator_checks
  from dask.array.utils import assert_eq
  from dask.distributed import Client, LocalCluster, default_client, wait
  from scipy.sparse import csc_matrix, csr_matrix
  from scipy.stats import spearmanr
  from sklearn.datasets import make_blobs, make_regression
  from .utils import make_ranking, pickle_obj, unpickle_obj
label_desc: Use image node_id 14 for calling a global function with example usage: test_classifier_pred_contrib(output, task, cluster) without return types