PLearn 0.1
ShiftAndRescaleVMatrix.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 //
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines