code: def fit(self, ctx: Context) -> None:
      kit = ctx.cipher.phe.setup()
      encryptor = kit.get_tensor_encryptor()
      decryptor = kit.get_tensor_decryptor()
      ctx.hosts("encryptor").put(encryptor)
      ctx.guest("encryptor").put(encryptor)
      label_count = ctx.guest("label_count").get()
      if label_count > 2 or self.ovr:
          self.ovr = True
          warm_start = True
          if self.estimator is None:
              self.estimator = {}
              warm_start = False
          for i, class_ctx in ctx.sub_ctx("class").ctxs_range(
              label_count
          ):
              if not warm_start:
                  optimizer = Optimizer(
                      self.optimizer_param["method"],
                      self.optimizer_param["penalty"],
                      self.optimizer_param["alpha"],
                      self.optimizer_param["optimizer_params"],
                  )
                  lr_scheduler = LRScheduler(
                      self.learning_rate_param["method"],
                      self.learning_rate_param["scheduler_params"],
                  )
                  single_estimator = CoordinatedLREstimatorArbiter(
                      epochs=self.epochs,
                      early_stop=self.early_stop,
                      tol=self.tol,
                      batch_size=self.batch_size,
                      optimizer=optimizer,
                      learning_rate_scheduler=lr_scheduler,
                  )
              else:
                  logger.info(
                      "estimator is not none, will train with warm start"
                  )
                  single_estimator = self.estimator[i]
                  single_estimator.epochs = self.epochs
                  single_estimator.batch_size = self.batch_size
              single_estimator.fit_single_model(class_ctx, decryptor)
              self.estimator[i] = single_estimator
      else:
          if self.estimator is None:
              optimizer = Optimizer(
                  self.optimizer_param["method"],
                  self.optimizer_param["penalty"],
                  self.optimizer_param["alpha"],
                  self.optimizer_param["optimizer_params"],
              )
              lr_scheduler = LRScheduler(
                  self.learning_rate_param["method"],
                  self.learning_rate_param["scheduler_params"],
              )
              single_estimator = CoordinatedLREstimatorArbiter(
                  epochs=self.epochs,
                  early_stop=self.early_stop,
                  tol=self.tol,
                  batch_size=self.batch_size,
                  optimizer=optimizer,
                  learning_rate_scheduler=lr_scheduler,
              )
          else:
              logger.info(
                  "estimator is not none, will train with warm start"
              )
              single_estimator = self.estimator
              single_estimator.epochs = self.epochs
              single_estimator.batch_size = self.batch_size
          single_estimator.fit_single_model(ctx, decryptor)
          self.estimator = single_estimator
  
imports: import logging
  import torch
  from fate.arch import Context
  from fate.arch.dataframe import DataLoader
  from fate.ml.abc.module import HeteroModule
  from fate.ml.utils._convergence import converge_func_factory
  from fate.ml.utils._optimizer import LRScheduler, Optimizer, separate
label_desc: Use image node_id 4 for calling the CoordinatedLRModuleArbiter obj's underlying member method code with example usage: obj.fit(ctx) without return types