class_docstr: A predictor that uses a QRX model for each of the steps in the forecast
  horizon.
  
  (In other words, there's a total of prediction_length many models being
  trained. In particular, this predictor does not learn a multivariate
  distribution.) The list of these models is saved under self.model_list.
code: def train(
      self,
      training_data,
      train_QRX_only_using_timestep: int = -1,  # If not -1 and self.method
      # == 'QRX', this will use only the train_QRX_only_using_timestep^th
      # timestep in the forecast horizon to create the partition.
  ):
      assert training_data
      if self.preprocess_object.use_feat_dynamic_real:
          assert (
              len(first(training_data)["feat_dynamic_real"][0])
              == len(first(training_data)["target"])
              + self.preprocess_object.forecast_horizon
          )
      if self.preprocess_object.use_past_feat_dynamic_real:
          assert len(
              first(training_data)["past_feat_dynamic_real"][0]
          ) == len(first(training_data)["target"])
      assert self.freq is not None
      if first(training_data)["start"].freq is not None:
          assert self.freq == next(iter(training_data))["start"].freq
      self.preprocess_object.preprocess_from_list(
          ts_list=list(training_data), change_internal_variables=True
      )
  
      feature_data = self.preprocess_object.feature_data
      target_data = np.array(self.preprocess_object.target_data)
  
      n_models = self.prediction_length
      logging.info(f"Length of forecast horizon: {n_models}")
      if self.method == "QuantileRegression":
          self.model_list = [
              QuantileReg(
                  params=self.model_params, quantiles=self.quantiles
              )
              for _ in range(n_models)
          ]
      elif self.method == "QRF":
          self.model_list = [
              QRF(params=self.model_params) for _ in range(n_models)
          ]
      elif self.method == "QRX":
          self.model_list = [
              QRX(
                  xgboost_params=self.model_params,
                  min_bin_size=self.min_bin_size,
                  model=self.model,
              )
              for _ in range(n_models)
          ]
  
      assert self.model_list is not None
      assert feature_data is not None
  
      if train_QRX_only_using_timestep != -1:
          assert (
              0
              <= train_QRX_only_using_timestep
              <= self.preprocess_object.forecast_horizon - 1
          )
          logger.info(
              "Training model for step no."
              f" {train_QRX_only_using_timestep} in the forecast horizon"
          )
          self.model_list[train_QRX_only_using_timestep].fit(
              feature_data,
              target_data[:, train_QRX_only_using_timestep],
          )
          self.model_list = [
              QRX(
                  xgboost_params=self.model_params,
                  min_bin_size=self.min_bin_size,
                  model=self.model_list[
                      train_QRX_only_using_timestep
                  ].model,
              )
              if i != train_QRX_only_using_timestep
              else self.model_list[i]
              for i in range(n_models)
          ]
          with concurrent.futures.ThreadPoolExecutor(
              max_workers=self.max_workers
          ) as executor:
              for n_step, model in enumerate(self.model_list):
                  current_target_data = target_data[:, n_step]
                  indices = ~np.isnan(current_target_data)
                  assert sum(indices), (
                      f"in timestamp {n_step} all values "
                      f"in train were nan"
                  )
                  if n_step != train_QRX_only_using_timestep:
                      logger.info(
                          f"Training model for step no. {n_step + 1} in the "
                          "forecast"
                          " horizon"
                      )
                      executor.submit(
                          model.fit,
                          list(compress(feature_data, indices)),
                          current_target_data[indices],
                          model_is_already_trained=True,
                      )
      else:
          target_data = np.array(target_data)
          with concurrent.futures.ThreadPoolExecutor(
              max_workers=self.max_workers
          ) as executor:
              for n_step, model in enumerate(self.model_list):
                  current_target_data = target_data[:, n_step]
                  indices = ~np.isnan(current_target_data)
                  assert sum(indices), (
                      f"in timestamp {n_step} all values "
                      f"in train were nan"
                  )
                  logger.info(
                      f"Training model for step no. {n_step + 1} in the"
                      " forecast horizon"
                  )
                  executor.submit(
                      model.fit,
                      list(compress(feature_data, indices)),
                      current_target_data[indices],
                  )
      return self
  
imports: import concurrent.futures
  import logging
  import pickle
  from itertools import chain
  from typing import Iterator, List, Optional, Any, Dict
  from toolz import first
  import numpy
  import pandas
  from pathlib import Path
  from itertools import compress
  from gluonts.core.component import validated
  from gluonts.dataset.common import Dataset
  from gluonts.dataset.util import forecast_start
  from gluonts.model.forecast import Forecast
  from gluonts.model.forecast_generator import log_once
  from gluonts.model.predictor import RepresentablePredictor
  from ._model import QRF, QRX, QuantileReg
  from ._preprocess import Cardinality, PreprocessOnlyLagFeatures
  from ._types import FeatureImportanceResult, ExplanationResult
label_desc: Use image node_id 2 for calling the TreePredictor obj's underlying member method code with example usage: obj.train(training_data, train_QRX_only_using_timestep) and returns: self