code: def main(args):
      custom_results = {}
      # Use our custom objective function
      booster_custom = xgb.train(
          {"num_class": kClasses, "disable_default_eval_metric": True},
          m,
          num_boost_round=kRounds,
          obj=softprob_obj,
          custom_metric=merror,
          evals_result=custom_results,
          evals=[(m, "train")],
      )
  
      predt_custom = predict(booster_custom, m)
  
      native_results = {}
      # Use the same objective function defined in XGBoost.
      booster_native = xgb.train(
          {
              "num_class": kClasses,
              "objective": "multi:softmax",
              "eval_metric": "merror",
          },
          m,
          num_boost_round=kRounds,
          evals_result=native_results,
          evals=[(m, "train")],
      )
      predt_native = booster_native.predict(m)
  
      # We are reimplementing the loss function in XGBoost, so it should
      # be the same for normal cases.
      assert np.all(predt_custom == predt_native)
      np.testing.assert_allclose(
          custom_results["train"]["PyMError"],
          native_results["train"]["merror"],
      )
  
      if args.plot != 0:
          plot_history(custom_results, native_results)
  
file_path: xgboost/demo/guide-python/custom_softmax.py
imports: import argparse
  import numpy
  from matplotlib import pyplot
  import xgboost
label_desc: Use image node_id 6 for calling a global function with example usage: main(args) without return types