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)
      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 = HeteroLinREstimatorArbiter(
              epochs=self.epochs,
              early_stop=self.early_stop,
              tol=self.tol,
              batch_size=self.batch_size,
              optimizer=optimizer,
              learning_rate_scheduler=lr_scheduler,
          )
          self.estimator = single_estimator
      self.estimator.fit_model(ctx, decryptor)
  
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 CoordinatedLinRModuleArbiter obj's underlying member method code with example usage: obj.fit(ctx) without return types