hops
Mixture.hpp
Go to the documentation of this file.
1 #ifndef HOPS_MIXTURE_HPP
2 #define HOPS_MIXTURE_HPP
3 
4 #include <execution>
5 #include <numeric>
6 #include <utility>
7 #include <vector>
8 
9 #include <hops/Model/Model.hpp>
10 
11 namespace hops {
12  class Mixture : public Model {
13  public:
14  explicit Mixture(const std::vector<std::shared_ptr<Model>> &models) :
15  models(models),
16  weights(std::vector<double>(models.size(), 1. / models.size())) {}
17 
18  Mixture(std::vector<std::shared_ptr<Model>> models, std::vector<double> weights) :
19  models(std::move(models)),
20  weights(std::move(weights)) {
21  if (this->models.size() != this->weights.size()) {
22  throw std::invalid_argument(
23  "Models and weights should have the same length for construction of Multimodal Object."
24  );
25  }
26  }
27 
28  [[nodiscard]] MatrixType::Scalar computeNegativeLogLikelihood(const VectorType &x) const override {
29  double likelihood = std::transform_reduce(std::execution::seq,
30  models.begin(),
31  models.end(),
32  weights.begin(),
33  double(0.),
34  std::plus<>(),
35  [&x](const std::shared_ptr<Model> &model, double weight) {
36  return static_cast<double>(weight * std::exp(
37  -model->computeNegativeLogLikelihood(x)));
38  });
39  return -std::log(likelihood);
40  }
41 
47  [[nodiscard]] std::optional<VectorType>
48  computeLogLikelihoodGradient(const VectorType &x) const override {
49  std::vector<double> weightedLikelihoods;
50 
51  std::transform(models.begin(),
52  models.end(),
53  weights.begin(),
54  std::back_inserter(weightedLikelihoods),
55  [&x](const std::shared_ptr<Model> &model, double weight) {
56  return weight * std::exp(-model->computeNegativeLogLikelihood(x));
57  }
58  );
59 
60  double denominator = std::accumulate(weightedLikelihoods.begin(), weightedLikelihoods.end(), 0.);
61 
62  return std::transform_reduce(models.begin(),
63  models.end(),
64  weightedLikelihoods.begin(),
65  VectorType(VectorType::Zero(x.rows())),
66  std::plus<>(),
67  [&x](const std::shared_ptr<Model> &model, double weightedLikelihood) {
68  auto gradient = model->computeLogLikelihoodGradient(x);
69  if (gradient) {
70  return VectorType(weightedLikelihood * gradient.value());
71  }
72  return VectorType(VectorType::Zero(x.rows()));
73  }
74  ) / denominator;
75  }
76 
77  [[nodiscard]] std::optional<MatrixType>
78  computeExpectedFisherInformation(const VectorType &x) const override {
79  return std::nullopt;
80  }
81 
82  private:
83  std::vector<std::shared_ptr<Model>> models;
84  std::vector<double> weights;
85  };
86 }
87 
88 #endif //HOPS_MIXTURE_HPP
hops::Mixture::Mixture
Mixture(const std::vector< std::shared_ptr< Model >> &models)
Definition: Mixture.hpp:14
hops::Mixture::computeNegativeLogLikelihood
MatrixType::Scalar computeNegativeLogLikelihood(const VectorType &x) const override
Evaluates the negative log likelihood for input x.
Definition: Mixture.hpp:28
hops::Mixture::computeLogLikelihoodGradient
std::optional< VectorType > computeLogLikelihoodGradient(const VectorType &x) const override
Definition: Mixture.hpp:48
hops::Mixture::Mixture
Mixture(std::vector< std::shared_ptr< Model >> models, std::vector< double > weights)
Definition: Mixture.hpp:18
hops::Mixture::computeExpectedFisherInformation
std::optional< MatrixType > computeExpectedFisherInformation(const VectorType &x) const override
Definition: Mixture.hpp:78
Model.hpp
hops
Definition: CsvReader.hpp:8
hops::Model
Definition: Model.hpp:12
hops::VectorType
Eigen::VectorXd VectorType
Definition: VectorType.hpp:7
hops::Mixture
Definition: Mixture.hpp:12