'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'

def fit(self, X, y=None):

    X = _check_X(X, self.n_components)
    self._check_initial_parameters(X)
    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    converge.    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
