PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // CompareLearner.cc 00004 // 00005 // Copyright (C) 2004 Hugo Larochelle 00006 // 00007 // Redistribution and use in source and binary forms, with or without 00008 // modification, are permitted provided that the following conditions are met: 00009 // 00010 // 1. Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // 3. The name of the authors may not be used to endorse or promote 00018 // products derived from this software without specific prior written 00019 // permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 // 00032 // This file is part of the PLearn library. For more information on the PLearn 00033 // library, go to the PLearn Web site at www.plearn.org 00034 00035 /* ******************************************************* 00036 * $Id: CompareLearner.cc 3994 2005-08-25 13:35:03Z chapados $ 00037 ******************************************************* */ 00038 00039 // Authors: Hugo Larochelle 00040 00044 #include "CompareLearner.h" 00045 #include <plearn/io/fileutils.h> 00046 00047 namespace PLearn { 00048 using namespace std; 00049 00050 CompareLearner::CompareLearner() 00051 : learners(0) 00052 { 00053 build_(); 00054 } 00055 00056 PLEARN_IMPLEMENT_OBJECT(CompareLearner, "Learner that trains and compares different learners ", 00057 "This learner takes different learners, trains them and computes their\n" 00058 "common costs in order to compare them. The learners and the names of the \n" 00059 "learners are given by the user, and the common costs shared by all the \n" 00060 "learners are also specified by the user. The cost name [LEARNER]::[COST] \n" 00061 "is the name of the cost [COST] for the learner named [LEARNER]. If a specifed learner \n" 00062 "doesn't use this cost, its cost value is always MISSING_VALUE. Also, \n" 00063 "the cost names difference_[COST]_[LEARNER1]_VS_[LEARNER2] and \n" 00064 "abs_difference_[COST]_[LEARNER1]_VS_[LEARNER2] are the difference and \n" 00065 "absolute difference of [COST]::[LEARNER1] and [COST]::[LEARNER2]. Note that \n" 00066 "[LEARNER1] must appear before [LEARNER2] in the learner_names vector." 00067 ); 00068 void CompareLearner::declareOptions(OptionList& ol) 00069 { 00070 declareOption(ol, "learners", &CompareLearner::learners, OptionBase::buildoption, 00071 "learners to compare"); 00072 declareOption(ol, "common_costs", &CompareLearner::common_costs, OptionBase::buildoption, 00073 "common costs of the learners to compare"); 00074 declareOption(ol, "learner_names", &CompareLearner::learner_names, OptionBase::buildoption, 00075 "names of the learners"); 00076 00077 inherited::declareOptions(ol); 00078 } 00079 00080 void CompareLearner::build_() 00081 { 00082 n_learners = learners.length(); 00083 if(n_learners > 0) 00084 { 00085 learners_outputsize = learners[0]->outputsize(); 00086 if(learner_names.length() != n_learners) PLERROR("Number of learner names is different from number of learners"); 00087 costs_indexes.resize(n_learners,common_costs.length()); 00088 TVec<string> test_costs; 00089 for(int i=0; i<n_learners; i++) 00090 { 00091 learners[i]->build(); 00092 test_costs = learners[i]->getTestCostNames(); 00093 for(int c=0; c<common_costs.length(); c++) 00094 { 00095 costs_indexes(i,c) = test_costs.find(common_costs[c]); 00096 } 00097 } 00098 } 00099 } 00100 00101 void CompareLearner::build() 00102 { 00103 inherited::build(); 00104 build_(); 00105 } 00106 00107 00108 void CompareLearner::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00109 { 00110 inherited::makeDeepCopyFromShallowCopy(copies); 00111 00112 deepCopyField(learners, copies); 00113 deepCopyField(learner_names, copies); 00114 deepCopyField(common_costs, copies); 00115 deepCopyField(costs_indexes, copies); 00116 00117 //PLERROR("CompareLearner::makeDeepCopyFromShallowCopy not fully (correctly) implemented yet!"); 00118 } 00119 00120 00121 int CompareLearner::outputsize() const 00122 { 00123 if(n_learners == 0) return 0; 00124 else return n_learners * learners_outputsize; 00125 } 00126 00127 void CompareLearner::forget() 00128 { 00129 for(int i=0; i<learners.length(); i++) 00130 learners[i]->forget(); 00131 } 00132 00133 void CompareLearner::train() 00134 { 00135 for(int i=0; i<n_learners; i++) 00136 learners[i]->train(); 00137 } 00138 00139 00140 void CompareLearner::computeOutput(const Vec& input, Vec& output) const 00141 { 00142 output.resize(outputsize()); 00143 Vec output_i; 00144 for(int i=0; i<n_learners; i++) 00145 { 00146 output_i = output.subVec(i*learners_outputsize,learners_outputsize); 00147 learners[i]->computeOutput(input,output_i); 00148 } 00149 } 00150 00151 void CompareLearner::computeCostsFromOutputs(const Vec& input, const Vec& output, 00152 const Vec& target, Vec& costs) const 00153 { 00154 Vec one_learner_costs; 00155 costs.resize(0); 00156 Vec output_i; 00157 for(int i=0; i<n_learners; i++) 00158 { 00159 one_learner_costs.resize(learners[i]->getTestCostNames().length()); 00160 output_i = output.subVec(i*learners_outputsize,learners_outputsize); 00161 learners[i]->computeCostsFromOutputs(input, output_i,target,one_learner_costs); 00162 for(int c=0; c<common_costs.length(); c++) 00163 { 00164 if(costs_indexes(i,c) == -1) 00165 costs.append(MISSING_VALUE); 00166 else 00167 costs.append(one_learner_costs[costs_indexes(i,c)]); 00168 00169 } 00170 } 00171 00172 for ( int m1=0; m1 < n_learners; m1++ ) 00173 for ( int m2=(m1+1); m2 < n_learners; m2++ ) 00174 for ( int cc=0; cc < common_costs.length(); cc++ ) 00175 { 00176 real diff = costs[m1*common_costs.length()+cc]-costs[m2*common_costs.length()+cc]; 00177 costs.append(diff); 00178 costs.append(fabs(diff)); 00179 } 00180 } 00181 00182 TVec<string> CompareLearner::getTestCostNames() const 00183 { 00184 TVec<string> cost_names(0); 00185 00186 for(int i=0; i<n_learners; i++) 00187 { 00188 for(int c=0; c<common_costs.length(); c++) 00189 { 00190 cost_names.append(learner_names[i] + "::" + common_costs[c]); 00191 } 00192 } 00193 00194 for ( int m1=0; m1 < n_learners; m1++ ) 00195 for ( int m2=(m1+1); m2 < n_learners; m2++ ) 00196 for ( int cc=0; cc < common_costs.length(); cc++ ) 00197 { 00198 string postfix = common_costs[cc] + "_" + learner_names[m1] + "_VS_" + learner_names[m2]; 00199 cost_names.append( "difference_" + postfix ); 00200 cost_names.append( "abs_difference_" + postfix ); 00201 } 00202 00203 return cost_names; 00204 } 00205 00206 TVec<string> CompareLearner::getTrainCostNames() const 00207 { 00208 TVec<string> cost_names(0); 00209 TVec<string> cost_names_i; 00210 for(int i=0; i<n_learners; i++) 00211 { 00212 cost_names_i = learners[i]->getTrainCostNames(); 00213 for(int c=0; c<cost_names_i.length(); c++) 00214 cost_names.append(learner_names[i] + "::" + cost_names_i[c]); 00215 } 00216 00217 return cost_names; 00218 } 00219 00220 void CompareLearner::setTrainStatsCollector(PP<VecStatsCollector> statscol) 00221 { 00222 PP<VecStatsCollector> stat_i; 00223 for(int i=0; i<n_learners; i++) 00224 { 00225 stat_i = new VecStatsCollector(); 00226 learners[i]->setTrainStatsCollector(stat_i); 00227 } 00228 } 00229 00230 void CompareLearner::setTrainingSet(VMat training_set, bool call_forget) 00231 { 00232 for(int i=0; i<n_learners; i++) 00233 { 00234 learners[i]->setTrainingSet(training_set,call_forget); 00235 } 00236 if (call_forget) 00237 forget(); 00238 } 00239 00240 void CompareLearner::setValidationSet(VMat validset) 00241 { 00242 for(int i=0; i<n_learners; i++) 00243 { 00244 learners[i]->setValidationSet(validset); 00245 } 00246 } 00247 00248 void CompareLearner::setExperimentDirectory(const PPath& the_expdir) 00249 { 00250 if(the_expdir=="") 00251 { 00252 expdir = ""; 00253 for(int i=0; i<n_learners; i++) 00254 { 00255 learners[i]->setExperimentDirectory(the_expdir); 00256 } 00257 } 00258 else 00259 { 00260 if(!force_mkdir(the_expdir)) 00261 PLERROR("In PLearner::setExperimentDirectory Could not create experiment directory %s",the_expdir.c_str()); 00262 expdir = the_expdir.absolute(); 00263 string learner_expdir; 00264 for(int i=0; i<n_learners; i++) 00265 { 00266 learner_expdir = the_expdir.absolute() + "_" + learner_names[i]; 00267 learners[i]->setExperimentDirectory(learner_expdir); 00268 } 00269 } 00270 } 00271 00272 } // end of namespace PLearn 00273 00274 00275 /* 00276 Local Variables: 00277 mode:c++ 00278 c-basic-offset:4 00279 c-file-style:"stroustrup" 00280 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00281 indent-tabs-mode:nil 00282 fill-column:79 00283 End: 00284 */ 00285 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :