contrib/mul/clsfy/clsfy_simple_adaboost.cxx
Go to the documentation of this file.
00001 //:
00002 // \file
00003 // \brief Classifier using adaboost on combinations of simple 1D classifiers
00004 // \author Tim Cootes
00005 
00006 //=======================================================================
00007 
00008 #include "clsfy_simple_adaboost.h"
00009 #include <vcl_string.h>
00010 #include <vcl_iostream.h>
00011 #include <vcl_vector.h>
00012 #include <vcl_cassert.h>
00013 #include <vcl_cmath.h>
00014 #include <vsl/vsl_binary_io.h>
00015 #include <vsl/vsl_binary_loader.h>
00016 #include <vsl/vsl_vector_io.h>
00017 #include <vnl/io/vnl_io_matrix.h>
00018 #include <vnl/io/vnl_io_vector.h>
00019 
00020 //=======================================================================
00021 //: Default constructor
00022 clsfy_simple_adaboost::clsfy_simple_adaboost()
00023 : n_clfrs_used_(-1) , n_dims_(-1)
00024 {
00025 }
00026 
00027 clsfy_simple_adaboost::clsfy_simple_adaboost(const clsfy_simple_adaboost& c)
00028   : clsfy_classifier_base()
00029 {
00030   *this = c;
00031 }
00032 
00033 //: Copy operator
00034 clsfy_simple_adaboost& clsfy_simple_adaboost::operator=(const clsfy_simple_adaboost& c)
00035 {
00036   delete_stuff();
00037 
00038   int n = c.classifier_1d_.size();
00039   classifier_1d_.resize(n);
00040   for (int i=0;i<n;++i)
00041     classifier_1d_[i] = c.classifier_1d_[i]->clone();
00042 
00043   alphas_ = c.alphas_;
00044   index_ = c.index_;
00045   return *this;
00046 }
00047 
00048 //: Delete objects on heap
00049 void clsfy_simple_adaboost::delete_stuff()
00050 {
00051   for (unsigned int i=0;i<classifier_1d_.size();++i)
00052     delete classifier_1d_[i];
00053 
00054   classifier_1d_.resize(0);
00055 
00056   alphas_.resize(0);
00057   index_.resize(0);
00058   n_clfrs_used_= -1;
00059 }
00060 
00061 //: Destructor
00062 clsfy_simple_adaboost::~clsfy_simple_adaboost()
00063 {
00064   delete_stuff();
00065 }
00066 
00067 
00068 //: Comparison
00069 bool clsfy_simple_adaboost::operator==(const clsfy_simple_adaboost& x) const
00070 {
00071   if (x.classifier_1d_.size() != classifier_1d_.size() ) return false;
00072   int n= x.classifier_1d_.size();
00073   for (int i=0; i<n; ++i)
00074     if (!(*(x.classifier_1d_[i]) == *(classifier_1d_[i]) )) return false;
00075 
00076   return x.alphas_ == alphas_ &&
00077          x.index_ == index_;
00078 }
00079 
00080 
00081 //: Set parameters.  Clones taken of *classifier[i]
00082 void clsfy_simple_adaboost::set_parameters(
00083                       const vcl_vector<clsfy_classifier_1d*>& classifier,
00084                       const vcl_vector<double>& alphas,
00085                       const vcl_vector<int>& index)
00086 {
00087   delete_stuff();
00088 
00089   int n = classifier.size();
00090   classifier_1d_.resize(n);
00091   for (int i=0;i<n;++i)
00092     classifier_1d_[i] = classifier[i]->clone();
00093 
00094   alphas_ = alphas;
00095   index_= index;
00096 }
00097 
00098 
00099 //: Clear all alphas and classifiers
00100 void clsfy_simple_adaboost::clear()
00101 {
00102   delete_stuff();
00103 }
00104 
00105 
00106 //: Add weak classifier and alpha value
00107 // nb also changes n_clfrs_used to use all current weak classifiers
00108 void clsfy_simple_adaboost::add_classifier(clsfy_classifier_1d* c1d,
00109                                            double alpha,
00110                                            int index)
00111 {
00112   classifier_1d_.push_back(c1d->clone());
00113   alphas_.push_back(alpha);
00114   index_.push_back(index);
00115   n_clfrs_used_=alphas_.size();
00116 }
00117 
00118 
00119 //: Classify the input vector.
00120 // Returns either 1 (for positive class) or 0 (for negative class)
00121 unsigned clsfy_simple_adaboost::classify(const vnl_vector<double> &v) const
00122 {
00123   //vcl_cout<<"alphas_.size()= "<<alphas_.size()<<vcl_endl;
00124   //vcl_cout<<"n_clfrs_used_= "<<n_clfrs_used_<<vcl_endl;
00125   assert ( n_clfrs_used_ >= 0);
00126   assert ( (unsigned)n_clfrs_used_ <= alphas_.size() );
00127   assert ( n_dims_ >= 0);
00128   assert ( v.size() == (unsigned)n_dims_ );
00129 
00130 
00131   double sum1 = 0.0, sum2 =0.0;
00132   for (int i=0;i<n_clfrs_used_;++i)
00133   {
00134     //vcl_cout<<"index_["<<i<<"]= "<<index_[i]<<vcl_endl;
00135     sum1 += alphas_[i]*classifier_1d_[i]->classify(v[ index_[i] ]);
00136     sum2 += alphas_[i];
00137   }
00138 
00139   if (sum1 - sum2 * 0.5 > 0.0) return 1;
00140   return 0;
00141 }
00142 
00143 //=======================================================================
00144 
00145 //: Find the posterior probability of the input being in the positive class.
00146 // The result is outputs(0)
00147 void clsfy_simple_adaboost::class_probabilities(vcl_vector<double> &outputs,
00148   const vnl_vector<double> &input) const
00149 {
00150   outputs.resize(1);
00151   outputs[0] = 1.0 / (1.0 + vcl_exp(-log_l(input)));
00152 }
00153 
00154 //=======================================================================
00155 
00156 //: Log likelihood of being in the positive class.
00157 // Class probability = 1 / (1+exp(-log_l))
00158 double clsfy_simple_adaboost::log_l(const vnl_vector<double> &v) const
00159 {
00160   assert ( n_clfrs_used_ >= 0);
00161   assert ( (unsigned)n_clfrs_used_ <= alphas_.size() );
00162   //assert ( n_dims_ != -1);
00163   //assert ( v.size() == n_dims_ );
00164   double sum1 = 0.0, sum2= 0.0;
00165   for (int i=0;i<n_clfrs_used_;++i)
00166   {
00167     sum1 += alphas_[i]*classifier_1d_[i]->classify(v[ index_[i] ]);
00168     sum2 += alphas_[i];
00169   }
00170 
00171   return sum1 - sum2 * 0.5;
00172 }
00173 
00174 //=======================================================================
00175 
00176 vcl_string clsfy_simple_adaboost::is_a() const
00177 {
00178   return vcl_string("clsfy_simple_adaboost");
00179 }
00180 
00181 //=======================================================================
00182 
00183 bool clsfy_simple_adaboost::is_class(vcl_string const& s) const
00184 {
00185   return s == clsfy_simple_adaboost::is_a() || clsfy_classifier_base::is_class(s);
00186 }
00187 
00188 //=======================================================================
00189 
00190 // required if data is present in this class
00191 void clsfy_simple_adaboost::print_summary(vcl_ostream& os) const
00192 {
00193   int n = alphas_.size();
00194   assert( alphas_.size() == index_.size() );
00195   for (int i=0;i<n;++i)
00196   {
00197     os<<" Alpha: "<<alphas_[i]
00198       <<" Index: "<<index_[i]
00199       <<" Classifier: "<<classifier_1d_[i]<<'\n';
00200   }
00201 }
00202 
00203 //=======================================================================
00204 
00205 short clsfy_simple_adaboost::version_no() const
00206 {
00207   return 1;
00208 }
00209 
00210 //=======================================================================
00211 
00212 void clsfy_simple_adaboost::b_write(vsl_b_ostream& bfs) const
00213 {
00214   vsl_b_write(bfs,version_no());
00215   vsl_b_write(bfs,classifier_1d_);
00216   vsl_b_write(bfs,alphas_);
00217   vsl_b_write(bfs,index_);
00218 }
00219 
00220 //=======================================================================
00221 
00222 void clsfy_simple_adaboost::b_read(vsl_b_istream& bfs)
00223 {
00224   if (!bfs) return;
00225 
00226   delete_stuff();
00227 
00228   short version;
00229   vsl_b_read(bfs,version);
00230   switch (version)
00231   {
00232     case (1):
00233       vsl_b_read(bfs,classifier_1d_);
00234       vsl_b_read(bfs,alphas_);
00235       vsl_b_read(bfs,index_);
00236 
00237       // set default number of classifiers used to be the maximum number
00238       n_clfrs_used_= index_.size();
00239 
00240       break;
00241     default:
00242       vcl_cerr << "I/O ERROR: clsfy_simple_adaboost::b_read(vsl_b_istream&)\n"
00243                << "           Unknown version number "<< version << '\n';
00244       bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00245   }
00246 }