code: def test_unbiased() -> None:
      import pandas as pd
      from sklearn.model_selection import train_test_split
  
      X, y, q, w = tm.make_ltr(8192, 2, n_query_groups=6, max_rel=4)
      X, Xe, y, ye, q, qe = train_test_split(
          X, y, q, test_size=0.2, random_state=3
      )
      X = csr_matrix(X)
      Xe = csr_matrix(Xe)
      data = RelDataCV((X, y, q), (Xe, ye, qe), max_rel=4)
  
      train, _ = simulate_clicks(data)
      x, c, y, q = sort_ltr_samples(
          train.X, train.y, train.qid, train.click, train.pos
      )
      df: Optional[pd.DataFrame] = None
  
      class Position(xgboost.callback.TrainingCallback):
          def after_training(self, model) -> bool:
              nonlocal df
              config = json.loads(model.save_config())
              ti_plus = np.array(config["learner"]["objective"]["ti+"])
              tj_minus = np.array(config["learner"]["objective"]["tj-"])
              df = pd.DataFrame({"ti+": ti_plus, "tj-": tj_minus})
              return model
  
      ltr = xgboost.XGBRanker(
          n_estimators=8,
          tree_method="hist",
          lambdarank_unbiased=True,
          lambdarank_num_pair_per_sample=12,
          lambdarank_pair_method="topk",
          objective="rank:ndcg",
          callbacks=[Position()],
          boost_from_average=0,
      )
      ltr.fit(x, c, qid=q, eval_set=[(x, c)], eval_qid=[q])
  
      assert df is not None
      # normalized
      np.testing.assert_allclose(df["ti+"].iloc[0], 1.0)
      np.testing.assert_allclose(df["tj-"].iloc[0], 1.0)
      # less biased on low ranks.
      assert df["ti+"].iloc[-1] < df["ti+"].iloc[0]
  
imports: import itertools
  import json
  import os
  import shutil
  from typing import Optional
  import numpy
  import pytest
  from hypothesis import given, note, settings
  from scipy.sparse import csr_matrix
  import xgboost
  from xgboost import testing
  from xgboost.testing.data import RelDataCV, simulate_clicks, sort_ltr_samples
  from xgboost.testing.params import lambdarank_parameter_strategy
label_desc: Use image node_id 6 for calling a global function with example usage: test_unbiased() and returns: model