class_docstr: Hidden Markov Model with Gaussian mixture emissions.
  
  Attributes
  ----------
  monitor_ : ConvergenceMonitor
      Monitor object used to check the convergence of EM.
  
  startprob_ : array, shape (n_components, )
      Initial state occupation distribution.
  
  transmat_ : array, shape (n_components, n_components)
      Matrix of transition probabilities between states.
  
  weights_ : array, shape (n_components, n_mix)
      Mixture weights for each state.
  
  means_ : array, shape (n_components, n_mix, n_features)
      Mean parameters for each mixture component in each state.
  
  covars_ : array
      Covariance parameters for each mixture components in each state.
  
      The shape depends on :attr:`covariance_type`:
  
      * (n_components, n_mix)                          if "spherical",
      * (n_components, n_mix, n_features)              if "diag",
      * (n_components, n_mix, n_features, n_features)  if "full"
      * (n_components, n_features, n_features)         if "tied".
class_docstr_tok: ["Hidden","Markov","Model","with","Gaussian","mixture","emissions",".","Attributes","--","--","--","--","--","monitor_",":","ConvergenceMonitor","Monitor","object","used","to","check","the","convergence","of","EM",".","startprob_",":","array",",","shape","(","n_components",",",")","Initial","state","occupation","distribution",".","transmat_",":","array",",","shape","(","n_components",",","n_components",")","Matrix","of","transition","probabilities","between","states",".","weights_",":","array",",","shape","(","n_components",",","n_mix",")","Mixture","weights","for","each","state",".","means_",":","array",",","shape","(","n_components",",","n_mix",",","n_features",")","Mean","parameters","for","each","mixture","component","in","each","state",".","covars_",":","array","Covariance","parameters","for","each","mixture","components","in","each","state",".","The","shape","depends","on",":","attr",":","`","covariance_type","`",":","*","(","n_components",",","n_mix",")","if","``","spherical","''",",","*","(","n_components",",","n_mix",",","n_features",")","if","``","diag","''",",","*","(","n_components",",","n_mix",",","n_features",",","n_features",")","if","``","full","''","*","(","n_components",",","n_features",",","n_features",")","if","``","tied","''","."]
code: def _do_mstep(self, stats):
      super()._do_mstep(stats)
      nf = self.n_features
      nm = self.n_mix
  
      # Maximizing weights
      if "w" in self.params:
          alphas_minus_one = self.weights_prior - 1
          w_n = stats["post_mix_sum"] + alphas_minus_one
          w_d = (stats["post_sum"] + alphas_minus_one.sum(axis=1))[
              :, None
          ]
          self.weights_ = w_n / w_d
  
      # Maximizing means
      if "m" in self.params:
          m_n = stats["m_n"]
          m_d = stats["post_mix_sum"] + self.means_weight
          # If a componenent has zero weight, then replace nan (0/0?) means
          # by 0 (0/1).  The actual value is irrelevant as the component will
          # be unused.  This needs to be done before maximizing covariances
          # as nans would otherwise propagate to other components if
          # covariances are tied.
          m_d[(self.weights_ == 0) & (m_n == 0).all(axis=-1)] = 1
          self.means_ = m_n / m_d[:, :, None]
  
      # Maximizing covariances
      if "c" in self.params:
          lambdas, mus = self.means_weight, self.means_prior
          centered_means = self.means_ - mus
  
          def outer_f(x):  # Outer product over features.
              return x[..., :, None] * x[..., None, :]
  
          if self.covariance_type == "full":
              centered_means_dots = outer_f(centered_means)
  
              psis_t = np.transpose(
                  self.covars_prior, axes=(0, 1, 3, 2)
              )
              nus = self.covars_weight
  
              c_n = (
                  psis_t
                  + lambdas[:, :, None, None] * centered_means_dots
              )
              c_n += stats["c_n"]
              c_d = (stats["post_mix_sum"] + 1 + nus + nf + 1)[
                  :, :, None, None
              ]
  
          elif self.covariance_type == "diag":
              alphas = self.covars_prior
              betas = self.covars_weight
              centered_means2 = centered_means**2
  
              c_n = lambdas[:, :, None] * centered_means2 + 2 * betas
              c_n += stats["c_n"]
              c_d = (
                  stats["post_mix_sum"][:, :, None]
                  + 1
                  + 2 * (alphas + 1)
              )
  
          elif self.covariance_type == "spherical":
              centered_means_norm2 = (
                  np.einsum(  # Faster than (x**2).sum(-1)
                      "...i,...i", centered_means, centered_means
                  )
              )
  
              alphas = self.covars_prior
              betas = self.covars_weight
  
              c_n = lambdas * centered_means_norm2 + 2 * betas
              c_n += stats["c_n"]
              c_d = nf * (stats["post_mix_sum"] + 1) + 2 * (alphas + 1)
  
          elif self.covariance_type == "tied":
              centered_means_dots = outer_f(centered_means)
  
              psis_t = np.transpose(self.covars_prior, axes=(0, 2, 1))
              nus = self.covars_weight
  
              c_n = (
                  np.einsum(
                      "ij,ijkl->ikl", lambdas, centered_means_dots
                  )
                  + psis_t
              )
              c_n += stats["c_n"]
              c_d = (stats["post_sum"] + nm + nus + nf + 1)[
                  :, None, None
              ]
  
          self.covars_ = c_n / c_d
  
imports: import logging
  import numpy
  from scipy import linalg
  from sklearn import cluster
  from sklearn.utils import check_random_state
  from .None import _emissions, _utils
  from .base import BaseHMM
  from .utils import fill_covars, normalize
label_desc: Use image node_id 6 for calling the GMMHMM obj's underlying member method code with example usage: obj._do_mstep(stats) and returns: unknown