PLearn 0.1
TargetEncodingLearner.cc
Go to the documentation of this file.
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines