docstr: Test learning rate scheduler, used by both CPU and GPU tests.
docstr_tok: ["Test","learning","rate","scheduler",",","used","by","both","CPU","and","GPU","tests","."]
code: def run_eta_decay(self, tree_method):
      """Test learning rate scheduler, used by both CPU and GPU tests."""
      scheduler = xgb.callback.LearningRateScheduler
  
      dtrain, dtest = tm.load_agaricus(__file__)
  
      watchlist = [(dtest, "eval"), (dtrain, "train")]
      num_round = 4
  
      # learning_rates as a list
      # init eta with 0 to check whether learning_rates work
      param = {
          "max_depth": 2,
          "eta": 0,
          "objective": "binary:logistic",
          "eval_metric": "error",
          "tree_method": tree_method,
      }
      evals_result = {}
      bst = xgb.train(
          param,
          dtrain,
          num_round,
          evals=watchlist,
          callbacks=[scheduler([0.8, 0.7, 0.6, 0.5])],
          evals_result=evals_result,
      )
      eval_errors_0 = list(map(float, evals_result["eval"]["error"]))
      assert isinstance(bst, xgb.core.Booster)
      # validation error should decrease, if eta > 0
      assert eval_errors_0[0] > eval_errors_0[-1]
  
      # init learning_rate with 0 to check whether learning_rates work
      param = {
          "max_depth": 2,
          "learning_rate": 0,
          "objective": "binary:logistic",
          "eval_metric": "error",
          "tree_method": tree_method,
      }
      evals_result = {}
  
      bst = xgb.train(
          param,
          dtrain,
          num_round,
          evals=watchlist,
          callbacks=[scheduler([0.8, 0.7, 0.6, 0.5])],
          evals_result=evals_result,
      )
      eval_errors_1 = list(map(float, evals_result["eval"]["error"]))
      assert isinstance(bst, xgb.core.Booster)
      # validation error should decrease, if learning_rate > 0
      assert eval_errors_1[0] > eval_errors_1[-1]
  
      # check if learning_rates override default value of eta/learning_rate
      param = {
          "max_depth": 2,
          "objective": "binary:logistic",
          "eval_metric": "error",
          "tree_method": tree_method,
      }
      evals_result = {}
      bst = xgb.train(
          param,
          dtrain,
          num_round,
          evals=watchlist,
          callbacks=[scheduler([0, 0, 0, 0])],
          evals_result=evals_result,
      )
      eval_errors_2 = list(map(float, evals_result["eval"]["error"]))
      assert isinstance(bst, xgb.core.Booster)
      # validation error should not decrease, if eta/learning_rate = 0
      assert eval_errors_2[0] == eval_errors_2[-1]
  
      # learning_rates as a customized decay function
      def eta_decay(ithround, num_boost_round=num_round):
          return num_boost_round / (ithround + 1)
  
      evals_result = {}
      bst = xgb.train(
          param,
          dtrain,
          num_round,
          evals=watchlist,
          callbacks=[scheduler(eta_decay)],
          evals_result=evals_result,
      )
      eval_errors_3 = list(map(float, evals_result["eval"]["error"]))
  
      assert isinstance(bst, xgb.core.Booster)
  
      assert eval_errors_3[0] == eval_errors_2[0]
  
      for i in range(1, len(eval_errors_0)):
          assert eval_errors_3[i] != eval_errors_2[i]
  
      xgb.cv(param, dtrain, num_round, callbacks=[scheduler(eta_decay)])
  
imports: import json
  import os
  import tempfile
  from typing import Union
  import pytest
  import xgboost
  from xgboost import testing
label_desc: Use image node_id 11 for calling the TestCallbacks obj's underlying member method code with example usage: obj.run_eta_decay(tree_method) and returns: unknown