mog_diag_em.cpp
Go to the documentation of this file.
#include <itpp/stat/mog_diag_em.h>
#include <itpp/base/math/log_exp.h>
#include <itpp/base/timing.h>
#include <iostream>
#include <iomanip>
namespace itpp
{
void inline MOG_diag_EM_sup::update_internals()
{
double Ddiv2_log_2pi = D / 2.0 * std::log(m_2pi);
for (int k = 0;k < K;k++) c_log_weights[k] = std::log(c_weights[k]);
for (int k = 0;k < K;k++) {
double acc = 0.0;
double * c_diag_cov = c_diag_covs[k];
double * c_diag_cov_inv_etc = c_diag_covs_inv_etc[k];
for (int d = 0;d < D;d++) {
double tmp = c_diag_cov[d];
c_diag_cov_inv_etc[d] = 1.0 / (2.0 * tmp);
acc += std::log(tmp);
}
c_log_det_etc[k] = -Ddiv2_log_2pi - 0.5 * acc;
}
}
void inline MOG_diag_EM_sup::sanitise_params()
{
double acc = 0.0;
for (int k = 0;k < K;k++) {
if (c_weights[k] < weight_floor) c_weights[k] = weight_floor;
if (c_weights[k] > 1.0) c_weights[k] = 1.0;
acc += c_weights[k];
}
for (int k = 0;k < K;k++) c_weights[k] /= acc;
for (int k = 0;k < K;k++)
for (int d = 0;d < D;d++)
if (c_diag_covs[k][d] < var_floor) c_diag_covs[k][d] = var_floor;
}
double MOG_diag_EM_sup::ml_update_params()
{
double acc_loglhood = 0.0;
for (int k = 0;k < K;k++) {
c_acc_loglhood_K[k] = 0.0;
double * c_acc_mean = c_acc_means[k];
double * c_acc_cov = c_acc_covs[k];
for (int d = 0;d < D;d++) { c_acc_mean[d] = 0.0; c_acc_cov[d] = 0.0; }
}
for (int n = 0;n < N;n++) {
double * c_x = c_X[n];
bool danger = paranoid;
for (int k = 0;k < K;k++) {
double tmp = c_log_weights[k] + MOG_diag::log_lhood_single_gaus_internal(c_x, k);
c_tmpvecK[k] = tmp;
if (tmp >= log_max_K) danger = true;
}
if (danger) {
double log_sum = c_tmpvecK[0];
for (int k = 1;k < K;k++) log_sum = log_add(log_sum, c_tmpvecK[k]);
acc_loglhood += log_sum;
for (int k = 0;k < K;k++) {
double * c_acc_mean = c_acc_means[k];
double * c_acc_cov = c_acc_covs[k];
double tmp_k = trunc_exp(c_tmpvecK[k] - log_sum);
acc_loglhood_K[k] += tmp_k;
for (int d = 0;d < D;d++) {
double tmp_x = c_x[d];
c_acc_mean[d] += tmp_k * tmp_x;
c_acc_cov[d] += tmp_k * tmp_x * tmp_x;
}
}
}
else {
double sum = 0.0;
for (int k = 0;k < K;k++) { double tmp = std::exp(c_tmpvecK[k]); c_tmpvecK[k] = tmp; sum += tmp; }
acc_loglhood += std::log(sum);
for (int k = 0;k < K;k++) {
double * c_acc_mean = c_acc_means[k];
double * c_acc_cov = c_acc_covs[k];
double tmp_k = c_tmpvecK[k] / sum;
c_acc_loglhood_K[k] += tmp_k;
for (int d = 0;d < D;d++) {
double tmp_x = c_x[d];
c_acc_mean[d] += tmp_k * tmp_x;
c_acc_cov[d] += tmp_k * tmp_x * tmp_x;
}
}
}
}
for (int k = 0;k < K;k++) {
double * c_mean = c_means[k];
double * c_diag_cov = c_diag_covs[k];
double * c_acc_mean = c_acc_means[k];
double * c_acc_cov = c_acc_covs[k];
double tmp_k = c_acc_loglhood_K[k];
c_weights[k] = tmp_k / N;
for (int d = 0;d < D;d++) {
double tmp_mean = c_acc_mean[d] / tmp_k;
c_mean[d] = tmp_mean;
c_diag_cov[d] = c_acc_cov[d] / tmp_k - tmp_mean * tmp_mean;
}
}
return(acc_loglhood / N);
}
void MOG_diag_EM_sup::ml_iterate()
{
using std::cout;
using std::endl;
using std::setw;
using std::showpos;
using std::noshowpos;
using std::scientific;
using std::fixed;
using std::flush;
using std::setprecision;
double avg_log_lhood_old = -1.0 * std::numeric_limits<double>::max();
Real_Timer tt;
if (verbose) {
cout << "MOG_diag_EM_sup::ml_iterate()" << endl;
cout << setw(14) << "iteration";
cout << setw(14) << "avg_loglhood";
cout << setw(14) << "delta";
cout << setw(10) << "toc";
cout << endl;
}
for (int i = 0; i < max_iter; i++) {
sanitise_params();
update_internals();
if (verbose) tt.tic();
double avg_log_lhood_new = ml_update_params();
if (verbose) {
double delta = avg_log_lhood_new - avg_log_lhood_old;
cout << noshowpos << fixed;
cout << setw(14) << i;
cout << showpos << scientific << setprecision(3);
cout << setw(14) << avg_log_lhood_new;
cout << setw(14) << delta;
cout << noshowpos << fixed;
cout << setw(10) << tt.toc();
cout << endl << flush;
}
if (avg_log_lhood_new <= avg_log_lhood_old) break;
avg_log_lhood_old = avg_log_lhood_new;
}
}
void MOG_diag_EM_sup::ml(MOG_diag &model_in, Array<vec> &X_in, int max_iter_in, double var_floor_in, double weight_floor_in, bool verbose_in)
{
it_assert(model_in.is_valid(), "MOG_diag_EM_sup::ml(): initial model not valid");
it_assert(check_array_uniformity(X_in), "MOG_diag_EM_sup::ml(): 'X' is empty or contains vectors of varying dimensionality");
it_assert((max_iter_in > 0), "MOG_diag_EM_sup::ml(): 'max_iter' needs to be greater than zero");
verbose = verbose_in;
N = X_in.size();
Array<vec> means_in = model_in.get_means();
Array<vec> diag_covs_in = model_in.get_diag_covs();
vec weights_in = model_in.get_weights();
init(means_in, diag_covs_in, weights_in);
means_in.set_size(0);
diag_covs_in.set_size(0);
weights_in.set_size(0);
if (K > N) {
it_warning("MOG_diag_EM_sup::ml(): WARNING: K > N");
}
else {
if (K > N / 10) {
it_warning("MOG_diag_EM_sup::ml(): WARNING: K > N/10");
}
}
var_floor = var_floor_in;
weight_floor = weight_floor_in;
const double tiny = std::numeric_limits<double>::min();
if (var_floor < tiny) var_floor = tiny;
if (weight_floor < tiny) weight_floor = tiny;
if (weight_floor > 1.0 / K) weight_floor = 1.0 / K;
max_iter = max_iter_in;
tmpvecK.set_size(K);
tmpvecD.set_size(D);
acc_loglhood_K.set_size(K);
acc_means.set_size(K);
for (int k = 0;k < K;k++) acc_means(k).set_size(D);
acc_covs.set_size(K);
for (int k = 0;k < K;k++) acc_covs(k).set_size(D);
c_X = enable_c_access(X_in);
c_tmpvecK = enable_c_access(tmpvecK);
c_tmpvecD = enable_c_access(tmpvecD);
c_acc_loglhood_K = enable_c_access(acc_loglhood_K);
c_acc_means = enable_c_access(acc_means);
c_acc_covs = enable_c_access(acc_covs);
ml_iterate();
model_in.init(means, diag_covs, weights);
disable_c_access(c_X);
disable_c_access(c_tmpvecK);
disable_c_access(c_tmpvecD);
disable_c_access(c_acc_loglhood_K);
disable_c_access(c_acc_means);
disable_c_access(c_acc_covs);
tmpvecK.set_size(0);
tmpvecD.set_size(0);
acc_loglhood_K.set_size(0);
acc_means.set_size(0);
acc_covs.set_size(0);
cleanup();
}
void MOG_diag_EM_sup::map(MOG_diag &, MOG_diag &, Array<vec> &, int, double,
double, double, bool)
{
it_error("MOG_diag_EM_sup::map(): not implemented yet");
}
//
// convenience functions
void MOG_diag_ML(MOG_diag &model_in, Array<vec> &X_in, int max_iter_in, double var_floor_in, double weight_floor_in, bool verbose_in)
{
MOG_diag_EM_sup EM;
EM.ml(model_in, X_in, max_iter_in, var_floor_in, weight_floor_in, verbose_in);
}
void MOG_diag_MAP(MOG_diag &, MOG_diag &, Array<vec> &, int, double, double,
double, bool)
{
it_error("MOG_diag_MAP(): not implemented yet");
}
}
itpp::Array
General array class.
Definition array.h:105
itpp::Array::size
int size() const
Returns the number of data elements in the array object.
Definition array.h:155
itpp::Array::set_size
void set_size(int n, bool copy=false)
Resizing an Array<T>.
Definition array.h:257
itpp::MOG_diag_EM_sup
support class for MOG_diag_ML() and MOG_diag_MAP()
Definition mog_diag_em.h:44
itpp::MOG_diag_EM_sup::max_iter
int max_iter
Maximum number of iterations.
Definition mog_diag_em.h:68
itpp::MOG_diag_EM_sup::var_floor
double var_floor
ADD DOCUMENTATION HERE.
Definition mog_diag_em.h:74
itpp::MOG_diag_EM_sup::sanitise_params
void sanitise_params()
ADD DOCUMENTATION HERE.
Definition mog_diag_em.cpp:66
itpp::MOG_diag_EM_sup::weight_floor
double weight_floor
ADD DOCUMENTATION HERE.
Definition mog_diag_em.h:76
itpp::MOG_diag_EM_sup::N
int N
number of training vectors
Definition mog_diag_em.h:65
itpp::MOG_diag_EM_sup::update_internals
void update_internals()
ADD DOCUMENTATION HERE.
Definition mog_diag_em.cpp:41
itpp::MOG_diag_EM_sup::verbose
bool verbose
Whether we print the progress.
Definition mog_diag_em.h:62
itpp::MOG_diag_EM_sup::map
void map(MOG_diag &model_in, MOG_diag &prior_model, Array< vec > &X_in, int max_iter_in=10, double alpha_in=0.5, double var_floor_in=0.0, double weight_floor_in=0.0, bool verbose_in=false)
ADD DOCUMENTATION HERE.
Definition mog_diag_em.cpp:306
itpp::MOG_diag_EM_sup::ml
void ml(MOG_diag &model_in, Array< vec > &X_in, int max_iter_in=10, double var_floor_in=0.0, double weight_floor_in=0.0, bool verbose_in=false)
ADD DOCUMENTATION HERE.
Definition mog_diag_em.cpp:228
itpp::MOG_diag_EM_sup::ml_update_params
double ml_update_params()
ADD DOCUMENTATION HERE.
Definition mog_diag_em.cpp:84
itpp::MOG_diag_EM_sup::ml_iterate
void ml_iterate()
ADD DOCUMENTATION HERE.
Definition mog_diag_em.cpp:176
itpp::MOG_diag_EM_sup::c_X
double ** c_X
'C' pointers to training vectors
Definition mog_diag_em.h:71
itpp::MOG_diag
Diagonal Mixture of Gaussians (MOG) class.
Definition mog_diag.h:56
itpp::MOG_diag::c_diag_covs_inv_etc
double ** c_diag_covs_inv_etc
pointers to the inverted covariance vectors
Definition mog_diag.h:203
itpp::MOG_diag::log_lhood_single_gaus_internal
double log_lhood_single_gaus_internal(const double *c_x_in, const int k) const
ADD DOCUMENTATION HERE.
Definition mog_diag.cpp:37
itpp::MOG_diag::c_means
double ** c_means
pointers to the mean vectors
Definition mog_diag.h:197
itpp::MOG_diag::disable_c_access
double ** disable_c_access(double **A_in)
Disable C style access to an Array of vectors (vec)
Definition mog_diag.cpp:300
itpp::MOG_diag::enable_c_access
double ** enable_c_access(Array< vec > &A_in)
Enable C style access to an Array of vectors (vec)
Definition mog_diag.cpp:284
itpp::MOG_diag::cleanup
void cleanup()
Release memory used by the model. The model will be empty.
Definition mog_diag.h:111
itpp::MOG_diag::c_log_det_etc
double * c_log_det_etc
pointer to the log_det_etc vector
Definition mog_diag.h:212
itpp::MOG_diag::c_log_weights
double * c_log_weights
pointer to the log version of the weight vector
Definition mog_diag.h:209
itpp::MOG_diag::c_weights
double * c_weights
pointer to the weight vector
Definition mog_diag.h:206
itpp::MOG_diag::c_diag_covs
double ** c_diag_covs
pointers to the covariance vectors
Definition mog_diag.h:200
itpp::MOG_generic::check_array_uniformity
bool check_array_uniformity(const Array< vec > &A) const
Check if all vectors in Array X_in have the same dimensionality.
Definition mog_generic.cpp:144
itpp::MOG_generic::init
void init()
Initialise the model to be empty.
Definition mog_generic.cpp:43
itpp::MOG_generic::K
int K
number of gaussians
Definition mog_generic.h:292
itpp::MOG_generic::weights
vec weights
weights
Definition mog_generic.h:307
itpp::MOG_generic::diag_covs
Array< vec > diag_covs
diagonal covariance matrices, stored as vectors
Definition mog_generic.h:301
itpp::MOG_generic::D
int D
dimensionality
Definition mog_generic.h:295
itpp::MOG_generic::means
Array< vec > means
means
Definition mog_generic.h:298
itpp::MOG_generic::log_max_K
double log_max_K
Pre-calcualted std::log(std::numeric_limits<double>::max() / K), where K is the number of Gaussians.
Definition mog_generic.h:310
itpp::MOG_generic::paranoid
bool paranoid
indicates whether we are paranoid about numerical stability
Definition mog_generic.h:289
itpp::Real_Timer
A real time timer class.
Definition timing.h:139
itpp::MOG_diag_ML
void MOG_diag_ML(MOG_diag &model_in, Array< vec > &X_in, int max_iter_in, double var_floor_in, double weight_floor_in, bool verbose_in)
Definition mog_diag_em.cpp:316
it_error
#define it_error(s)
Abort unconditionally.
Definition itassert.h:126
it_warning
#define it_warning(s)
Display a warning message.
Definition itassert.h:173
it_assert
#define it_assert(t, s)
Abort if t is not true.
Definition itassert.h:94
itpp::flush
it_file & flush(it_file &f)
Flush operator.
Definition itfile.h:409
itpp::log_add
double log_add(double log_a, double log_b)
Safe substitute for log(exp(log_a) + exp(log_b))
Definition log_exp.cpp:40
itpp::trunc_exp
double trunc_exp(double x)
Truncated exponential function.
Definition log_exp.h:137
itpp::sum
T sum(const Vec< T > &v)
Sum of all elements in the vector.
Definition matfunc.h:59
log_exp.h
Logarithmic and exponenential functions - header file.
mog_diag_em.h
Expectation Maximisation (EM) based optimisers for MOG - header file.
itpp
itpp namespace
Definition itmex.h:37
itpp::m_2pi
const double m_2pi
Constant 2*Pi.
Definition misc.h:106
itpp::MOG_diag_MAP
void MOG_diag_MAP(MOG_diag &, MOG_diag &, Array< vec > &, int, double, double, double, bool)
Definition mog_diag_em.cpp:322
timing.h
Definitions of Timing classes.

Generated on Mon Jun 10 2024 11:49:26 for IT++ by Doxygen 1.9.8