class_docstr: Base class for mixture models.
  
  This abstract class specifies an interface for all mixture classes and
  provides basic common methods for mixture models.
docstr: Estimate model parameters with the EM algorithm.
  
  The method fit the model `n_init` times and set the parameters with
  which the model has the largest likelihood or lower bound. Within each
  trial, the method iterates between E-step and M-step for `max_iter`
  times until the change of likelihood or lower bound is less than
  `tol`, otherwise, a `ConvergenceWarning` is raised.
  
  Parameters
  ----------
  X : array-like, shape (n_samples, n_features)
      List of n_features-dimensional data points. Each row
      corresponds to a single data point.
  
  Returns
  -------
  self
code: def fit(self, X, y=None):
      """Estimate model parameters with the EM algorithm.
  
      The method fit the model `n_init` times and set the parameters with
      which the model has the largest likelihood or lower bound. Within each
      trial, the method iterates between E-step and M-step for `max_iter`
      times until the change of likelihood or lower bound is less than
      `tol`, otherwise, a `ConvergenceWarning` is raised.
  
      Parameters
      ----------
      X : array-like, shape (n_samples, n_features)
          List of n_features-dimensional data points. Each row
          corresponds to a single data point.
  
      Returns
      -------
      self
      """
      X = _check_X(X, self.n_components)
      self._check_initial_parameters(X)
  
      # if we enable warm_start, we will have a unique initialisation
      do_init = not (self.warm_start and hasattr(self, "converged_"))
      n_init = self.n_init if do_init else 1
  
      max_lower_bound = -np.infty
      self.converged_ = False
  
      random_state = check_random_state(self.random_state)
  
      n_samples, _ = X.shape
      for init in range(n_init):
          self._print_verbose_msg_init_beg(init)
  
          if do_init:
              self._initialize_parameters(X, random_state)
              self.lower_bound_ = -np.infty
  
          for n_iter in range(self.max_iter):
              prev_lower_bound = self.lower_bound_
  
              log_prob_norm, log_resp = self._e_step(X)
              self._m_step(X, log_resp)
              self.lower_bound_ = self._compute_lower_bound(
                  log_resp, log_prob_norm
              )
  
              change = self.lower_bound_ - prev_lower_bound
              self._print_verbose_msg_iter_end(n_iter, change)
  
              if abs(change) < self.tol:
                  self.converged_ = True
                  break
  
          self._print_verbose_msg_init_end(self.lower_bound_)
  
          if self.lower_bound_ > max_lower_bound:
              max_lower_bound = self.lower_bound_
              best_params = self._get_parameters()
              best_n_iter = n_iter
  
      if not self.converged_:
          warnings.warn(
              "Initialization %d did not converged. "
              "Try different init parameters, "
              "or increase max_iter, tol "
              "or check for degenerate data." % (init + 1),
              ConvergenceWarning,
          )
  
      self._set_parameters(best_params)
      self.n_iter_ = best_n_iter
  
      return self
  
imports: from __future__ import print_function
  import warnings
  from abc import ABCMeta, abstractmethod
  from time import time
  import numpy
  from ..None import cluster
  from ..base import BaseEstimator
  from ..base import DensityMixin
  from ..externals import six
  from ..exceptions import ConvergenceWarning
  from ..utils import check_array, check_random_state
  from ..utils.extmath import logsumexp
label_desc: Use image node_id 6 for calling the BaseMixture obj's underlying member method code with example usage: obj.fit(X, y) and returns: self