class_docstr: Handmade PCA to bypass sklearn dependency.
  
  Attributes:
      n_components:
          Number of principal components to keep.
      eps:
          Epsilon for numerical stability.
docstr: Fits PCA to data in X.
  
  Args:
      X:
          Datapoints stored in numpy array of size n x d.
  
  Returns:
      PCA object to transform datapoints.
docstr_tok: ["Fits","PCA","to","data","in","X.","Args",":","X",":","Datapoints","stored","in","numpy","array","of","size","n","x","d.","Returns",":","PCA","object","to","transform","datapoints","."]
code: def fit(self, X: NDArray[np.float32]) -> PCA:
      """Fits PCA to data in X.
  
      Args:
          X:
              Datapoints stored in numpy array of size n x d.
  
      Returns:
          PCA object to transform datapoints.
  
      """
      X = X.astype(np.float32)
      self.mean = X.mean(axis=0)
      assert self.mean is not None
      X = X - self.mean + self.eps
      cov = np.cov(X.T) / X.shape[0]
      v, w = np.linalg.eig(cov)
      idx = v.argsort()[::-1]
      v, w = v[idx], w[:, idx]
      self.w = w
      return self
  
file_path: lightly/lightly/utils/embeddings_2d.py
imports: from __future__ import annotations
  from typing import Optional, Tuple
  import numpy
  from numpy.typing import NDArray
label_desc: Use image node_id 2 for calling the PCA obj's underlying member method code with example usage: obj.fit(X) and returns: self