code: def predict(self, ctx, test_data):
      if ctx.is_on_guest:
          if self.init_param.get("fit_intercept"):
              test_data["intercept"] = 1.0
          X = test_data.values.as_tensor()
          # logger.info(f"in predict, w: {self.w}")
          pred = torch.matmul(X, self.w.detach())
          h_pred = ctx.hosts.get("h_pred")[0]
          pred += h_pred
          pred = torch.sigmoid(pred)
  
          return pred
      else:
          X = test_data.values.as_tensor()
          output = torch.matmul(X, self.w)
          ctx.guest.put("h_pred", output)
  
imports: import logging
  import torch
  from fate.arch import Context, dataframe
  from fate.arch.dataframe import DataFrame
  from fate.arch.protocol.mpc.nn.sshe.lr_layer import SSHELogisticRegressionLayer, SSHELogisticRegressionLossLayer, SSHEOptimizerSGD
  from fate.ml.abc.module import Module, HeteroModule
  from fate.ml.utils import predict_tools
  from fate.ml.utils._convergence import converge_func_factory
  from fate.ml.utils._model_param import get_initialize_func
  from fate.ml.utils._model_param import serialize_param, deserialize_param
label_desc: Use image node_id 3 for calling the SSHELREstimator obj's underlying member method code with example usage: obj.predict(ctx, test_data) and returns: pred