53 if (!isValidMemberIndex(k))
56 _(
"index out of bounds."));
59 return members[k].first;
73 if (!isValidMemberIndex(k))
76 _(
"index out of bounds."));
79 return members[k].second;
93 if (!isValidMemberIndex(k))
96 _(
"index out of bounds."));
99 return members[k].first.GetMean();
113 if (!isValidMemberIndex(k))
116 _(
"index out of bounds."));
119 return members[k].first.GetVariance();
130 members.push_back(std::make_pair(pdf, w));
144 if (!isValidMemberIndex(k))
147 "UnivariateGaussianPDF PDF, double w, size_t k): ") +
148 _(
"index out of bounds."));
150 members[k] = std::make_pair(pdf, w);
157 inline bool operator()(
const std::pair<UnivariateGaussianPDF, double> &e1,
const std::pair<UnivariateGaussianPDF, double> &e2)
const
160 return e1.first.GetMean() > e2.first.GetMean();
162 return e1.first.GetMean() < e2.first.GetMean();
173 inline bool operator()(
const std::pair<UnivariateGaussianPDF, double> &e1,
const std::pair<UnivariateGaussianPDF, double> &e2)
const
176 return e1.first.GetVariance() > e2.first.GetVariance();
178 return e1.first.GetVariance() < e2.first.GetVariance();
189 inline bool operator()(
const std::pair<UnivariateGaussianPDF, double> &e1,
const std::pair<UnivariateGaussianPDF, double> &e2)
const
192 return e1.second > e2.second;
194 return e1.second < e2.second;
206 std::sort(members.begin(), members.end(),
pair_comp_mean(reverse));
236 for (
auto & elem : members)
237 d += elem.second * elem.first.ValueAt(x);
254 if (!isValidMemberIndex(k))
256 _(
"index out of bounds."));
258 double val = members[k].first.ValueAt(x);
261 val *= members[k].second;
275 size_t nbPatterns = data.
GetRows();
278 for (
size_t k = 0; k < nbPatterns; ++k)
293 size_t nbPatterns = data.size();
296 for (
size_t k = 0; k < nbPatterns; ++k)
314 unsigned int nbIterations = 0;
315 size_t nbMembers = size_t(nbSeeds);
316 size_t nbPatterns = patterns.
GetRows();
324 double min_value = patterns.
GetMin();
325 double max_value = patterns.
GetMax();
326 double delta = (max_value - min_value) /
double(nbSeeds);
327 double seed = min_value + delta / 2.0;
332 for (
size_t k = 0; k < nbMembers; ++k)
338 double sigma = sqrt(var);
343 double v = patterns[counter][0];
345 redo = (fabs(seed - v) > sigma);
348 if ((counter >= nbPatterns) && redo)
363 bool Continue =
true;
364 double likelihood = 0.0;
374 for (
size_t i = 0; i < nbPatterns; ++i)
376 double xi = patterns[i][0];
379 for (
size_t k = 0; k < nbMembers; ++k)
381 double pik = this->
ValueAt(xi, k);
392 for (
size_t k = 0; k < nbMembers; ++k)
395 double CumulPk = 0.0;
401 for (
size_t i = 0; i < nbPatterns; ++i)
403 double pik = Proba[i][k];
404 double xi = patterns[i][0];
408 v += pik *
Sqr(xi - muk);
412 if (std::isinf(mu) || std::isinf(v))
417 for (
size_t i = 0; i < nbPatterns; ++i)
419 double pik = Proba[i][k];
420 double xi = patterns[i][0];
422 mu += pik * xi / CumulPk;
423 v += pik *
Sqr(xi - muk) / CumulPk;
432 members[k].second = double(CumulPk) / double(nbPatterns);
436 double NewLikelihood =
MLLE(patterns);
437 double LikelihoodDiff = fabs(NewLikelihood - likelihood);
439 likelihood = NewLikelihood;
442 Continue = ((nbIterations < maximalIterations) && (LikelihoodDiff > epsilon));
460 unsigned int nbIterations = 0;
461 size_t nbMembers = size_t(nbSeeds);
462 size_t nbPatterns = patterns.size();
463 auto spatterns = patterns;
470 std::sort(spatterns.begin(), spatterns.end());
472 double min_value = spatterns.front();
473 double max_value = spatterns.back();
474 double delta = (max_value - min_value) /
double(nbSeeds);
475 double seed = min_value + delta / 2.0;
480 for (
size_t k = 0; k < nbMembers; ++k)
486 double sigma = sqrt(var);
491 double v = spatterns[counter];
493 redo = (fabs(seed - v) > sigma);
496 if ((counter >= nbPatterns) && redo)
510 bool Continue =
true;
511 double likelihood = 0.0;
521 for (
size_t i = 0; i < nbPatterns; ++i)
523 double xi = spatterns[i];
526 for (
size_t k = 0; k < nbMembers; ++k)
528 double pik = this->
ValueAt(xi, k);
539 for (
size_t k = 0; k < nbMembers; ++k)
542 double CumulPk = 0.0;
548 for (
size_t i = 0; i < nbPatterns; ++i)
550 double pik = Proba[i][k];
551 double xi = spatterns[i];
555 v += pik *
Sqr(xi - muk);
558 if (std::isfinite(mu) && std::isfinite(v))
568 for (
size_t i = 0; i < nbPatterns; ++i)
570 double pik = Proba[i][k];
571 double xi = spatterns[i];
573 mu += pik * xi / CumulPk;
574 v += pik *
Sqr(xi - muk) / CumulPk;
578 members[k].second = double(CumulPk) / double(nbPatterns);
582 double NewLikelihood =
MLLE(spatterns);
583 double LikelihoodDiff = fabs(NewLikelihood - likelihood);
585 likelihood = NewLikelihood;
588 Continue = ((nbIterations < maximalIterations) && (LikelihoodDiff > epsilon));
607 auto patterns = std::vector<double>();
609 std::vector<int> pop;
610 std::vector<double> cumul_weights;
611 std::vector<double> index_sample;
618 srand((
unsigned int)time(
nullptr));
621 for (
size_t k = 0; k < n; ++k)
623 index_sample.push_back(((
double)(rand())) / ((
double)(RAND_MAX)));
630 for (
size_t k = 0; k < nbPDF; k++)
634 cumul_weights.push_back(mass);
637 for (
size_t k = 0; k < nbPDF; ++k)
639 cumul_weights[k] /= mass;
645 for (
size_t k = 0; k < n; k++)
647 double d = index_sample[k];
648 bool continue_flag =
true;
651 while (continue_flag)
653 if ((cumul_weights[Id] >= d) || (Id == nbPDF - 1))
655 continue_flag =
false;
668 for (
size_t p = 0; p < nbPDF; ++p)
670 int subsample_pop = pop[p];
674 for (
int r = 0; r < subsample_pop; ++r)
676 patterns.push_back(subsample[r]);
692 for (
size_t k = 0; k < members.size(); ++k)
711 if (isValidMemberIndex(k))
716 s += members.size() - 1;
717 s += U
"]\nWeight = ";
718 s += members[k].second;
720 s += (members[k].first).
GetMean();
721 s += U
"\nVariance = ";
741 if (el.
GetName() !=
"UnivariateGaussianMixture")
744 _(
"Wrong XML element."));
747 std::vector<std::pair<UnivariateGaussianPDF, double> > newmembers;
751 double w = sub_el.GetAttribute<
double>(
"weight",
false);
755 newmembers.push_back(std::make_pair(pdf, w));
758 members.swap(newmembers);
774 for (
auto & elem : members)
785 Cloner::Register<UnivariateGaussianMixture>();
bool operator()(const std::pair< UnivariateGaussianPDF, double > &e1, const std::pair< UnivariateGaussianPDF, double > &e2) const
size_t GetRows() const noexcept
Returns the number of rows.
Univariate Gaussian distribution.
double GetWeight(size_t k) const
Returns the weight of a given density function.
StringUTF8 GetName() const
Gets the label of the element.
String ToString() const
Dumps a summary of the mixture to a string.
bool operator()(const std::pair< UnivariateGaussianPDF, double > &e1, const std::pair< UnivariateGaussianPDF, double > &e2) const
void AddMember(UnivariateGaussianPDF pdf, double Weight)
Adds a density function.
void SetMember(UnivariateGaussianPDF pdf, double w, size_t k)
Replaces a given density function and its weight.
std::vector< double > MakeRandomSample(size_t n=1, size_t m=100, bool reseed=true) const
Creates a data sample following the PDF's probability law.
UnivariateGaussianPDF GetMember(size_t k) const
Returns a given density function.
void Deserialize(xml::Element &el)
double ValueAt(const double x) const
Evaluates a pattern.
Element BeginElement()
Gets the first child element.
#define CRN_END_CLASS_CONSTRUCTOR(classname)
Defines a class constructor.
bool operator()(const std::pair< UnivariateGaussianPDF, double > &e1, const std::pair< UnivariateGaussianPDF, double > &e2) const
A UTF32 character string class.
virtual ~UnivariateGaussianMixture() override
Destructor.
size_t GetNbMembers() const noexcept
Returns the number of density functions.
unsigned int EM(const MatrixDouble &patterns, size_t nbSeeds=2, double epsilon=std::numeric_limits< double >::epsilon(), size_t maximalIterations=100)
Expectation Maximization.
void MultRow(size_t r, double v)
Scale one row from matrix.
#define CRN_DATA_FACTORY_REGISTER(elemname, classname)
Registers a class to the data factory.
constexpr SumType< T > Sqr(const T &v) noexcept(noexcept(v *v))
Returns the square of a value.
void SortMembersByWeights(bool reverse=false)
Sort members by weights.
pair_comp_variance(bool r)
double GetMean() const noexcept
Returns the mean of a given density function.
void SetAttribute(const StringUTF8 &name, const StringUTF8 &value)
Sets the value of an attribute.
Univariate Gaussian mixture.
const T & At(size_t pos) const noexcept
double GetVariance(size_t k) const
Returns the variance of a given density function.
A character string class.
std::vector< double > MakeRandomSample(size_t n=1, size_t m=100, bool reseed=true) const
Creates a data sample following the mixture's probability law.
void SortMembersByMeans(bool reverse=false)
Sort members by means.
xml::Element Serialize(xml::Element &parent) const
Element PushBackElement(const StringUTF8 &name)
Adds an element at the end of the children list.
void SortMembersByVariances(bool reverse=false)
Sort members by means.
Element EndElement()
Gets a null node.
double MLLE(const MatrixDouble &Data) const
Maximum log-likelihood estimation.
Invalid argument error (e.g.: nullptr pointer)
double GetMean(size_t k) const
Returns the mean of a given density function.
#define CRN_BEGIN_CLASS_CONSTRUCTOR(classname)
Defines a class constructor.