Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

ClassifierFromDensity.cc

Go to the documentation of this file.
00001 00002 // -*- C++ -*- 00003 00004 // ClassifierFromDensity.cc 00005 // 00006 // Copyright (C) 2003 Pascal Vincent 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are met: 00010 // 00011 // 1. Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // 00014 // 2. Redistributions in binary form must reproduce the above copyright 00015 // notice, this list of conditions and the following disclaimer in the 00016 // documentation and/or other materials provided with the distribution. 00017 // 00018 // 3. The name of the authors may not be used to endorse or promote 00019 // products derived from this software without specific prior written 00020 // permission. 00021 // 00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00033 // This file is part of the PLearn library. For more information on the PLearn 00034 // library, go to the PLearn Web site at www.plearn.org 00035 00036 /* ******************************************************* 00037 * $Id: ClassifierFromDensity.cc,v 1.11 2004/07/21 16:30:55 chrish42 Exp $ 00038 ******************************************************* */ 00039 00041 #include "ClassifierFromDensity.h" 00042 #include <plearn/vmat/ConcatColumnsVMatrix.h> 00043 #include <plearn/vmat/VMat_maths.h> 00044 #include <plearn/ker/Kernel.h> 00045 #include <plearn/ker/ClassErrorCostFunction.h> 00046 #include <plearn/ker/NegLogProbCostFunction.h> 00047 00048 namespace PLearn { 00049 using namespace std; 00050 00051 ClassifierFromDensity::ClassifierFromDensity() 00052 :nclasses(-1), output_log_probabilities(0), normalize_probabilities(1) 00053 { 00054 // build_(); 00055 } 00056 00057 PLEARN_IMPLEMENT_OBJECT(ClassifierFromDensity, "A classifier built from density estimators using Bayes' rule.", 00058 "ClassifierFromDensity allowd to build a classifier\n" 00059 "by building one density estimator for each class, \n" 00060 "and using Bayes rule to combine them. \n"); 00061 00062 void ClassifierFromDensity::declareOptions(OptionList& ol) 00063 { 00064 declareOption(ol, "nclasses", &ClassifierFromDensity::nclasses, OptionBase::buildoption, 00065 "The number of classes"); 00066 declareOption(ol, "estimators", &ClassifierFromDensity::estimators, OptionBase::buildoption, 00067 "The array of density estimators, one for each class. \n" 00068 "You may also specify just one that will be replicated as many times as there are classes."); 00069 declareOption(ol, "log_priors", &ClassifierFromDensity::log_priors, OptionBase::buildoption, 00070 "The log of the class prior probabilities"); 00071 declareOption(ol, "output_log_probabilities", &ClassifierFromDensity::output_log_probabilities, OptionBase::buildoption, 00072 "Whether computeOutput yields log-probabilities or probabilities (of classes given inputs)"); 00073 declareOption(ol, "normalize_probabilities", &ClassifierFromDensity::normalize_probabilities, OptionBase::buildoption, 00074 "Whether to normalize the probabilities (if not just compute likelihood * prior for each class)"); 00075 00076 // Now call the parent class' declareOptions 00077 inherited::declareOptions(ol); 00078 } 00079 00080 void ClassifierFromDensity::build_() 00081 { 00082 if(estimators.size()==1) 00083 { 00084 estimators.resize(nclasses); 00085 for(int i=1; i<nclasses; i++) 00086 estimators[i] = PLearn::deepCopy(estimators[0]); 00087 } 00088 else if(estimators.size()!=nclasses) 00089 PLERROR("In ClassifierFromDensity: specified %d estimators but there are %d classes",estimators.size(), nclasses); 00090 } 00091 00092 // ### Nothing to add here, simply calls build_ 00093 void ClassifierFromDensity::build() 00094 { 00095 inherited::build(); 00096 build_(); 00097 } 00098 00099 00100 void ClassifierFromDensity::makeDeepCopyFromShallowCopy(map<const void*, void*>& copies) 00101 { 00102 inherited::makeDeepCopyFromShallowCopy(copies); 00103 deepCopyField(estimators, copies); 00104 deepCopyField(log_priors, copies); 00105 } 00106 00107 00108 int ClassifierFromDensity::outputsize() const 00109 { 00110 return nclasses; 00111 } 00112 00113 void ClassifierFromDensity::forget() 00114 { 00115 stage=0; 00116 for(int c=0; c<estimators.length(); c++) 00117 estimators[c]->forget(); 00118 } 00119 00120 void ClassifierFromDensity::train() 00121 { 00122 if(targetsize()!=1) 00123 PLERROR("In ClassifierFromDensity: expecting a targetsize of 1 (class index between 0 and nclasses-1), not %d !!",targetsize()); 00124 00125 if(!train_stats) // make a default stats collector, in case there's none 00126 train_stats = new VecStatsCollector(); 00127 00128 if(nstages<stage) // asking to revert to a previous stage! 00129 forget(); // reset the learner to stage=0 00130 00131 if(stage==0) 00132 { 00133 log_priors.resize(nclasses); 00134 00135 map<real, TVec<int> > indices = indicesOfOccurencesInColumn(train_set, inputsize()); 00136 00137 for(int c=0; c<nclasses; c++) 00138 log_priors[c] = log(real(indices[real(c)].length())) - log(real(train_set.length())); // how many do we have? 00139 00140 string expd = getExperimentDirectory(); 00141 00142 for(int c=0; c<nclasses; c++) 00143 { 00144 if(verbosity>=1) 00145 cerr << ">>> Training class " << c; 00146 VMat set_c = train_set.rows(indices[c]); 00147 int in_sz = set_c->inputsize(); 00148 int targ_sz = set_c->targetsize(); 00149 int we_sz = set_c->weightsize(); 00150 // removing target from set 00151 if(we_sz==0) 00152 { 00153 set_c = set_c.subMatColumns(0,in_sz); 00154 set_c->defineSizes(in_sz, 0, 0); 00155 } 00156 else // argh, there are some weights... 00157 { 00158 set_c = hconcat(set_c.subMatColumns(0,in_sz), set_c.subMatColumns(in_sz+targ_sz,we_sz)); 00159 set_c->defineSizes(in_sz,0,we_sz); 00160 } 00161 if(expd!="") 00162 estimators[c]->setExperimentDirectory(expd+"Class"+tostring(c)); 00163 if(verbosity>=1) 00164 cerr << " ( " << set_c.length() << " samples)" << endl; 00165 estimators[c]->setTrainingSet(set_c); 00166 estimators[c]->train(); 00167 } 00168 stage = 1; // trained! 00169 } 00170 } 00171 00172 void ClassifierFromDensity::computeOutput(const Vec& input, Vec& output) const 00173 { 00174 output.resize(nclasses); 00175 00176 real logprob; 00177 Vec logprobvec(1,&logprob); 00178 double log_of_sumprob = 0.; 00179 00180 for(int c=0; c<nclasses; c++) 00181 { 00182 estimators[c]->computeOutput(input, logprobvec); 00183 double logprob_c = logprob + log_priors[c]; // multiply p by the prior 00184 output[c] = logprob_c; 00185 if (normalize_probabilities) 00186 { 00187 if(c==0) 00188 log_of_sumprob = logprob_c; 00189 else 00190 log_of_sumprob = logadd(log_of_sumprob, logprob_c); 00191 } 00192 } 00193 00194 // cerr << "unnormalized logprob: " << output << endl; 00195 // cerr << "log of sumprob: " << log_of_sumprob << endl; 00196 00197 if (normalize_probabilities) 00198 output -= real(log_of_sumprob); // divide by the sum 00199 else if (nclasses==2) 00200 output[1] -= output[0]; 00201 00202 // make it probabilities rather than log probabilities... 00203 if (!output_log_probabilities) 00204 exp(output, output); 00205 00206 // cout << "output: " << output << endl; 00207 // cout << "argmax: " << argmax(output) << endl; 00208 } 00209 00210 void ClassifierFromDensity::computeCostsFromOutputs(const Vec& input, const Vec& output, 00211 const Vec& target, Vec& costs) const 00212 { 00213 static CostFunc cl_er; 00214 static CostFunc cond_p; 00215 if(!cl_er) 00216 cl_er = class_error(); 00217 if(!cond_p) 00218 cond_p = condprob_cost(); 00219 00220 costs.resize(2); 00221 costs[0] = cl_er->evaluate(output, target); 00222 costs[1] = cond_p->evaluate(output, target); 00223 } 00224 00225 TVec<string> ClassifierFromDensity::getTestCostNames() const 00226 { 00227 TVec<string> cnames(2); 00228 cnames[0] = "class_error"; 00229 cnames[1] = "condprob_cost"; 00230 return cnames; 00231 } 00232 00233 TVec<string> ClassifierFromDensity::getTrainCostNames() const 00234 { 00235 return TVec<string>(); 00236 } 00237 00238 00239 00240 } // end of namespace PLearn

Generated on Tue Aug 17 15:49:24 2004 for PLearn by doxygen 1.3.7