class_docstr: Base class of SEM estimators. All the estimators inherit this class.
class_docstr_tok: ["Base","class","of","SEM","estimators",".","All","the","estimators","inherit","this","class","."]
docstr: Estimate the parameters of the model from the data.
  
  Parameters
  ----------
  data: pandas DataFrame or pgmpy.data.Data instance
      The data from which to estimate the parameters of the model.
  
  method: str ("ml"|"uls"|"gls"|"2sls")
      The fitting function to use.
      ML : Maximum Likelihood
      ULS: Unweighted Least Squares
      GLS: Generalized Least Squares
      2sls: 2-SLS estimator
  
  init_values: str or dict
      Options for str: random | std | iv
      dict: dictionary with keys `B` and `zeta`.
  
  **kwargs: dict
      Extra parameters required in case of some estimators.
      GLS:
          W: np.array (n x n) where n is the number of observe variables.
      2sls:
          x:
          y:
  
  Returns
  -------
      pgmpy.model.SEM instance: Instance of the model with estimated parameters
  
  References
  ----------
  .. [1] Bollen, K. A. (2010). Structural equations with latent variables. New York: Wiley.
docstr_tok: ["Estimate","the","parameters","of","the","model","from","the","data",".","Parameters","--","--","--","--","--","data",":","pandas","DataFrame","or","pgmpy.data.Data","instance","The","data","from","which","to","estimate","the","parameters","of","the","model",".","method",":","str","(","``","ml","''","|","''","uls","''","|","''","gls","''","|","''","2sls","''",")","The","fitting","function","to","use",".","ML",":","Maximum","Likelihood","ULS",":","Unweighted","Least","Squares","GLS",":","Generalized","Least","Squares","2sls",":","2-SLS","estimator","init_values",":","str","or","dict","Options","for","str",":","random","|","std","|","iv","dict",":","dictionary","with","keys","`","B","`","and","`","zeta","`",".","*","*","kwargs",":","dict","Extra","parameters","required","in","case","of","some","estimators",".","GLS",":","W",":","np.array","(","n","x","n",")","where","n","is","the","number","of","observe","variables",".","2sls",":","x",":","y",":","Returns","--","--","--","-","pgmpy.model.SEM","instance",":","Instance","of","the","model","with","estimated","parameters","References","--","--","--","--","--","..","[","1","]","Bollen",",","K.","A",".","(","2010",")",".","Structural","equations","with","latent","variables",".","New","York",":","Wiley","."]
code: def fit(
      self,
      data,
      method,
      opt="adam",
      init_values="random",
      exit_delta=1e-4,
      max_iter=1000,
      **kwargs,
  ):
      """
      Estimate the parameters of the model from the data.
  
      Parameters
      ----------
      data: pandas DataFrame or pgmpy.data.Data instance
          The data from which to estimate the parameters of the model.
  
      method: str ("ml"|"uls"|"gls"|"2sls")
          The fitting function to use.
          ML : Maximum Likelihood
          ULS: Unweighted Least Squares
          GLS: Generalized Least Squares
          2sls: 2-SLS estimator
  
      init_values: str or dict
          Options for str: random | std | iv
          dict: dictionary with keys `B` and `zeta`.
  
      **kwargs: dict
          Extra parameters required in case of some estimators.
          GLS:
              W: np.array (n x n) where n is the number of observe variables.
          2sls:
              x:
              y:
  
      Returns
      -------
          pgmpy.model.SEM instance: Instance of the model with estimated parameters
  
      References
      ----------
      .. [1] Bollen, K. A. (2010). Structural equations with latent variables. New York: Wiley.
      """
      # Check if given arguments are valid
      if not isinstance(data, pd.DataFrame):
          raise ValueError(
              f"data must be a pandas DataFrame. Got type: {type(data)}"
          )
  
      if not sorted(data.columns) == sorted(self.model.y):
          raise ValueError(
              f"The column names data do not match the variables in the model. Expected: {sorted(self.model.observed)}. Got: {sorted(data.columns)}"
          )
  
      # Initialize the values of parameters as tensors.
      if isinstance(init_values, dict):
          B_init, zeta_init = init_values["B"], init_values["zeta"]
      else:
          B_init, zeta_init = self.get_init_values(
              data, method=init_values.lower()
          )
      B = torch.tensor(
          B_init,
          device=config.DEVICE,
          dtype=config.DTYPE,
          requires_grad=True,
      )
      zeta = torch.tensor(
          zeta_init,
          device=config.DEVICE,
          dtype=config.DTYPE,
          requires_grad=True,
      )
  
      # Compute the covariance of the data
      variable_order = self.model.y
      S = (
          data.cov()
          .reindex(variable_order, axis=1)
          .reindex(variable_order, axis=0)
      )
      S = torch.tensor(
          S.values,
          device=config.DEVICE,
          dtype=config.DTYPE,
          requires_grad=False,
      )
  
      # Optimize the parameters
      if method.lower() == "ml":
          params = optimize(
              self.ml_loss,
              params={"B": B, "zeta": zeta},
              loss_args={"S": S},
              opt=opt,
              exit_delta=exit_delta,
              max_iter=max_iter,
          )
  
      elif method.lower() == "uls":
          params = optimize(
              self.uls_loss,
              params={"B": B, "zeta": zeta},
              loss_args={"S": S},
              opt=opt,
              exit_delta=exit_delta,
              max_iter=max_iter,
          )
  
      elif method.lower() == "gls":
          W = torch.tensor(
              kwargs["W"],
              device=config.DEVICE,
              dtype=config.DTYPE,
              requires_grad=False,
          )
          params = optimize(
              self.gls_loss,
              params={"B": B, "zeta": zeta},
              loss_args={"S": S, "W": W},
              opt=opt,
              exit_delta=exit_delta,
              max_iter=max_iter,
          )
  
      elif method.lower() == "2sls" or method.lower() == "2-sls":
          raise NotImplementedError("2-SLS is not implemented yet")
  
      B = params["B"] * self.B_mask + self.B_fixed_mask
      zeta = params["zeta"] * self.zeta_mask + self.zeta_fixed_mask
  
      # Compute goodness of fit statistics.
      N = data.shape[0]
      sample_cov = S.detach().numpy()
      sigma_hat = self._get_implied_cov(B, zeta).detach().numpy()
      residual = sample_cov - sigma_hat
  
      norm_residual = np.zeros(residual.shape)
      for i in range(norm_residual.shape[0]):
          for j in range(norm_residual.shape[1]):
              norm_residual[i, j] = (
                  sample_cov[i, j] - sigma_hat[i, j]
              ) / np.sqrt(
                  (
                      (sigma_hat[i, i] * sigma_hat[j, j])
                      + (sigma_hat[i, j] ** 2)
                  )
                  / N
              )
  
      # Compute chi-square value.
      likelihood_ratio = -(N - 1) * (
          np.log(np.linalg.det(sigma_hat))
          + (np.linalg.inv(sigma_hat) @ S).trace()
          - np.log(np.linalg.det(S))
          - S.shape[0]
      )
      if method.lower() == "ml":
          error = self.ml_loss(params, loss_args={"S": S})
      elif method.lower() == "uls":
          error = self.uls_loss(params, loss_args={"S": S})
      elif method.lower() == "gls":
          error = self.gls_loss(params, loss_args={"S": S, "W": W})
      chi_square = likelihood_ratio / error.detach().numpy()
  
      free_params = self.B_mask.sum()
      dof = ((S.shape[0] * (S.shape[0] + 1)) / 2) - free_params
  
      summary = {
          "Sample Size": N,
          "Sample Covariance": sample_cov,
          "Model Implied Covariance": sigma_hat,
          "Residual": residual,
          "Normalized Residual": norm_residual,
          "chi_square": chi_square,
          "dof": dof,
      }
  
      # Update the model with the learned params
      self.model.set_params(
          B=params["B"].detach().numpy(),
          zeta=params["B"].detach().numpy(),
      )
      return summary
  
file_path: pgmpy/pgmpy/estimators/SEMEstimator.py
imports: import numpy
  import pandas
  import statsmodels.api
  import torch
  from pgmpy import config
  from pgmpy.models import SEM, SEMAlg, SEMGraph
  from pgmpy.utils import optimize, pinverse
label_desc: Use image node_id 7 for calling the SEMEstimator obj's underlying member method code with example usage: obj.fit(data, method, opt, init_values, exit_delta, max_iter) and returns: summary