PLearn 0.1
|
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 :