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 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are met: 00010 // 00011 // 1. Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // 00014 // 2. Redistributions in binary form must reproduce the above copyright 00015 // notice, this list of conditions and the following disclaimer in the 00016 // documentation and/or other materials provided with the distribution. 00017 // 00018 // 3. The name of the authors may not be used to endorse or promote 00019 // products derived from this software without specific prior written 00020 // permission. 00021 // 00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00033 // This file is part of the PLearn library. For more information on the PLearn 00034 // library, go to the PLearn Web site at www.plearn.org 00035 00036 00037 /* ******************************************************* 00038 * $Id: ShiftAndRescaleVMatrix.cc 10178 2009-05-06 15:21:16Z nouiz $ 00039 ******************************************************* */ 00040 00041 #include "ShiftAndRescaleVMatrix.h" 00042 #include "VMat_computeStats.h" 00043 #include "VMat_basic_stats.h" 00044 #include <plearn/math/TMat_maths.h> 00045 00046 namespace PLearn { 00047 using namespace std; 00048 00051 PLEARN_IMPLEMENT_OBJECT(ShiftAndRescaleVMatrix, 00052 "Applies a linear transformation to columns of a" 00053 " source VMatrix.", 00054 "The default behavior is to shift and scale only the" 00055 " input columns in order\n" 00056 "to set their mean to 0 and their standard deviation" 00057 " to 1, but the various\n" 00058 "options can be used for finer control.\n" 00059 ); 00060 00061 ShiftAndRescaleVMatrix::ShiftAndRescaleVMatrix(bool call_build_) 00062 : inherited(call_build_), 00063 shared_shift(0), 00064 shared_scale(1), 00065 automatic(1), 00066 n_train(0), 00067 n_inputs(-1), 00068 negate_shift(false), 00069 no_scale(false), 00070 verbosity(1) 00071 { 00072 if( call_build_ ) 00073 build_(); 00074 } 00075 00076 ShiftAndRescaleVMatrix::ShiftAndRescaleVMatrix(VMat the_source, 00077 bool call_build_) 00078 : inherited(the_source, 00079 the_source->length(), 00080 the_source->width(), 00081 call_build_), 00082 automatic(1), 00083 n_train(0), 00084 n_inputs(-1), 00085 negate_shift(false), 00086 no_scale(false), 00087 verbosity(1) 00088 { 00089 if( call_build_ ) 00090 build_(); 00091 } 00092 00093 ShiftAndRescaleVMatrix::ShiftAndRescaleVMatrix(VMat the_source, 00094 Vec the_shift, Vec the_scale, 00095 bool call_build_) 00096 : inherited(the_source, 00097 the_source->length(), 00098 the_source->width(), 00099 call_build_), 00100 shift(the_shift), 00101 scale(the_scale), 00102 automatic(0), 00103 n_train(0), 00104 n_inputs(-1), 00105 negate_shift(false), 00106 no_scale(false), 00107 verbosity(1) 00108 { 00109 if( call_build_ ) 00110 build_(); 00111 } 00112 00113 00114 ShiftAndRescaleVMatrix::ShiftAndRescaleVMatrix(VMat the_source, 00115 int the_n_inputs, 00116 bool call_build_) 00117 : inherited(the_source, 00118 the_source->length(), 00119 the_source->width(), 00120 call_build_), 00121 shift(the_source->width()), 00122 scale(the_source->width()), 00123 automatic(1), 00124 n_train(0), 00125 n_inputs(the_n_inputs), 00126 negate_shift(false), 00127 no_scale(false), 00128 verbosity(1) 00129 { 00130 if( call_build_ ) 00131 build_(); 00132 } 00133 00134 ShiftAndRescaleVMatrix::ShiftAndRescaleVMatrix(VMat the_source, 00135 int the_n_inputs, 00136 int the_n_train, 00137 bool the_ignore_missing, 00138 bool the_verbosity, 00139 bool call_build_) 00140 : inherited(the_source, 00141 the_source->length(), 00142 the_source->width(), 00143 call_build_), 00144 shift(the_source->width()), 00145 scale(the_source->width()), 00146 automatic(1), 00147 n_train(the_n_train), 00148 n_inputs(the_n_inputs), 00149 negate_shift(false), 00150 no_scale(false), 00151 verbosity(the_verbosity) 00152 { 00153 PLDEPRECATED("In ShiftAndRescaleVMatrix::ShiftAndRescaleVMatrix - This " 00154 "constructor is deprecated, as it takes an option " 00155 "'ignore_missing' that does not exist anymore"); 00156 if( call_build_ ) 00157 build_(); 00158 } 00159 00160 void ShiftAndRescaleVMatrix::declareOptions(OptionList& ol) 00161 { 00162 declareOption(ol, "underlying_vmat", &ShiftAndRescaleVMatrix::source, 00163 (OptionBase::learntoption | OptionBase::nosave), 00164 "DEPRECATED - Use 'source' instead."); 00165 00166 declareOption(ol, "shift", &ShiftAndRescaleVMatrix::shift, 00167 OptionBase::buildoption, 00168 "Quantity added to each INPUT element of a row of the source" 00169 " vmatrix."); 00170 00171 declareOption(ol, "scale", &ShiftAndRescaleVMatrix::scale, 00172 OptionBase::buildoption, 00173 "Quantity multiplied to each shifted element of a row of the" 00174 " source vmatrix."); 00175 00176 declareOption(ol, "shared_shift", &ShiftAndRescaleVMatrix::shared_shift, 00177 OptionBase::buildoption, 00178 "Quantity added to ALL INPUT elements of a row of the source\n" 00179 "vmatrix. This option is ignored if 'shift' is provided\n" 00180 "or 'automatic' is true.\n"); 00181 00182 declareOption(ol, "shared_scale", &ShiftAndRescaleVMatrix::shared_scale, 00183 OptionBase::buildoption, 00184 "Quantity multiplied to ALL shifted INPUT elements of a row of the" 00185 "source vmatrix. This option is ignored if 'scale' is provided,\n" 00186 "'automatic' is true or 'no_scale' is true.\n"); 00187 00188 declareOption(ol, "automatic", &ShiftAndRescaleVMatrix::automatic, 00189 OptionBase::buildoption, 00190 "Whether shift and scale are determined from the mean and" 00191 " stddev\n" 00192 "of the source vmatrix, or user-provided.\n"); 00193 00194 declareOption(ol, "n_train", &ShiftAndRescaleVMatrix::n_train, 00195 OptionBase::buildoption, 00196 "when automatic, use only the n_train first examples to" 00197 " estimate\n" 00198 "shift and scale, if n_train>0.\n"); 00199 00200 declareOption(ol, "n_inputs", &ShiftAndRescaleVMatrix::n_inputs, 00201 OptionBase::buildoption, 00202 "When automatic, shift and scale only the first n_inputs columns.\n" 00203 "Special values are as follows:\n" 00204 " -1 : n_inputs <- source->inputsize()\n" 00205 " -2 : n_inputs <- source->inputsize() + source->targetsize()"); 00206 00207 declareOption(ol, "negate_shift", &ShiftAndRescaleVMatrix::negate_shift, 00208 OptionBase::buildoption, 00209 "If set to 1, the shift will be removed instead of added."); 00210 00211 declareOption(ol, "no_scale", &ShiftAndRescaleVMatrix::no_scale, 00212 OptionBase::buildoption, 00213 "If set to 1, no scaling will be performed (only a shift" 00214 " will be applied)."); 00215 00216 declareOption(ol, "fields", &ShiftAndRescaleVMatrix::fields, 00217 OptionBase::buildoption, 00218 "The fields to shift and rescale. Automatic must be true and" 00219 " if empty we use instead n_inputs."); 00220 00221 declareOption(ol, "verbosity", &ShiftAndRescaleVMatrix::verbosity, 00222 OptionBase::buildoption, 00223 "Controls the amount of output."); 00224 00225 declareOption(ol, "min_max", &ShiftAndRescaleVMatrix::min_max, 00226 OptionBase::buildoption, 00227 "A vector of size 2 [min,max]. For each column, the elements will be\n" 00228 "shifted and rescaled to be in [min,max]. If set, it will override\n" 00229 "the value of the 'automatic' option. A constant column will be set\n" 00230 "to the average of 'min' and 'max'."); 00231 00232 // Now call the parent class' declareOptions 00233 inherited::declareOptions(ol); 00234 } 00235 00237 // build_ // 00239 void ShiftAndRescaleVMatrix::build_() 00240 { 00241 PLASSERT( n_inputs >= 0 || n_inputs == -1 || n_inputs == -2 ); 00242 PLCHECK(fields.size()<=0||automatic); 00243 if( source ) 00244 { 00245 if (automatic && min_max.isEmpty()) 00246 { 00247 if (n_inputs<0) 00248 { 00249 PLCHECK( source->inputsize() >= 0 ); 00250 if (n_inputs == -1) 00251 n_inputs = source->inputsize(); 00252 else if (n_inputs == -2) { 00253 PLCHECK( source->targetsize() >= 0 ); 00254 n_inputs = source->inputsize() + source->targetsize(); 00255 } else 00256 PLERROR("In ShiftAndRescaleVMatrix::build_ - Wrong value " 00257 "for 'n_inputs'"); 00258 if (n_inputs<0) 00259 PLERROR("ShiftAndRescaleVMatrix: either n_inputs should be" 00260 " provided explicitly\n" 00261 "or the source VMatrix should have a set value of" 00262 " inputsize.\n"); 00263 } 00264 if (n_train>0) 00265 computeMeanAndStddev(source.subMatRows(0,n_train), 00266 shift, scale); 00267 else 00268 computeMeanAndStddev(source, shift, scale); 00269 if (!negate_shift) 00270 negateElements(shift); 00271 if (!no_scale) { 00272 for (int i=0;i<scale.length();i++) 00273 if (fast_exact_is_equal(scale[i], 0)) 00274 { 00275 if (verbosity >= 1) 00276 PLWARNING("ShiftAndRescale: data column number %d" 00277 " is constant",i); 00278 scale[i]=1; 00279 } 00280 invertElements(scale); 00281 scale.resize(source->width()); 00282 scale.subVec(n_inputs, scale.length()-n_inputs).fill(1); 00283 } 00284 00285 if(fields.size()>0){ 00286 //we shift and scale only the fields 00287 TVec<int> idx(fields.size()); 00288 for(int i=0;i<fields.size();i++){ 00289 idx[i]=source->getFieldIndex(fields[i]); 00290 if(idx[i]>n_inputs) 00291 PLERROR("In ShiftAndRescaleVMatrix::build_() - The " 00292 "fields index must be lower or equal to n_inputs"); 00293 } 00294 for(int i=0;i<n_inputs;i++){ 00295 bool found=false; 00296 for(int j=0;j<idx.size();j++){ 00297 if(i==idx[j]) 00298 found=true; 00299 } 00300 if(!found){ 00301 shift[i]=0; 00302 scale[i]=1; 00303 } 00304 } 00305 } 00306 shift.resize(source->width()); 00307 shift.subVec(n_inputs, shift.length()-n_inputs).fill(0); 00308 } 00309 else { 00310 if (!min_max.isEmpty()) { 00311 00312 if ( min_max.length()!=2 ) 00313 PLERROR("ShiftAndRescale: min_max should have exactly 2" 00314 "elements(if set)") ; 00315 00316 if ( min_max[0] >= min_max[1]) 00317 PLERROR("ShiftAndRescale: min_max[0] should be smaller than" 00318 "min_max[1]") ; 00319 if (n_inputs<0) 00320 { 00321 PLCHECK(source->inputsize()>=0); 00322 if(n_inputs==-1) 00323 n_inputs = source->inputsize(); 00324 else if (n_inputs == -2) { 00325 PLCHECK( source->targetsize() >= 0 ); 00326 n_inputs = source->inputsize() + source->targetsize(); 00327 } else 00328 PLERROR("In ShiftAndRescaleVMatrix::build_ - Wrong value " 00329 "for 'n_inputs'"); 00330 } 00331 00332 Vec min_col(n_inputs) , max_col(n_inputs) ; 00333 Mat data = transpose(source.subMatColumns(0,n_inputs).toMat()); 00334 00335 rowMin(data , min_col) ; 00336 rowMax(data , max_col) ; 00337 00338 shift.resize(source->width()) ; 00339 shift.subVec(n_inputs, shift.length()-n_inputs).fill(0); 00340 scale.resize(source->width()) ; 00341 scale.subVec(n_inputs, scale.length()-n_inputs).fill(1); 00342 00343 for(int i=0 ; i<n_inputs ; ++i) { 00344 if (fast_exact_is_equal(min_col[i], max_col[i])) { 00345 // Constant column. 00346 shift[i] = (min_max[1] + min_max[0]) / 2 - min_col[i]; 00347 scale[i] = 1; 00348 } else { 00349 shift[i] = (max_col[i] - min_col[i]) / 00350 (min_max[1] - min_max[0]) * 00351 (min_max[0] - (min_max[1] - min_max[0])*min_col[i] 00352 / (max_col[i] - min_col[i]) ); 00353 scale[i] = (min_max[1] - min_max[0]) / 00354 (max_col[i] - min_col[i]); 00355 } 00356 } 00357 00358 } 00359 else 00360 { 00361 n_inputs = source->inputsize(); 00362 if (n_inputs<0) 00363 { 00364 n_inputs = source->inputsize(); 00365 if (n_inputs<0) 00366 PLERROR("ShiftAndRescaleVMatrix: either n_inputs should be" 00367 " provided explicitly\n" 00368 "or the source VMatrix should have a set value of" 00369 " inputsize.\n"); 00370 } 00371 00372 if( shift.length() == 0) 00373 { 00374 shift.resize(source->width()) ; 00375 shift.subVec(n_inputs, shift.length()-n_inputs).fill(0); 00376 shift.subVec(0,n_inputs).fill(shared_shift); 00377 } 00378 00379 if( scale.length() == 0) 00380 { 00381 scale.resize(source->width()) ; 00382 scale.subVec(n_inputs, scale.length()-n_inputs).fill(1); 00383 scale.subVec(0,n_inputs).fill(shared_scale); 00384 } 00385 } 00386 } 00387 reset_dimensions(); 00388 setMetaInfoFromSource(); 00389 } 00390 } 00391 00393 // getNewRow // 00395 void ShiftAndRescaleVMatrix::getNewRow(int i, const Vec& v) const 00396 { 00397 source->getRow(i, v); 00398 00399 if( negate_shift ) 00400 v -= shift; 00401 else 00402 v += shift; 00403 00404 if( !no_scale ) 00405 v *= scale; 00406 } 00407 00409 // build // 00411 void ShiftAndRescaleVMatrix::build() 00412 { 00413 inherited::build(); 00414 build_(); 00415 } 00416 00418 // makeDeepCopyFromShallowCopy // 00420 void ShiftAndRescaleVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00421 { 00422 inherited::makeDeepCopyFromShallowCopy(copies); 00423 deepCopyField(shift, copies); 00424 deepCopyField(scale, copies); 00425 deepCopyField(min_max, copies); 00426 } 00427 00428 } // end of namespace PLearn 00429 00430 00431 /* 00432 Local Variables: 00433 mode:c++ 00434 c-basic-offset:4 00435 c-file-style:"stroustrup" 00436 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00437 indent-tabs-mode:nil 00438 fill-column:79 00439 End: 00440 */ 00441 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :