PLearn 0.1
|
00001 00002 // -*- C++ -*- 00003 00004 // ClassifierFromConditionalPDistribution.cc 00005 // 00006 // Copyright (C) 2003-2005 Pascal Vincent & Olivier Delalleau 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: ClassifierFromConditionalPDistribution.cc 4412 2005-11-02 19:00:20Z tihocan $ 00038 ******************************************************* */ 00039 00041 #include "ClassifierFromConditionalPDistribution.h" 00042 #include <plearn/io/PPath.h> 00043 00044 namespace PLearn { 00045 using namespace std; 00046 00047 ClassifierFromConditionalPDistribution::ClassifierFromConditionalPDistribution() 00048 : nclasses(-1), 00049 output_type("predicted_class") 00050 {} 00051 00052 PLEARN_IMPLEMENT_OBJECT( 00053 ClassifierFromConditionalPDistribution, 00054 "Classifier that takes a ConditionalPDistribution and classifies with it.", 00055 "ClassifierFromConditionalPDistribution classifies by finding the target\n" 00056 "class y that maximizes p(y|x), where x is the input.\n"); 00057 00059 // declareOptions // 00061 void ClassifierFromConditionalPDistribution::declareOptions(OptionList& ol) 00062 { 00063 00064 // Build options. 00065 00066 declareOption(ol, "nclasses", &ClassifierFromConditionalPDistribution::nclasses, OptionBase::buildoption, 00067 "The number of classes"); 00068 00069 declareOption(ol, "conditional_distribution", &ClassifierFromConditionalPDistribution::pcd, OptionBase::buildoption, 00070 "ConditionalPDistribution that computes p(y|x) for all possible classes y."); 00071 00072 declareOption(ol, "output_type", &ClassifierFromConditionalPDistribution::output_type, OptionBase::buildoption, 00073 "Output type. Choose among: \n" 00074 "- \"predicted_class\"\n" 00075 "- \"class_probabilities\"\n" 00076 "- \"class_log-probabilities\")\n" 00077 "Note that this may change the value of output_defs of the conditional_distribution."); 00078 00079 // Now call the parent class' declareOptions 00080 inherited::declareOptions(ol); 00081 } 00082 00084 // build // 00086 void ClassifierFromConditionalPDistribution::build() 00087 { 00088 inherited::build(); 00089 build_(); 00090 } 00091 00093 // build_ // 00095 void ClassifierFromConditionalPDistribution::build_() 00096 { 00097 if(pcd && train_set) 00098 { 00099 PP<Dictionary> target_dict = train_set->getDictionary(inputsize()); 00100 if(!target_dict && nclasses <= 0) PLERROR("In ClassifierFromConditionalPDistribution::build_(): There is not way to know what are the possible targets (nclasses <= 0 and no Dictionary for target field)"); 00101 if(target_dict) nclasses = -1; 00102 if(output_type == "predicted_class" || output_type == "class_log-probabilities") pcd->outputs_def = "l"; 00103 else if (output_type == "class_probabilities") pcd->outputs_def = "d"; 00104 else PLERROR("ClassifierFromConditionalPDistribution::build_(): output_type %s is not supported", output_type.c_str()); 00105 00106 pcd_input.resize(train_set->inputsize() + train_set->targetsize()); 00107 pcd_output.resize(1); 00108 } 00109 00110 } 00111 00113 // makeDeepCopyFromShallowCopy // 00115 void ClassifierFromConditionalPDistribution::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00116 { 00117 inherited::makeDeepCopyFromShallowCopy(copies); 00118 deepCopyField(pcd, copies); 00119 deepCopyField(target_values, copies); 00120 deepCopyField(pcd_input, copies); 00121 } 00122 00124 // outputsize // 00126 int ClassifierFromConditionalPDistribution::outputsize() const 00127 { 00128 if(nclasses > 0) return nclasses; 00129 else 00130 { 00131 train_set->getValues(0,inputsize(),target_values); 00132 return target_values.length(); 00133 } 00134 } 00135 00137 // forget // 00139 void ClassifierFromConditionalPDistribution::forget() 00140 { 00141 stage=0; 00142 pcd->forget(); 00143 } 00144 00146 // train // 00148 void ClassifierFromConditionalPDistribution::train() 00149 { 00150 if(targetsize()!=1) 00151 PLERROR("In ClassifierFromConditionalPDistribution::train - Expecting a targetsize of 1, not %d !!",targetsize()); 00152 00153 if(nstages<stage) // asking to revert to a previous stage! 00154 forget(); // reset the learner to stage=0 00155 00156 if(stage==0) 00157 { 00158 pcd->setExperimentDirectory(getExperimentDirectory() / "PCD"); 00159 train_set->defineSizes(inputsize()+1,targetsize()-1,weightsize()); 00160 pcd->setTrainingSet(train_set); 00161 PP<VecStatsCollector> train_stats = new VecStatsCollector(); 00162 train_stats->setFieldNames(pcd->getTrainCostNames()); 00163 pcd->setTrainStatsCollector(train_stats); 00164 pcd->nstages = nstages; 00165 if (verbosity >= 2) 00166 pout << ">>> Training ConditionalPDistribution" << endl; 00167 pcd->train(); 00168 if (verbosity >= 2) 00169 pout << ">>> Training is over" << endl; 00170 train_set->defineSizes(inputsize(),targetsize(),weightsize()); 00171 } 00172 stage = nstages; // trained! 00173 } 00174 00176 // computeOutput // 00178 void ClassifierFromConditionalPDistribution::computeOutput(const Vec& input, Vec& output) const 00179 { 00180 pcd_input.subVec(0,inputsize()) << input; 00181 if(nclasses <= 0) 00182 { 00183 train_set->getValues(input, inputsize(),target_values); 00184 output.resize(target_values.length()); 00185 for(int i=0; i<target_values.length(); i++) 00186 { 00187 pcd_input[inputsize()] = target_values[i]; 00188 pcd->computeOutput(pcd_input, pcd_output); 00189 output[i] = pcd_output[0]; 00190 } 00191 } 00192 else 00193 { 00194 output.resize(nclasses); 00195 for(int c=0; c<nclasses; c++) 00196 { 00197 pcd_input[inputsize()] = c; 00198 pcd->computeOutput(pcd_input, pcd_output); 00199 output[c] = pcd_output[0]; 00200 } 00201 } 00202 00203 if(output_type == "predicted_class") 00204 { 00205 if(nclasses <= 0) 00206 output[0] = (int)target_values[argmax(output)]; 00207 else 00208 output[0] = argmax(output); 00209 output.resize(1); 00210 } 00211 } 00212 00214 // computeCostsFromOutputs // 00216 void ClassifierFromConditionalPDistribution::computeCostsFromOutputs(const Vec& input, const Vec& output, 00217 const Vec& target, Vec& costs) const 00218 { 00219 if(output_type == "predicted_class") 00220 { 00221 costs[0] = (int) (target[0] != output[0]); 00222 } 00223 else 00224 { 00225 int c; 00226 if(nclasses <= 0) 00227 { 00228 train_set->getValues(input,inputsize(),target_values); 00229 c = target_values.find(target[0]); 00230 } 00231 else 00232 c = (int)target[0]; 00233 costs[0] = (int) (argmax(output) != c); 00234 if(output_type == "class_probabilities") costs[1] = safeflog(output[c]); 00235 else costs[1] = output[c]; 00236 } 00237 } 00238 00240 // getTestCostNames // 00242 TVec<string> ClassifierFromConditionalPDistribution::getTestCostNames() const 00243 { 00244 TVec<string> cnames; 00245 if(output_type == "predicted_class") 00246 { 00247 cnames.resize(1); 00248 cnames[0] = "class_error"; 00249 } 00250 else 00251 { 00252 cnames.resize(2); 00253 cnames[0] = "class_error"; 00254 cnames[1] = "NLL"; 00255 } 00256 return cnames; 00257 } 00258 00260 // getTrainCostNames // 00262 TVec<string> ClassifierFromConditionalPDistribution::getTrainCostNames() const 00263 { 00264 return TVec<string>(); 00265 } 00266 00267 } // end of namespace PLearn 00268 00269 00270 /* 00271 Local Variables: 00272 mode:c++ 00273 c-basic-offset:4 00274 c-file-style:"stroustrup" 00275 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00276 indent-tabs-mode:nil 00277 fill-column:79 00278 End: 00279 */ 00280 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :