def fit(self, X, chunks):
    """Learn the RCA model.

    Parameters
    ----------
    data : (n x d) data matrix
        Each row corresponds to a single instance
    chunks : (n,) array of ints
        When ``chunks[i] == -1``, point i doesn't belong to any chunklet.
        When ``chunks[i] == j``, point i belongs to chunklet j.
    """
    X = self._prepare_inputs(X, ensure_min_samples=2)

    # PCA projection to remove noise and redundant information.
    if self.pca_comps is not None:
      pca = decomposition.PCA(n_components=self.pca_comps)
      X_t = pca.fit_transform(X)
      M_pca = pca.components_
    else:
      X_t = X - X.mean(axis=0)
      M_pca = None

    chunks = np.asanyarray(chunks, dtype=int)
    chunk_mask, chunked_data = _chunk_mean_centering(X_t, chunks)

    inner_cov = np.atleast_2d(np.cov(chunked_data, rowvar=0, bias=1))
    dim = self._check_dimension(np.linalg.matrix_rank(inner_cov), X_t)

    # Fisher Linear Discriminant projection
    if dim < X_t.shape[1]:
      total_cov = np.cov(X_t[chunk_mask], rowvar=0)
      tmp = np.linalg.lstsq(total_cov, inner_cov)[0]
      vals, vecs = np.linalg.eig(tmp)
      inds = np.argsort(vals)[:dim]
      A = vecs[:, inds]
      inner_cov = np.atleast_2d(A.T.dot(inner_cov).dot(A))
      self.transformer_ = _inv_sqrtm(inner_cov).dot(A.T)
    else:
      self.transformer_ = _inv_sqrtm(inner_cov).T

    if M_pca is not None:
        self.transformer_ = np.atleast_2d(self.transformer_.dot(M_pca))

    return self
Learn the RCA model.

    Parameters
    ----------
    data : (n x d) data matrix
        Each row corresponds to a single instance
    chunks : (n,) array of ints
        When ``chunks[i] == -1``, point i doesn't belong to any chunklet.
        When ``chunks[i] == j``, point i belongs to chunklet j.