Go to the documentation of this file.00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "vpdfl_pc_gaussian.h"
00017 #include <vcl_string.h>
00018 #include <vcl_cstdlib.h>
00019 #include <vcl_cassert.h>
00020 #include <vsl/vsl_binary_loader.h>
00021 #include <vsl/vsl_indent.h>
00022 #include <vnl/vnl_math.h>
00023 #include <mbl/mbl_matxvec.h>
00024 #include <vpdfl/vpdfl_pc_gaussian_builder.h>
00025 #include <vpdfl/vpdfl_gaussian_sampler.h>
00026 #include <vpdfl/vpdfl_gaussian.h>
00027
00028
00029
00030
00031 vpdfl_pc_gaussian::vpdfl_pc_gaussian()
00032 : partition_(0), log_k_principal_(0.0), partition_chooser_(0)
00033 {
00034 }
00035
00036
00037
00038 vpdfl_pc_gaussian::~vpdfl_pc_gaussian()
00039 {
00040 delete partition_chooser_;
00041 }
00042
00043
00044
00045
00046
00047
00048
00049 double vpdfl_pc_gaussian::log_p(const vnl_vector<double>& x) const
00050 {
00051 unsigned int m = n_principal_components();
00052 unsigned int n = n_dims();
00053 assert(x.size() == n);
00054
00055 if (m+1>=n)
00056 return vpdfl_gaussian::log_p(x);
00057
00058 double mahalDIFS, euclidDFFS;
00059 get_distances(mahalDIFS, euclidDFFS, x);
00060
00061 return log_k() - log_k_principal() -euclidDFFS/(2 * (eigenvals()(m+1))) - mahalDIFS;
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071 void vpdfl_pc_gaussian::get_distances(double &mahalDIFS, double &euclidDFFS, const vnl_vector<double>& x) const
00072 {
00073 const unsigned int m = n_principal_components();
00074 const unsigned int n = n_dims();
00075
00076 assert(x.size() == n);
00077
00078 dx_ = x;
00079 dx_ -= mean();
00080
00081 if (b_.size()!=m) b_.set_size(m);
00082
00083
00084
00085
00086
00087 mbl_matxvec_prod_vm(dx_, eigenvecs(), b_);
00088
00089 const double* b_data = b_.data_block();
00090 const double* v_data = eigenvals().data_block();
00091
00092 double sum=0.0;
00093
00094 int i=m;
00095 double db, sumBSq=0.0;
00096 while (i--)
00097 {
00098 db = b_data[i];
00099 sum+=(db*db)/v_data[i];
00100 sumBSq+=(db*db);
00101 }
00102
00103 mahalDIFS = - log_k_principal() + 0.5*sum;
00104 if ( n!=m)
00105 {
00106 i=n;
00107 const double* dx_data = dx_.data_block() ;
00108 double ddx, sumDxSq=0.0;
00109 while (i--)
00110 {
00111 ddx = dx_data[i];
00112 sumDxSq+=(ddx*ddx);
00113 }
00114
00115
00116
00117
00118
00119 euclidDFFS = sumDxSq - sumBSq;
00120 if (euclidDFFS < 0) euclidDFFS = 0;
00121 }
00122 else
00123 euclidDFFS = 0.0;
00124 }
00125
00126
00127
00128 void vpdfl_pc_gaussian::calcPartLogK()
00129 {
00130 const double *v_data = eigenvals().data_block();
00131 double log_v_sum = 0.0;
00132 const unsigned& n = partition_;
00133
00134 for (unsigned int i=0;i<n;i++) log_v_sum+=vcl_log(v_data[i]);
00135
00136 log_k_principal_ = -0.5 * (n*vcl_log(2 * vnl_math::pi) + log_v_sum);
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146 void vpdfl_pc_gaussian::set(const vnl_vector<double>& mean,
00147 const vnl_matrix<double>& evecs,
00148 const vnl_vector<double>& evals,
00149 double complementEVal)
00150 {
00151 partition_ = evals.size();
00152
00153 assert (partition_ <= evecs.cols());
00154
00155 assert (evecs.cols() == evecs.rows());
00156
00157 unsigned int n = evecs.cols();
00158
00159 vnl_vector<double> allEVals(n);
00160
00161
00162 for (unsigned int i = 0; i < partition_; i++)
00163 {
00164 allEVals(i) = evals(i);
00165 }
00166 for (unsigned int i = partition_; i < n; i++)
00167 {
00168 allEVals(i) = complementEVal;
00169 }
00170 vpdfl_gaussian::set(mean, evecs, allEVals);
00171
00172 calcPartLogK();
00173 }
00174
00175
00176
00177
00178
00179
00180
00181 void vpdfl_pc_gaussian::set(const vnl_vector<double>& mean, const vnl_matrix<double>& evecs, const vnl_vector<double>& evals)
00182 {
00183 #ifndef NDEBUG
00184 if (!partition_chooser_)
00185 {
00186 vcl_cerr << "ERROR: vpdfl_pc_gaussian::set()\nUsing this function requires"
00187 << " partition_chooser_ to be set to a real builder\n\n";
00188 vcl_abort();
00189 }
00190 #endif
00191
00192 int n_principal_components = partition_chooser_->decide_partition(evals);
00193 int n = mean.size();
00194 vnl_vector<double> principalEVals(n_principal_components);
00195
00196
00197 for (int i=0;i<n_principal_components;++i)
00198 principalEVals(i)=evals(i);
00199
00200 double eVsum = 0.0;
00201 for (int i=n_principal_components; i < n; i++)
00202 eVsum += evals(i);
00203
00204
00205 double complementaryEVals = eVsum / (n - n_principal_components);
00206
00207 set(mean, evecs, principalEVals, complementaryEVals);
00208 }
00209
00210
00211
00212
00213 vpdfl_sampler_base* vpdfl_pc_gaussian::sampler() const
00214 {
00215 vpdfl_gaussian_sampler *i = new vpdfl_gaussian_sampler;
00216 i->set_model(*this);
00217 return i;
00218 }
00219
00220
00221
00222 vcl_string vpdfl_pc_gaussian::is_a() const
00223 {
00224 return vcl_string("vpdfl_pc_gaussian");
00225 }
00226
00227
00228
00229 bool vpdfl_pc_gaussian::is_class(vcl_string const& s) const
00230 {
00231 return vpdfl_gaussian::is_class(s) || s==vpdfl_pc_gaussian::is_a();
00232 }
00233
00234
00235
00236 short vpdfl_pc_gaussian::version_no() const
00237 {
00238 return 2;
00239 }
00240
00241
00242
00243 vpdfl_pdf_base* vpdfl_pc_gaussian::clone() const
00244 {
00245 return new vpdfl_pc_gaussian(*this);
00246 }
00247
00248
00249
00250 void vpdfl_pc_gaussian::print_summary(vcl_ostream& os) const
00251 {
00252 os << '\n' << vsl_indent() << "Partition at: " << partition_
00253 << " Log(k) for principal space: "<< log_k_principal_ << '\n'
00254 << vsl_indent() << "Partition Chooser: " ;
00255 if (partition_chooser_) os << *partition_chooser_ << '\n';
00256 else os << "NULL\n";
00257 os << vsl_indent();
00258 vpdfl_gaussian::print_summary(os);
00259 }
00260
00261
00262
00263 void vpdfl_pc_gaussian::b_write(vsl_b_ostream& bfs) const
00264 {
00265 vsl_b_write(bfs,is_a());
00266 vsl_b_write(bfs,version_no());
00267 vpdfl_gaussian::b_write(bfs);
00268 vsl_b_write(bfs,partition_);
00269 vsl_b_write(bfs,log_k_principal_);
00270 vsl_b_write(bfs,static_cast<vpdfl_builder_base *>(partition_chooser_));
00271 }
00272
00273
00274
00275 void vpdfl_pc_gaussian::b_read(vsl_b_istream& bfs)
00276 {
00277 if (!bfs) return;
00278
00279 vcl_string name;
00280 vsl_b_read(bfs,name);
00281 if (name != is_a())
00282 {
00283 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, vpdfl_pc_gaussian &)\n"
00284 << " Attempted to load object of type "
00285 << name <<" into object of type " << is_a() << vcl_endl;
00286 bfs.is().clear(vcl_ios::badbit);
00287 return;
00288 }
00289
00290 short version;
00291 vsl_b_read(bfs,version);
00292 switch (version)
00293 {
00294 case (1):
00295 vpdfl_gaussian::b_read(bfs);
00296 vsl_b_read(bfs,partition_);
00297 vsl_b_read(bfs,log_k_principal_);
00298 partition_chooser_ = 0;
00299 break;
00300 case (2):
00301 vpdfl_gaussian::b_read(bfs);
00302 vsl_b_read(bfs,partition_);
00303 vsl_b_read(bfs,log_k_principal_);
00304 {
00305 vpdfl_builder_base * c = 0;
00306 vsl_b_read(bfs,c);
00307 assert(!c || c->is_class("vpdfl_pc_gaussian_builder"));
00308 partition_chooser_ = static_cast<vpdfl_pc_gaussian_builder *>(c);
00309 }
00310 break;
00311 default:
00312 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, vpdfl_pc_gaussian &)\n"
00313 << " Unknown version number "<< version << vcl_endl;
00314 bfs.is().clear(vcl_ios::badbit);
00315 return;
00316 }
00317 }
00318
00319
00320
00321 const vpdfl_pc_gaussian_builder * vpdfl_pc_gaussian::partition_chooser() const
00322 {
00323 return partition_chooser_;
00324 }
00325
00326
00327
00328 void vpdfl_pc_gaussian::set_partition_chooser(
00329 const vpdfl_pc_gaussian_builder * partition_chooser)
00330 {
00331 delete partition_chooser_;
00332 if (partition_chooser)
00333 partition_chooser_ = static_cast<vpdfl_pc_gaussian_builder *>(partition_chooser->clone());
00334 else
00335 partition_chooser_ = 0;
00336 }