PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // TargetEncodingLearner.cc 00004 // 00005 // Copyright (C) 2006 Xavier Sanint-Mleux 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 // Authors: Xavier Saint-Mleux 00036 00040 #include "TargetEncodingLearner.h" 00041 #include <plearn/vmat/EncodedVMatrix.h> 00042 00043 namespace PLearn { 00044 using namespace std; 00045 00046 PLEARN_IMPLEMENT_OBJECT(TargetEncodingLearner,"", 00047 "This learner encodes input data so that field values are replaced by the weighted average target for that value.\n" 00048 "Fields that have more than max_nvals_for_encoding different values are not encoded.\n"); 00049 00050 TargetEncodingLearner::TargetEncodingLearner() 00051 :max_nvals_for_encoding(1000), 00052 sublearner(0), 00053 encodings(), 00054 encode_col(), 00055 mean(0.), 00056 encodings_learnt(false) 00057 { 00058 } 00059 00060 void TargetEncodingLearner::declareOptions(OptionList& ol) 00061 { 00062 declareOption(ol, "max_nvals_for_encoding", &TargetEncodingLearner::max_nvals_for_encoding, 00063 OptionBase::buildoption, 00064 "Max number of different values for a field to be encoded.\n"); 00065 00066 declareOption(ol, "sublearner", &TargetEncodingLearner::sublearner, 00067 OptionBase::buildoption, 00068 "Learner to be trained/tested on the encoded dataset.\n"); 00069 00070 declareOption(ol, "encodings", &TargetEncodingLearner::encodings, 00071 OptionBase::learntoption, 00072 "Learnt encodings for the trainset.\n"); 00073 00074 declareOption(ol, "encode_col", &TargetEncodingLearner::encode_col, 00075 OptionBase::learntoption, 00076 "Wether each col. should be encoded.\n"); 00077 00078 declareOption(ol, "mean", &TargetEncodingLearner::mean, 00079 OptionBase::learntoption, 00080 "Weighted mean all targets.\n"); 00081 00082 declareOption(ol, "encodings_learnt", &TargetEncodingLearner::encodings_learnt, 00083 OptionBase::learntoption, 00084 "Wether encodings have already been learnt.\n"); 00085 00086 // Now call the parent class' declareOptions 00087 inherited::declareOptions(ol); 00088 } 00089 00090 void TargetEncodingLearner::build_() 00091 { 00092 // ### This method should do the real building of the object, 00093 // ### according to set 'options', in *any* situation. 00094 // ### Typical situations include: 00095 // ### - Initial building of an object from a few user-specified options 00096 // ### - Building of a "reloaded" object: i.e. from the complete set of 00097 // ### all serialised options. 00098 // ### - Updating or "re-building" of an object after a few "tuning" 00099 // ### options have been modified. 00100 // ### You should assume that the parent class' build_() has already been 00101 // ### called. 00102 encodings_learnt= false; 00103 } 00104 00105 // ### Nothing to add here, simply calls build_ 00106 void TargetEncodingLearner::build() 00107 { 00108 inherited::build(); 00109 build_(); 00110 } 00111 00112 00113 void TargetEncodingLearner::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00114 { 00115 inherited::makeDeepCopyFromShallowCopy(copies); 00116 00117 // ### Call deepCopyField on all "pointer-like" fields 00118 // ### that you wish to be deepCopied rather than 00119 // ### shallow-copied. 00120 // ### ex: 00121 // deepCopyField(trainvec, copies); 00122 00123 // ### Remove this line when you have fully implemented this method. 00124 PLERROR("TargetEncodingLearner::makeDeepCopyFromShallowCopy not fully (correctly) implemented yet!"); 00125 } 00126 00127 00128 void TargetEncodingLearner::setExperimentDirectory(const PPath& the_expdir) 00129 { 00130 inherited::setExperimentDirectory(the_expdir); 00131 sublearner->setExperimentDirectory(the_expdir / "SubLearner"); 00132 } 00133 00134 00135 int TargetEncodingLearner::outputsize() const 00136 { 00137 return sublearner->outputsize(); 00138 } 00139 00140 void TargetEncodingLearner::forget() 00141 { 00142 inherited::forget(); 00143 stage = 0; 00144 encodings_learnt= false; 00145 } 00146 00147 void TargetEncodingLearner::train() 00148 { 00149 if (!initTrain()) 00150 return; 00151 00152 if(stage<1) 00153 { 00154 00155 buildEncodingsFromTrainset(); 00156 VMat vm= new EncodedVMatrix(getTrainingSet(), encodings, defaults, encode_col); 00157 vm->setMetaDataDir(getExperimentDirectory() / "EncodedVMatrix.metadata"); 00158 sublearner->setTrainingSet(vm); 00159 ++stage; 00160 } 00161 00162 sublearner->train(); 00163 00164 } 00165 00166 void TargetEncodingLearner::buildEncodingsFromTrainset() 00167 { 00168 int l = train_set->length(); 00169 int n = train_set->inputsize(); 00170 Vec input; 00171 Vec target; 00172 real weight; 00173 00174 encodings.resize(n); 00175 00176 TVec<map<real, pair<real, real> > > stats(n); 00177 00178 encode_col.resize(n); 00179 encode_col.fill(true); 00180 00181 PP<ProgressBar> pb; 00182 if(report_progress) 00183 pb = new ProgressBar("TargetEncodingLearner computing statistics ",l); 00184 00185 real tot_weight= 0.; 00186 real tot_wt_targ= 0.; 00187 00188 for(int i= 0; i < l; ++i) 00189 { 00190 train_set->getExample(i, input, target, weight); 00191 if(target.length() != 1) 00192 PLERROR("TargetEncodingLearner supports only one target"); 00193 tot_weight+= weight; 00194 tot_wt_targ+= weight*target[0]; 00195 for(int j= 0; j < n; ++j) 00196 { 00197 if(encode_col[j]) 00198 { 00199 real val= input[j]; 00200 00201 map<real, pair<real, real> >::iterator it= stats[j].find(val); 00202 00203 if(it == stats[j].end()) 00204 stats[j].insert(make_pair(val, make_pair(weight, weight*target[0]))); 00205 else 00206 { 00207 it->second.first+= weight; 00208 it->second.second+= weight*target[0]; 00209 } 00210 if(static_cast<int>(stats[j].size()) > max_nvals_for_encoding) 00211 { 00212 encode_col[j]= false; 00213 stats[j].clear(); 00214 } 00215 } 00216 } 00217 00218 if(pb) 00219 pb->update(i); 00220 } 00221 00222 mean= tot_wt_targ / tot_weight; 00223 defaults.resize(n); 00224 defaults.fill(mean); 00225 00226 for(int i= 0; i < n; ++i) 00227 { 00228 encodings[i].clear(); 00229 for(map<real, pair<real, real> >::iterator it= stats[i].begin(); it != stats[i].end(); ++it) 00230 { 00231 real count= it->second.first; 00232 real sum= it->second.second; 00233 real avg= sum/count; 00234 encodings[i].insert(make_pair(it->first, avg)); 00235 } 00236 } 00237 00238 encodings_learnt= true; 00239 } 00240 00241 00242 00243 void TargetEncodingLearner::computeOutput(const Vec& input, Vec& output) const 00244 { 00245 if(!encodings_learnt) 00246 PLERROR("TargetEncodingLearner::computeOutput encodings not learnt"); 00247 EncodedVMatrix::encodeRow(encodings, defaults, encode_col, input); 00248 sublearner->computeOutput(input, output); 00249 } 00250 00251 void TargetEncodingLearner::computeCostsFromOutputs(const Vec& input, const Vec& output, 00252 const Vec& target, Vec& costs) const 00253 { 00254 if(!encodings_learnt) 00255 PLERROR("TargetEncodingLearner::computeCostsFromOutputs encodings not learnt"); 00256 //EncodedVMatrix::encodeRow(encodings, defaults, encode_col, input); 00257 sublearner->computeCostsFromOutputs(input, output, target, costs); 00258 } 00259 00260 TVec<string> TargetEncodingLearner::getTestCostNames() const 00261 { 00262 return sublearner->getTestCostNames(); 00263 } 00264 00265 TVec<string> TargetEncodingLearner::getTrainCostNames() const 00266 { 00267 return sublearner->getTrainCostNames(); 00268 } 00269 00270 TVec<string> TargetEncodingLearner::getOutputNames() const 00271 { 00272 return sublearner->getOutputNames(); 00273 } 00274 00275 void TargetEncodingLearner::setTrainingSet(VMat training_set, bool call_forget) 00276 { 00277 // temporarly set sublearner's train set (reset in train()) 00278 if(sublearner) 00279 sublearner->setTrainingSet(training_set, call_forget); 00280 inherited::setTrainingSet(training_set, call_forget); 00281 } 00282 00283 00284 } // end of namespace PLearn 00285 00286 00287 /* 00288 Local Variables: 00289 mode:c++ 00290 c-basic-offset:4 00291 c-file-style:"stroustrup" 00292 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00293 indent-tabs-mode:nil 00294 fill-column:79 00295 End: 00296 */ 00297 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :