PLearn 0.1
MeanImputationVMatrix.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PLearn (A C++ Machine Learning Library)
00004 // Copyright (C) 1998 Pascal Vincent
00005 // Copyright (C) 1999-2001 Pascal Vincent, Yoshua Bengio, Rejean Ducharme and University of Montreal
00006 // Copyright (C) 2002 Pascal Vincent, Julien Keable, Xavier Saint-Mleux
00007 // Copyright (C) 2003, 2006 Olivier Delalleau
00008 //
00009 // Redistribution and use in source and binary forms, with or without
00010 // modification, are permitted provided that the following conditions are met:
00011 //
00012 //  1. Redistributions of source code must retain the above copyright
00013 //     notice, this list of conditions and the following disclaimer.
00014 //
00015 //  2. Redistributions in binary form must reproduce the above copyright
00016 //     notice, this list of conditions and the following disclaimer in the
00017 //     documentation and/or other materials provided with the distribution.
00018 //
00019 //  3. The name of the authors may not be used to endorse or promote
00020 //     products derived from this software without specific prior written
00021 //     permission.
00022 //
00023 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00024 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00025 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00026 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00027 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00028 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00029 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00030 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00031 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 //
00034 // This file is part of the PLearn library. For more information on the PLearn
00035 // library, go to the PLearn Web site at www.plearn.org
00036 
00037 
00038 /* *******************************************************************
00039  * $Id: MeanImputationVMatrix.cc 3658 2005-07-06 20:30:15  Godbout $
00040  ******************************************************************* */
00041 
00042 
00043 #include "MeanImputationVMatrix.h"
00044 #include <plearn/vmat/ForwardVMatrix.h>
00045 #include <plearn/vmat/SubVMatrix.h>
00046 #include <plearn/vmat/VMat_basic_stats.h>
00047 
00048 namespace PLearn {
00049 using namespace std;
00050 
00053 PLEARN_IMPLEMENT_OBJECT(
00054     MeanImputationVMatrix,
00055     "Imputes the observed variable mean to replace missing values in source.",
00056     "This class will replace missing values in the underlying dataset with\n"
00057     "the observed mean of a variable.\n"
00058     "If the 'number_of_train_samples' option is different than zero, the\n"
00059     "mean is computed only on that first portion of the underlying VMat.\n"
00060     "Otherwise, the mean is computed on the entire dataset.\n"
00061     "Optionally, if one wants to obtain the variable means from another\n"
00062     "dataset than the underlying source VMatrix, the 'mean_source' option\n"
00063     "can be specified.\n"
00064     "\n"
00065     "If the 'distribution' option is given, then instead of imputing the\n"
00066     "global empirical mean, the conditional mean of the missing values given\n"
00067     "the observed values in each sample will be used (the distribution must\n"
00068     "implement the missingExpectation(..) method).\n"
00069 );
00070 
00072 // MeanImputationVMatrix //
00074 MeanImputationVMatrix::MeanImputationVMatrix():
00075     obtained_inputsize_from_source(false),
00076     obtained_targetsize_from_source(false),
00077     obtained_weightsize_from_source(false),
00078     distribution_access_to_target("train_only"),
00079     number_of_train_samples(0.0)
00080 {}
00081 
00082 MeanImputationVMatrix::MeanImputationVMatrix(VMat the_source,
00083                                              real the_number_of_train_samples,
00084                                              bool call_build_):
00085     inherited(the_source, call_build_),
00086     obtained_inputsize_from_source(false),
00087     obtained_targetsize_from_source(false),
00088     obtained_weightsize_from_source(false),
00089     distribution_access_to_target("train_only"),
00090     number_of_train_samples(the_number_of_train_samples)
00091 {
00092     if (call_build_)
00093         build_();
00094 }
00095 
00097 // declareOptions //
00099 void MeanImputationVMatrix::declareOptions(OptionList &ol)
00100 {
00101 
00102     declareOption(ol, "number_of_train_samples",
00103                   &MeanImputationVMatrix::number_of_train_samples,
00104                   OptionBase::buildoption,
00105         "If equal to zero, all the underlying dataset samples are used to\n"
00106         "compute the variable means. If it is a fraction between 0 and 1,\n"
00107         "this proportion of the samples will be used. If greater than or\n"
00108         "equal to 1, the integer portion will be interpreted as the number\n"
00109         "of samples to use.");
00110 
00111     declareOption(ol, "mean_source",
00112                   &MeanImputationVMatrix::mean_source,
00113                   OptionBase::buildoption,
00114         "If specified, this VMat will be used to compute the means instead\n"
00115         "of the 'source' option.");
00116 
00117     declareOption(ol, "distribution",
00118                   &MeanImputationVMatrix::distribution,
00119                   OptionBase::buildoption,
00120         "If provided, this conditional distribution will provide a way to\n"
00121         "compute the conditional mean given observed values. Otherwise, the\n"
00122         "empirical mean will be used. This distribution is trained on the\n"
00123         "'source' (or 'mean_source') VMat unless it already has a stage > 0.\n"
00124         "Whether this distribution has access to the target value or not\n"
00125         "depends on the 'distribution_access_to_target' option.\n");
00126 
00127     declareOption(ol, "distribution_access_to_target",
00128                   &MeanImputationVMatrix::distribution_access_to_target,
00129                   OptionBase::buildoption,
00130         "Used only when a distribution is specified, and modifies the way\n"
00131         "target values are given to the distribution:\n"
00132         "- train_only: only the first 'number_of_train_samples' are given\n"
00133         "              access to their target (if this number is 0, all\n"
00134         "              samples are given access to their target)\n"
00135         "- none      : no sample is given access to its target\n");
00136 
00137     declareOption(ol, "variable_mean", &MeanImputationVMatrix::variable_mean,
00138                                        OptionBase::learntoption,
00139         "The vector of variable means observed from the source matrix.");
00140 
00141     declareOption(ol, "obtained_inputsize_from_source",
00142                   &MeanImputationVMatrix::obtained_inputsize_from_source,
00143                   OptionBase::learntoption,
00144         "Set to 1 when the inputsize was obtained from the source matrix.");
00145 
00146     declareOption(ol, "obtained_targetsize_from_source",
00147                   &MeanImputationVMatrix::obtained_targetsize_from_source,
00148                   OptionBase::learntoption,
00149         "Set to 1 when the targetsize was obtained from the source matrix.");
00150 
00151     declareOption(ol, "obtained_weightsize_from_source",
00152                   &MeanImputationVMatrix::obtained_weightsize_from_source,
00153                   OptionBase::learntoption,
00154         "Set to 1 when the weightsize was obtained from the source matrix.");
00155 
00156     inherited::declareOptions(ol);
00157 }
00158 
00160 // build //
00162 void MeanImputationVMatrix::build()
00163 {
00164     inherited::build();
00165     build_();
00166 }
00167 
00169 // build_ //
00171 void MeanImputationVMatrix::build_()
00172 {
00173     if (source) {
00174         string error_msg =
00175             "In MeanImputationVMatrix::build_ - For safety reasons, it is forbidden to "
00176             "re-use sizes obtained from a previous source VMatrix with a new source "
00177             "VMatrix having different sizes";
00178         length_ = source->length();
00179         width_ = source->width();
00180         if(inputsize_<0) {
00181             inputsize_ = source->inputsize();
00182             obtained_inputsize_from_source = true;
00183         } else if (obtained_inputsize_from_source && inputsize_ != source->inputsize())
00184             PLERROR(error_msg.c_str());
00185         if(targetsize_<0) {
00186             targetsize_ = source->targetsize();
00187             obtained_targetsize_from_source = true;
00188         } else if (obtained_targetsize_from_source && targetsize_ != source->targetsize())
00189             PLERROR(error_msg.c_str());
00190         if(weightsize_<0) {
00191             weightsize_ = source->weightsize();
00192             obtained_weightsize_from_source = true;
00193         } else if (obtained_weightsize_from_source && weightsize_ != source->weightsize())
00194             PLERROR(error_msg.c_str());
00195 
00196         setMetaInfoFromSource();
00197         updateMtime(mean_source);
00198         
00199         computeMeanVector();
00200 
00201         // Train the user-provided distribution if needed.
00202         if (distribution) {
00203             distribution->setPredictorPredictedSizes(0, -1);
00204             if (distribution->stage == 0) {
00205                 // Currently not implemented for a limited number of training
00206                 // samples, but it should not be too difficult to do it.
00207                 PLASSERT( number_of_train_samples == 0 );
00208                 VMat the_train_source = mean_source ? mean_source : source;
00209                 // Redefine sizes to train on the whole data.
00210                 the_train_source = new ForwardVMatrix(the_train_source);
00211                 the_train_source->defineSizes(the_train_source->width(), 0, 0, 0);
00212                 distribution->setTrainingSet(the_train_source);
00213                 distribution->train();
00214             }
00215         }
00216     } else {
00217         // Restore the original undefined sizes if the current one had been obtained
00218         // from the source VMatrix.
00219         if (obtained_inputsize_from_source) {
00220             inputsize_ = -1;
00221             obtained_inputsize_from_source = false;
00222         }
00223         if (obtained_targetsize_from_source) {
00224             targetsize_ = -1;
00225             obtained_targetsize_from_source = false;
00226         }
00227         if (obtained_weightsize_from_source) {
00228             weightsize_ = -1;
00229             obtained_weightsize_from_source = false;
00230         }
00231     }
00232 
00233     // Check valid values.
00234     if (distribution_access_to_target != "train_only" &&
00235         distribution_access_to_target != "none")
00236         PLERROR("In MeanImputationVMatrix::build_ - Invalid value for option "
00237                 "'distribution_access_to_target'");
00238 }
00239 
00241 // makeDeepCopyFromShallowCopy //
00243 void MeanImputationVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00244 {
00245     inherited::makeDeepCopyFromShallowCopy(copies);
00246     deepCopyField(cond_mean,     copies);
00247     deepCopyField(variable_mean, copies);
00248     deepCopyField(tmp_target,    copies);
00249     deepCopyField(distribution,  copies);
00250     deepCopyField(mean_source,   copies);
00251 }
00252 
00253 
00255 // getNewRow //
00257 void MeanImputationVMatrix::getNewRow(int i, const Vec& v) const
00258 {
00259     PLASSERT( source );
00260     source->getRow(i, v);
00261 
00262     if (v.hasMissing()){
00263         if (distribution) {
00264             Vec target;
00265             bool restore_target = false;
00266             if ((number_of_train_samples > 0 && i >= number_of_train_samples &&
00267                  distribution_access_to_target == "train_only") ||
00268                 distribution_access_to_target == "none")
00269             {
00270                 tmp_target.resize(source->targetsize());
00271                 target = v.subVec(source->inputsize(), source->targetsize());
00272                 tmp_target << target;
00273                 target.fill(MISSING_VALUE);
00274                 restore_target = true;
00275             }
00276             distribution->missingExpectation(v, cond_mean);
00277             int k = 0;
00278             for (int j = 0; j < v.length(); j++)
00279                 if (is_missing(v[j]))
00280                     v[j] = cond_mean[k++];
00281             if (restore_target)
00282                 target << tmp_target;
00283         } else
00284             for (int j = 0; j < v.length(); j++)
00285                 if (is_missing(v[j]))
00286                     v[j] = variable_mean[j];
00287     }
00288 }
00289 
00291 // getMeanVector //
00293 Vec MeanImputationVMatrix::getMeanVector()
00294 {
00295     return variable_mean;
00296 }
00297 
00299 // computeMeanVector //
00301 void MeanImputationVMatrix::computeMeanVector()
00302 {
00303     VMat the_mean_source;
00304     if (mean_source) {
00305         PLASSERT( mean_source->width() == source->width() );
00306         the_mean_source = mean_source;
00307     } else
00308         the_mean_source = source;
00309    
00310     PLASSERT( the_mean_source );
00311 
00312     int length = the_mean_source->length();
00313     int width = width_;
00314     PLASSERT( width = the_mean_source->width() );
00315     variable_mean.resize(width);
00316     if (number_of_train_samples > 0.0)
00317     {
00318         if (number_of_train_samples >= 1.0)
00319             length = (int) number_of_train_samples;
00320         else
00321             length = (int) ((double) length * number_of_train_samples);
00322         if (length < 1)
00323             length = 1;
00324         if (length > the_mean_source->length())
00325             length = the_mean_source->length();
00326     }
00327     VMat sub_source = the_mean_source;
00328     if (length != the_mean_source->length())
00329         sub_source = new SubVMatrix(sub_source, 0, 0,
00330                                     length, sub_source->width());
00331     computeMean(sub_source, variable_mean);
00332 }
00333 
00334 } // end of namespace PLearn
00335 
00336 
00337 /*
00338   Local Variables:
00339   mode:c++
00340   c-basic-offset:4
00341   c-file-style:"stroustrup"
00342   c-file-offsets:((innamespace . 0)(inline-open . 0))
00343   indent-tabs-mode:nil
00344   fill-column:79
00345   End:
00346 */
00347 // 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