<commit_before>/**
 * @author <NAME> (<EMAIL>)
 * @file mog_em.h
 *
 * Defines a Gaussian Mixture model and
 * estimates the parameters of the model
 */
#ifndef __MLPACK_METHODS_MOG_MOG_EM_HPP
#define __MLPACK_METHODS_MOG_MOG_EM_HPP

#include <mlpack/core.hpp>

// This is the default fitting method class.
#include "em_fit.hpp"

namespace mlpack {
namespace gmm /** Gaussian Mixture Models. */ {

/**
 * A Gaussian Mixture Model (GMM). This class uses maximum likelihood loss
 * functions to estimate the parameters of the GMM on a given dataset via the
 * given fitting mechanism, defined by the FittingType template parameter.  The
 * GMM can be trained using normal data, or data with probabilities of being
 * from this GMM (see GMM::Estimate() for more information).
 *
 * The FittingType template class must provide a way for the GMM to train on
 * data.  It must provide the following two functions:
 *
 * @code
 * void Estimate(const arma::mat& observations,
 *               std::vector<arma::vec>& means,
 *               std::vector<arma::mat>& covariances,
 *               arma::vec& weights);
 *
 * void Estimate(const arma::mat& observations,
 *               const arma::vec& probabilities,
 *               std::vector<arma::vec>& means,
 *               std::vector<arma::mat>& covariances,
 *               arma::vec& weights);
 * @endcode
 *
 * These functions should produce a trained GMM from the given observations and
 * probabilities.  These may modify the size of the model (by increasing the
 * size of the mean and covariance vectors as well as the weight vectors), but
 * the method should expect that these vectors are already set to the size of
 * the GMM as specified in the constructor.
 *
 * For a sample implementation, see the EMFit class; this class uses the EM
 * algorithm to train a GMM, and is the default fitting type.
 *
 * The GMM, once trained, can be used to generate random points from the
 * distribution and estimate the probability of points being from the
 * distribution.  The parameters of the GMM can be obtained through the
 * accessors and mutators.
 *
 * Example use:
 *
 * @code
 * // Set up a mixture of 5 gaussians in a 4-dimensional space (uses the default
 * // EM fitting mechanism).
 * GMM<> g(5, 4);
 *
 * // Train the GMM given the data observations.
 * g.Estimate(data);
 *
 * // Get the probability of 'observation' being observed from this GMM.
 * double probability = g.Probability(observation);
 *
 * // Get a random observation from the GMM.
 * arma::vec observation = g.Random();
 * @endcode
 */
template<typename FittingType = EMFit<> >
class GMM
{
 private:
  //! The number of Gaussians in the model.
  size_t gaussians;
  //! The dimensionality of the model.
  size_t dimensionality;
  //! Vector of means; one for each Gaussian.
  std::vector<arma::vec> means;
  //! Vector of covariances; one for each Gaussian.
  std::vector<arma::mat> covariances;
  //! Vector of a priori weights for each Gaussian.
  arma::vec weights;

 public:
  /**
   * Create an empty Gaussian Mixture Model, with zero gaussians.
   */
  GMM() :
      gaussians(0),
      dimensionality(0),
      localFitter(FittingType()),
      fitter(localFitter)
  {
    // Warn the user.  They probably don't want to do this.  If this constructor
    // is being used (because it is required by some template classes), the user
    // should know that it is potentially dangerous.
    Log::Debug << "GMM::GMM(): no parameters given; Estimate() may fail "
        << "unless parameters are set." << std::endl;
  }

  /**
   * Create a GMM with the given number of Gaussians, each of which have the
   * specified dimensionality.
   *
   * @param gaussians Number of Gaussians in this GMM.
   * @param dimensionality Dimensionality of each Gaussian.
   */
  GMM(const size_t gaussians, const size_t dimensionality) :
      gaussians(gaussians),
      dimensionality(dimensionality),
      means(gaussians, arma::vec(dimensionality)),
      covariances(gaussians, arma::mat(dimensionality, dimensionality)),
      weights(gaussians),
      localFitter(FittingType()),
      fitter(localFitter) { /* Nothing to do. */ }

  /**
   * Create a GMM with the given number of Gaussians, each of which have the
   * specified dimensionality.  Also, pass in an initialized FittingType class;
   * this is useful in cases where the FittingType class needs to store some
   * state.
   *
   * @param gaussians Number of Gaussians in this GMM.
   * @param dimensionality Dimensionality of each Gaussian.
   * @param fitter Initialized fitting mechanism.
   */
  GMM(const size_t gaussians,
      const size_t dimensionality,
      FittingType& fitter) :
      gaussians(gaussians),
      dimensionality(dimensionality),
      means(gaussians, arma::vec(dimensionality)),
      covariances(gaussians, arma::mat(dimensionality, dimensionality)),
      weights(gaussians),
      fitter(fitter) { /* Nothing to do. */ }

  /**
   * Create a GMM with the given means, covariances, and weights.
   *
   * @param means Means of the model.
   * @param covariances Covariances of the model.
   * @param weights Weights of the model.
   */
  GMM(const std::vector<arma::vec>& means,
      const std::vector<arma::mat>& covariances,
      const arma::vec& weights) :
      gaussians(means.size()),
      dimensionality((!means.empty()) ? means[0].n_elem : 0),
      means(means),
      covariances(covariances),
      weights(weights) { /* nothing to do */ }

  /**
   * Copy constructor for GMMs which use different fitting types.
   */
  template<typename OtherFittingType>
  GMM(const GMM<OtherFittingType>& other);

  /**
   * Copy constructor for GMMs using the same fitting type.  This also copies
   * the fitter.
   */
  GMM(const GMM& other);

  /**
   * Copy operator for GMMs which use different fitting types.
   */
  template<typename OtherFittingType>
  GMM& operator=(const GMM<OtherFittingType>& other);

  /**
   * Copy operator for GMMs which use the same fitting type.  This also copies<commit_msg>Take care of FittingType when we are passing in means, covariances, and weights to build a GMM.<commit_after>/**
 * @author <NAME> (<EMAIL>)
 * @file mog_em.h
 *
 * Defines a Gaussian Mixture model and
 * estimates the parameters of the model
 */
#ifndef __MLPACK_METHODS_MOG_MOG_EM_HPP
#define __MLPACK_METHODS_MOG_MOG_EM_HPP

#include <mlpack/core.hpp>

// This is the default fitting method class.
#include "em_fit.hpp"

namespace mlpack {
namespace gmm /** Gaussian Mixture Models. */ {

/**
 * A Gaussian Mixture Model (GMM). This class uses maximum likelihood loss
 * functions to estimate the parameters of the GMM on a given dataset via the
 * given fitting mechanism, defined by the FittingType template parameter.  The
 * GMM can be trained using normal data, or data with probabilities of being
 * from this GMM (see GMM::Estimate() for more information).
 *
 * The FittingType template class must provide a way for the GMM to train on
 * data.  It must provide the following two functions:
 *
 * @code
 * void Estimate(const arma::mat& observations,
 *               std::vector<arma::vec>& means,
 *               std::vector<arma::mat>& covariances,
 *               arma::vec& weights);
 *
 * void Estimate(const arma::mat& observations,
 *               const arma::vec& probabilities,
 *               std::vector<arma::vec>& means,
 *               std::vector<arma::mat>& covariances,
 *               arma::vec& weights);
 * @endcode
 *
 * These functions should produce a trained GMM from the given observations and
 * probabilities.  These may modify the size of the model (by increasing the
 * size of the mean and covariance vectors as well as the weight vectors), but
 * the method should expect that these vectors are already set to the size of
 * the GMM as specified in the constructor.
 *
 * For a sample implementation, see the EMFit class; this class uses the EM
 * algorithm to train a GMM, and is the default fitting type.
 *
 * The GMM, once trained, can be used to generate random points from the
 * distribution and estimate the probability of points being from the
 * distribution.  The parameters of the GMM can be obtained through the
 * accessors and mutators.
 *
 * Example use:
 *
 * @code
 * // Set up a mixture of 5 gaussians in a 4-dimensional space (uses the default
 * // EM fitting mechanism).
 * GMM<> g(5, 4);
 *
 * // Train the GMM given the data observations.
 * g.Estimate(data);
 *
 * // Get the probability of 'observation' being observed from this GMM.
 * double probability = g.Probability(observation);
 *
 * // Get a random observation from the GMM.
 * arma::vec observation = g.Random();
 * @endcode
 */
template<typename FittingType = EMFit<> >
class GMM
{
 private:
  //! The number of Gaussians in the model.
  size_t gaussians;
  //! The dimensionality of the model.
  size_t dimensionality;
  //! Vector of means; one for each Gaussian.
  std::vector<arma::vec> means;
  //! Vector of covariances; one for each Gaussian.
  std::vector<arma::mat> covariances;
  //! Vector of a priori weights for each Gaussian.
  arma::vec weights;

 public:
  /**
   * Create an empty Gaussian Mixture Model, with zero gaussians.
   */
  GMM() :
      gaussians(0),
      dimensionality(0),
      localFitter(FittingType()),
      fitter(localFitter)
  {
    // Warn the user.  They probably don't want to do this.  If this constructor
    // is being used (because it is required by some template classes), the user
    // should know that it is potentially dangerous.
    Log::Debug << "GMM::GMM(): no parameters given; Estimate() may fail "
        << "unless parameters are set." << std::endl;
  }

  /**
   * Create a GMM with the given number of Gaussians, each of which have the
   * specified dimensionality.
   *
   * @param gaussians Number of Gaussians in this GMM.
   * @param dimensionality Dimensionality of each Gaussian.
   */
  GMM(const size_t gaussians, const size_t dimensionality) :
      gaussians(gaussians),
      dimensionality(dimensionality),
      means(gaussians, arma::vec(dimensionality)),
      covariances(gaussians, arma::mat(dimensionality, dimensionality)),
      weights(gaussians),
      localFitter(FittingType()),
      fitter(localFitter) { /* Nothing to do. */ }

  /**
   * Create a GMM with the given number of Gaussians, each of which have the
   * specified dimensionality.  Also, pass in an initialized FittingType class;
   * this is useful in cases where the FittingType class needs to store some
   * state.
   *
   * @param gaussians Number of Gaussians in this GMM.
   * @param dimensionality Dimensionality of each Gaussian.
   * @param fitter Initialized fitting mechanism.
   */
  GMM(const size_t gaussians,
      const size_t dimensionality,
      FittingType& fitter) :
      gaussians(gaussians),
      dimensionality(dimensionality),
      means(gaussians, arma::vec(dimensionality)),
      covariances(gaussians, arma::mat(dimensionality, dimensionality)),
      weights(gaussians),
      fitter(fitter) { /* Nothing to do. */ }

  /**
   * Create a GMM with the given means, covariances, and weights.
   *
   * @param means Means of the model.
   * @param covariances Covariances of the model.
   * @param weights Weights of the model.
   */
  GMM(const std::vector<arma::vec>& means,
      const std::vector<arma::mat>& covariances,
      const arma::vec& weights) :
      gaussians(means.size()),
      dimensionality((!means.empty()) ? means[0].n_elem : 0),
      means(means),
      covariances(covariances),
      weights(weights),
      localFitter(FittingType()),
      fitter(localFitter) { /* Nothing to do. */ }

  /**
   * Create a GMM with the given means, covariances, and weights, and use the
   * given initialized FittingType class.  This is useful in cases where the
   * FittingType class needs to store some state.
   *
   * @param means Means of the model.
   * @param covariances Covariances of the model.
   * @param weights Weights of the model.
   */
  GMM(const std::vector<arma::vec>& means,
      const std::vector<arma::mat>& covariances,
      const arma::vec& weights,
      FittingType& fitter) :
      gaussians(means.size()),
      dimensionality((!means.empty()) ? means[0].n_elem : 0),
      means(means),
      covariances(covariances),
      weights(weights),
      fitter(fitter) { /* Nothing to do. */ }

  /**
   * Copy constructor for GMMs which use different fitting types.
   */
  template<typename OtherFittingType>
  GMM(const GMM<OtherFittingType>& other);

  /**
   * Copy constructor for GMMs using the same fitting type.  This also copies
   * the fitter.
   */
  GMM(const GMM& other);

  /**
   * Copy operator for GMMs which use different fitting types.
   */
  template<typename OtherFittingType>
  GMM& operator=(const GMM<OtherFittingType>& other);

  /**
   * Copy operator for GMMs which use the same fitting type.  This also copies
{'fraction_non_alphanumeric': 0.09918824893699266, 'fraction_numerical': 0.0013915732508697333, 'mean_word_length': 3.21505376344086, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7224514', 'n_tokens_mistral': 3814, 'n_tokens_neox': 3713, 'n_words': 1408}