class_docstr: Structured Covariance Estimator
  
  This estimator assumes observations can be predicted by multiple factors
      X = B @ F.T + U
  where `X` contains observations (row) of multiple variables (column),
  `F` contains factor exposures (column) for all variables (row),
  `B` is the regression coefficients matrix for all observations (row) on
  all factors (columns), and `U` is the residual matrix with shape like `X`.
  
  Therefore, the structured covariance can be estimated by
      cov(X.T) = F @ cov(B.T) @ F.T + diag(var(U))
  
  In finance domain, there are mainly three methods to design `F` [1][2]:
      - Statistical Risk Model (SRM): latent factor models major components
      - Fundamental Risk Model (FRM): human designed factors
      - Deep Risk Model (DRM): neural network designed factors (like a blend of SRM & DRM)
  
  In this implementation we use latent factor models to specify `F`.
  Specifically, the following two latent factor models are supported:
      - `pca`: Principal Component Analysis
      - `fa`: Factor Analysis
  
  Reference:
      [1] Fan, J., Liao, Y., & Liu, H. (2016). An overview of the estimation of large covariance and
          precision matrices. Econometrics Journal, 19(1), C1–C32. https://doi.org/10.1111/ectj.12061
      [2] Lin, H., Zhou, D., Liu, W., & Bian, J. (2021). Deep Risk Model: A Deep Learning Solution for
          Mining Latent Risk Factors to Improve Covariance Matrix Estimation. arXiv preprint arXiv:2107.05201.
docstr: covariance estimation implementation
  
  Args:
      X (np.ndarray): data matrix containing multiple variables (columns) and observations (rows).
      return_decomposed_components (bool): whether return decomposed components of the covariance matrix.
  
  Returns:
      tuple or np.ndarray: decomposed covariance matrix or covariance matrix.
docstr_tok: ["covariance","estimation","implementation","Args",":","X","(","np.ndarray",")",":","data","matrix","containing","multiple","variables","(","columns",")","and","observations","(","rows",")",".","return_decomposed_components","(","bool",")",":","whether","return","decomposed","components","of","the","covariance","matrix",".","Returns",":","tuple","or","np.ndarray",":","decomposed","covariance","matrix","or","covariance","matrix","."]
code: def _predict(
      self, X: np.ndarray, return_decomposed_components=False
  ) -> Union[np.ndarray, tuple]:
      """
      covariance estimation implementation
  
      Args:
          X (np.ndarray): data matrix containing multiple variables (columns) and observations (rows).
          return_decomposed_components (bool): whether return decomposed components of the covariance matrix.
  
      Returns:
          tuple or np.ndarray: decomposed covariance matrix or covariance matrix.
      """
  
      model = self.solver(self.num_factors, random_state=0).fit(X)
  
      F = model.components_.T  # variables x factors
      B = model.transform(X)  # observations x factors
      U = X - B @ F.T
      cov_b = np.cov(B.T)  # factors x factors
      var_u = np.var(U, axis=0)  # diagonal
  
      if return_decomposed_components:
          return F, cov_b, var_u
  
      cov_x = F @ cov_b @ F.T + np.diag(var_u)
  
      return cov_x
  
file_path: qlib/qlib/model/riskmodel/structured.py
imports: import numpy
  from typing import Union
  from sklearn.decomposition import PCA, FactorAnalysis
  from qlib.model.riskmodel import RiskModel
label_desc: Use image node_id 2 for calling the StructuredCovEstimator obj's underlying member method code with example usage: obj._predict(X, return_decomposed_components) and returns: cov_x, F,  cov_b,  var_u