class_docstr: Expectation-maximization algorithm.
  
  A class for performing Expectation-Maximization to fit a Gaussian Mixture
  Model (GMM) to data on a manifold. This method is only implemented for
  the hypersphere and the Poincare ball.
  
  Parameters
  ----------
  space : Manifold
      Equipped manifold.
  n_gaussians : int
      Number of Gaussian components in the mix.
  initialisation_method : basestring
      Optional, default: 'random'.
      Choice between initialization method for variances, means and weights.
  
      - 'random' : will select random uniformly train points as
        initial cluster centers.
      - 'kmeans' : will apply Riemannian kmeans to deduce
        variances and means that the EM will use initially.
  tol : float
      Optional, default: 1e-2.
      Convergence tolerance. If the difference of mean distance
      between two steps is lower than tol.
  max_iter : int
      Maximum number of iterations for the gradient descent.
      Optional, default: 100.
  
  Attributes
  ----------
  mixture_coefficients_ : array-like, shape=[n_gaussians,]
      Weights for each GMM component.
  variances_ : array-like, shape=[n_gaussians,]
      Variances for each GMM component.
  means_ : array-like, shape=[n_gaussian, _dimension]
      Barycentre of each component of the GMM.
  
  Example
  -------
  Available example on the Poincaré Ball manifold
  :mod:`examples.plot_expectation_maximization_ball`
class_docstr_tok: ["Expectation-maximization","algorithm",".","A","class","for","performing","Expectation-Maximization","to","fit","a","Gaussian","Mixture","Model","(","GMM",")","to","data","on","a","manifold",".","This","method","is","only","implemented","for","the","hypersphere","and","the","Poincare","ball",".","Parameters","--","--","--","--","--","space",":","Manifold","Equipped","manifold",".","n_gaussians",":","int","Number","of","Gaussian","components","in","the","mix",".","initialisation_method",":","basestring","Optional",",","default",":","'random","'",".","Choice","between","initialization","method","for","variances",",","means","and","weights",".","-","'random","'",":","will","select","random","uniformly","train","points","as","initial","cluster","centers",".","-","'kmeans","'",":","will","apply","Riemannian","kmeans","to","deduce","variances","and","means","that","the","EM","will","use","initially",".","tol",":","float","Optional",",","default",":","1e-2",".","Convergence","tolerance",".","If","the","difference","of","mean","distance","between","two","steps","is","lower","than","tol",".","max_iter",":","int","Maximum","number","of","iterations","for","the","gradient","descent",".","Optional",",","default",":","100",".","Attributes","--","--","--","--","--","mixture_coefficients_",":","array-like",",","shape=","[","n_gaussians",",","]","Weights","for","each","GMM","component",".","variances_",":","array-like",",","shape=","[","n_gaussians",",","]","Variances","for","each","GMM","component",".","means_",":","array-like",",","shape=","[","n_gaussian",",","_dimension","]","Barycentre","of","each","component","of","the","GMM",".","Example","--","--","--","-","Available","example","on","the","Poincar\u00e9","Ball","manifold",":","mod",":","`","examples.plot_expectation_maximization_ball","`"]
docstr: Update the posterior probabilities.
  
  Parameters
  ----------
  data : array-like, shape=[n_samples, n_features]
      Training data, where n_samples is the number of samples and
      n_features is the number of features.
docstr_tok: ["Update","the","posterior","probabilities",".","Parameters","--","--","--","--","--","data",":","array-like",",","shape=","[","n_samples",",","n_features","]","Training","data",",","where","n_samples","is","the","number","of","samples","and","n_features","is","the","number","of","features","."]
code: def _expectation(self, data):
      """Update the posterior probabilities.
  
      Parameters
      ----------
      data : array-like, shape=[n_samples, n_features]
          Training data, where n_samples is the number of samples and
          n_features is the number of features.
      """
      pdf = self._model.pdf(data)
  
      if gs.any(gs.isnan(pdf)):
          logging.warning(
              "EXPECTATION : Probability distribution function"
              "contain elements that are not numbers"
          )
  
      num_normalized_pdf = gs.einsum(
          "j,...j->...j", self.mixture_coefficients_, pdf
      )
      valid_pdf_condition = gs.amin(gs.sum(num_normalized_pdf, -1))
  
      if valid_pdf_condition <= PDF_TOL:
          num_normalized_pdf[
              gs.sum(num_normalized_pdf, -1) <= PDF_TOL
          ] = 1
  
      sum_pdf = gs.sum(num_normalized_pdf, -1)
      posterior_probabilities = gs.einsum(
          "...i,...->...i", num_normalized_pdf, 1 / sum_pdf
      )
  
      if gs.any(gs.mean(posterior_probabilities)) is None:
          logging.warning(
              "EXPECTATION : posterior probabilities "
              "contain elements that are not numbers."
          )
  
      if (
          1 - SUM_CHECK_PDF
          >= gs.mean(gs.sum(posterior_probabilities, 1))
          >= 1 + SUM_CHECK_PDF
      ):
          logging.warning(
              "EXPECTATION : posterior probabilities "
              "do not sum to 1."
          )
  
      if gs.any(gs.sum(posterior_probabilities, 0) < PDF_TOL):
          logging.warning(
              "EXPECTATION : Gaussian got no elements "
              "(precision error) reinitialize"
          )
          posterior_probabilities[
              posterior_probabilities == 0
          ] = PDF_TOL
  
      return posterior_probabilities
  
imports: import logging
  from sklearn.base import BaseEstimator, ClusterMixin
  import geomstats.backend
  from geomstats.learning._template import TransformerMixin
  from geomstats.learning.frechet_mean import FrechetMean, variance
  from geomstats.learning.kmeans import RiemannianKMeans
label_desc: Use image node_id 7 for calling the RiemannianEM obj's underlying member method code with example usage: obj._expectation(data) and returns: posterior_probabilities