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