PLearn 0.1
SquaredErrModule.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // SquaredErrModule.cc
00004 //
00005 // Copyright (C) 2005 Pascal Lamblin
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 /* *******************************************************
00036    * $Id: SquaredErrModule.cc,v 1.2 2005/12/30 19:53:56 lamblinp Exp $
00037    ******************************************************* */
00038 
00039 // Authors: Pascal Lamblin
00040 
00044 #include "SquaredErrModule.h"
00045 
00046 namespace PLearn {
00047 using namespace std;
00048 
00049 PLEARN_IMPLEMENT_OBJECT(
00050     SquaredErrModule,
00051     "SquaredError Module",
00052     ""
00053     );
00054 
00055 SquaredErrModule::SquaredErrModule() :
00056     /* ### Initialize all fields to their default value */
00057     target_size( 0 )
00058 {
00059     output_size = 1;
00060 }
00061 
00062 
00063 // output = error = sum of squared difference between input and target
00064 void SquaredErrModule::fprop(const Vec& input, Vec& output) const
00065 {
00066     int in_size = input.size();
00067     // size check
00068     if( in_size != input_size+target_size )
00069     {
00070         PLERROR("SquaredErrModule::fprop: 'input.size()' should be equal\n"
00071                 " to 'input_size' + 'target_size' (%i != %i + %i)\n",
00072                 in_size, input_size, target_size);
00073     }
00074 
00075     Vec target = input.subVec( input_size, target_size );
00076     Vec input_ = input.subVec( 0, input_size );
00077     output.resize( output_size );
00078     output[0] = sumsquare( input_ - target );
00079 }
00080 
00081 // Don't modify class
00082 void SquaredErrModule::bpropUpdate(const Vec& input, const Vec& output,
00083                                    const Vec& output_gradient)
00084 {
00085     int in_size = input.size();
00086     int out_size = output.size();
00087     int og_size = output_gradient.size();
00088 
00089     // size check
00090     if( in_size != input_size + target_size )
00091     {
00092         PLWARNING("SquaredErrModule::bpropUpdate: 'input.size()' should be\n"
00093                   " equal to 'input_size' + 'target_size' (%i != %i + %i)\n",
00094                   in_size, input_size, target_size);
00095     }
00096     if( out_size != output_size )
00097     {
00098         PLWARNING("SquaredErrModule::bpropUpdate: output.size()' should be\n"
00099                   " equal to 'output_size' (%i != %i)\n",
00100                   out_size, output_size);
00101     }
00102     if( og_size != output_size )
00103     {
00104         PLWARNING("SquaredErrModule::bpropUpdate: 'output_gradient.size()'\n"
00105                   " should be equal to 'output_size' (%i != %i)\n",
00106                   og_size, output_size);
00107     }
00108 }
00109 
00110 // We don't care about output_gradient, we consider we're the last variable.
00111 // So we compute the gradient of the error of this variable.
00112 void SquaredErrModule::bpropUpdate(const Vec& input, const Vec& output,
00113                                    Vec& input_gradient,
00114                                    const Vec& output_gradient)
00115 {
00116     int in_size = input.size();
00117     int out_size = output.size();
00118     int og_size = output_gradient.size();
00119     bool is_final_cost = false; // if yes, output_gradient is 1
00120 
00121     // size check
00122     if( in_size != input_size + target_size )
00123     {
00124         PLERROR("SquaredErrModule::bpropUpdate: 'input.size()' should be\n"
00125                 " equal to 'input_size' + 'target_size' (%i != %i + %i)\n",
00126                 in_size, input_size, target_size);
00127     }
00128     if( out_size != output_size )
00129     {
00130         PLERROR("SquaredErrModule::bpropUpdate: output.size()' should be\n"
00131                 " equal to 'output_size' (%i != %i)\n",
00132                 out_size, output_size);
00133     }
00134     if( og_size == 0 )
00135     {
00136         /*
00137         PLWARNING("SquaredErrModule::bpropUpdate: you are not providing"
00138                   "output_gradient.\n"
00139                   "Assuming this is the final cost, and output_gradient=1.\n");
00140          */
00141         is_final_cost = true;
00142     }
00143     else if( og_size != output_size )
00144     {
00145         PLERROR("SquaredErrModule::bpropUpdate: 'output_gradient.size()'\n"
00146                 " should be equal to 'output_size' (%i != %i)\n",
00147                 og_size, output_size);
00148     }
00149 
00150     Vec input_ = input.subVec( 0, input_size );
00151     Vec target = input.subVec( input_size, target_size );
00152     input_gradient.resize( input_size );
00153     for( int i=0 ; i<input_size ; i++ )
00154     {
00155         if( is_final_cost )
00156             input_gradient[i] = 2*( input_[i] - target[i] );
00157         else
00158             input_gradient[i] = 2*( input_[i] - target[i] )*output_gradient[0];
00159     }
00160 }
00161 
00162 // Does nothing (just checks and warns)
00163 void SquaredErrModule::bbpropUpdate(const Vec& input, const Vec& output,
00164                                     const Vec& output_gradient,
00165                                     const Vec& output_diag_hessian)
00166 {
00167     int odh_size = output_diag_hessian.size();
00168     if( odh_size != output_size )
00169     {
00170         PLWARNING("SquaredErrModule::bbpropUpdate:"
00171                   " 'output_diag_hessian.size()'\n"
00172                   " should be equal to 'output_size' (%i != %i)\n",
00173                   odh_size, output_size);
00174     }
00175 
00176     bpropUpdate( input, output, output_gradient );
00177 }
00178 
00179 // Propagates back output_gradient and output_diag_hessian
00180 void SquaredErrModule::bbpropUpdate(const Vec& input, const Vec& output,
00181                                     Vec& input_gradient,
00182                                     const Vec& output_gradient,
00183                                     Vec& input_diag_hessian,
00184                                     const Vec& output_diag_hessian)
00185 {
00186     int odh_size = output_diag_hessian.size();
00187     bool is_final_cost = false; // if yes, output_diag_hessian is 0
00188 
00189     // size check
00190     // others size checks will be done in bpropUpdate()
00191     if( odh_size == 0 )
00192     {
00193         PLWARNING("SquaredErrModule::bbpropUpdate: you are not providing"
00194                   " output_diag_hessian.\n"
00195                   "Assuming this is the final cost,"
00196                   " and output_diag_hessian=0.\n");
00197         is_final_cost = true;
00198     }
00199     else if( odh_size != output_size )
00200     {
00201         PLERROR("SquaredErrModule::bbpropUpdate:"
00202                 " 'output_diag_hessian.size()'\n"
00203                 " should be equal to 'output_size' (%i != %i)\n",
00204                 odh_size, output_size);
00205     }
00206 
00207     bpropUpdate( input, output, input_gradient, output_gradient );
00208 
00209     Vec input_ = input.subVec( 0, input_size );
00210     Vec target = input.subVec( input_size, target_size );
00211     input_diag_hessian.resize( input_size );
00212 
00213     // computation of term dC/dy d²y/dx²,
00214     // skipped if estimate_simpler_diag_hessian, unless it is final cost
00215     if( estimate_simpler_diag_hessian && !is_final_cost )
00216     {
00217         input_diag_hessian.clear();
00218     }
00219     else
00220     {
00221         Vec idh( input_size, 2 );
00222         input_diag_hessian << idh;
00223 
00224         if( !is_final_cost )
00225             input_diag_hessian *= output_gradient[0];
00226     }
00227 
00228     // computation of term d²C/dy² (dy/dx)²,
00229     // skipped if it is final cost, because then d²C/dy² == d²C/dC² == 0
00230     if( !is_final_cost )
00231     {
00232         for( int i=0 ; i<input_size ; i++ )
00233         {
00234             real fprime_i = 2*(input_[i] - target[i]);
00235             input_diag_hessian[i] += (fprime_i*fprime_i)
00236                                        * output_diag_hessian[0];
00237         }
00238     }
00239 
00240 }
00241 
00242 
00243 
00244 
00245 //
00246 void SquaredErrModule::forget()
00247 {
00248 //    target = Vec( input_size );
00249 }
00250 
00251 
00252 // ### Nothing to add here, simply calls build_
00253 void SquaredErrModule::build()
00254 {
00255     inherited::build();
00256     build_();
00257 }
00258 
00259 void SquaredErrModule::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00260 {
00261     inherited::makeDeepCopyFromShallowCopy(copies);
00262 
00263 //    deepCopyField(target, copies);
00264 }
00265 
00266 void SquaredErrModule::declareOptions(OptionList& ol)
00267 {
00268     inherited::declareOptions(ol);
00269 }
00270 
00271 void SquaredErrModule::build_()
00272 {
00273     if( input_size < 0 )
00274     {
00275         PLWARNING("SquaredErrModule::build_: 'input_size' is < 0.\n"
00276                   "You should set it to a positive integer.\n"
00277                   "Defaulting to '1' (scalar version).");
00278         input_size = 1;
00279     }
00280     if( output_size != 1 )
00281     {
00282         PLWARNING("SquaredErrModule::build_: 'output_size' (%i) should be 1.\n"
00283                   "Setting 'output_size' to 1.\n", output_size);
00284         output_size = 1;
00285     }
00286 
00287     target_size = input_size;
00288 }
00289 
00290 
00291 
00292 
00293 } // end of namespace PLearn
00294 
00295 
00296 /*
00297   Local Variables:
00298   mode:c++
00299   c-basic-offset:4
00300   c-file-style:"stroustrup"
00301   c-file-offsets:((innamespace . 0)(inline-open . 0))
00302   indent-tabs-mode:nil
00303   fill-column:79
00304   End:
00305 */
00306 // 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