PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // Supersampling2DModule.cc 00004 // 00005 // Copyright (C) 2006 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 // Authors: Pascal Lamblin 00036 00040 #define PL_LOG_MODULE_NAME "Supersampling2DModule" 00041 00042 #include "Supersampling2DModule.h" 00043 #include <plearn/math/convolutions.h> 00044 #include <plearn/math/TMat_maths.h> 00045 #include <plearn/io/pl_log.h> 00046 00047 namespace PLearn { 00048 using namespace std; 00049 00050 PLEARN_IMPLEMENT_OBJECT( 00051 Supersampling2DModule, 00052 "Apply convolution filters on (possibly multiple) 2D inputs (images)", 00053 ""); 00054 00055 Supersampling2DModule::Supersampling2DModule() : 00056 n_input_images(1), 00057 input_images_length(-1), 00058 input_images_width(-1), 00059 kernel_length(-1), 00060 kernel_width(-1), 00061 start_learning_rate(0.), 00062 decrease_constant(0.), 00063 output_images_length(-1), 00064 output_images_width(-1), 00065 input_images_size(-1), 00066 output_images_size(-1), 00067 kernel_size(-1), 00068 learning_rate(0.), 00069 step_number(0) 00070 { 00071 } 00072 00073 void Supersampling2DModule::declareOptions(OptionList& ol) 00074 { 00075 // declareOption(ol, "myoption", &Supersampling2DModule::myoption, 00076 // OptionBase::buildoption, 00077 // "Help text describing this option"); 00078 00079 declareOption(ol, "n_input_images", &Supersampling2DModule::n_input_images, 00080 OptionBase::buildoption, 00081 "Number of input images present at the same time in the" 00082 " input vector"); 00083 00084 declareOption(ol, "input_images_length", 00085 &Supersampling2DModule::input_images_length, 00086 OptionBase::buildoption, 00087 "Length of each of the input images"); 00088 00089 declareOption(ol, "input_images_width", 00090 &Supersampling2DModule::input_images_width, 00091 OptionBase::buildoption, 00092 "Width of each of the input images"); 00093 00094 declareOption(ol, "kernel_length", &Supersampling2DModule::kernel_length, 00095 OptionBase::buildoption, 00096 "Length of the area corresponding to one pixel" 00097 ); 00098 00099 declareOption(ol, "kernel_width", &Supersampling2DModule::kernel_width, 00100 OptionBase::buildoption, 00101 "Width of the area corresponding to one pixel" 00102 ); 00103 00104 declareOption(ol, "start_learning_rate", 00105 &Supersampling2DModule::start_learning_rate, 00106 OptionBase::buildoption, 00107 "Starting learning-rate, by which we multiply the gradient" 00108 " step" 00109 ); 00110 00111 declareOption(ol, "decrease_constant", 00112 &Supersampling2DModule::decrease_constant, 00113 OptionBase::buildoption, 00114 "learning_rate = start_learning_rate / (1 +" 00115 " decrease_constant*t),\n" 00116 "where t is the number of updates since the beginning\n" 00117 ); 00118 00119 declareOption(ol, "output_images_length", 00120 &Supersampling2DModule::output_images_length, 00121 OptionBase::learntoption, 00122 "Length of the output images"); 00123 00124 declareOption(ol, "output_images_width", 00125 &Supersampling2DModule::output_images_width, 00126 OptionBase::learntoption, 00127 "Width of the output images"); 00128 00129 declareOption(ol, "scale", &Supersampling2DModule::scale, 00130 OptionBase::learntoption, 00131 "Contains the scale of the output images"); 00132 00133 declareOption(ol, "bias", &Supersampling2DModule::bias, 00134 OptionBase::learntoption, 00135 "Contains the bias of the output images"); 00136 00137 00138 // Now call the parent class' declareOptions 00139 inherited::declareOptions(ol); 00140 00141 // Redeclare some of the parent's options as learntoptions 00142 redeclareOption(ol, "input_size", &Supersampling2DModule::input_size, 00143 OptionBase::learntoption, 00144 "Size of the input, computed from n_input_images,\n" 00145 "n_input_length and n_input_width.\n"); 00146 00147 redeclareOption(ol, "output_size", &Supersampling2DModule::output_size, 00148 OptionBase::learntoption, 00149 "Size of the output, computed from n_output_images,\n" 00150 "n_output_length and n_output_width.\n"); 00151 } 00152 00153 void Supersampling2DModule::build_() 00154 { 00155 MODULE_LOG << "build_() called" << endl; 00156 00157 // Verify the parameters 00158 if( n_input_images < 1 ) 00159 PLERROR("Supersampling2DModule::build_: 'n_input_images' < 1 (%i).\n", 00160 n_input_images); 00161 00162 if( input_images_length < 0 ) 00163 PLERROR("Supersampling2DModule::build_: 'input_images_length'<0 (%i)." 00164 "\n", 00165 input_images_length); 00166 00167 if( input_images_width < 0 ) 00168 PLERROR("Supersampling2DModule::build_: 'input_images_width'<0 (%i)." 00169 "\n", 00170 input_images_width); 00171 00172 if( kernel_length < 0 ) 00173 PLERROR("Supersampling2DModule::build_: 'kernel_length'<0 (%i).\n", 00174 kernel_length); 00175 00176 if( kernel_width < 0 ) 00177 PLERROR("Supersampling2DModule::build_: 'kernel_width'<0 (%i).\n", 00178 kernel_width); 00179 00180 // Build the learntoptions from the buildoptions 00181 input_images_size = input_images_length * input_images_width; 00182 input_size = n_input_images * input_size; 00183 00184 output_images_length = input_images_length * kernel_length; 00185 output_images_width = input_images_width * kernel_width; 00186 output_images_size = output_images_length * output_images_width; 00187 00188 kernel_size = kernel_length * kernel_width; 00189 00190 scale.resize(n_input_images); 00191 bias.resize(n_input_images); 00192 00193 input_images.resize(n_input_images); 00194 output_images.resize(n_input_images); 00195 input_gradients.resize(n_input_images); 00196 output_gradients.resize(n_input_images); 00197 kernel_gradient.resize(kernel_length, kernel_width); 00198 } 00199 00200 void Supersampling2DModule::build() 00201 { 00202 inherited::build(); 00203 build_(); 00204 } 00205 00206 00207 void Supersampling2DModule::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00208 { 00209 inherited::makeDeepCopyFromShallowCopy(copies); 00210 00211 deepCopyField(scale, copies); 00212 deepCopyField(bias, copies); 00213 deepCopyField(input_images, copies); 00214 deepCopyField(output_images, copies); 00215 deepCopyField(input_gradients, copies); 00216 deepCopyField(output_gradients, copies); 00217 deepCopyField(kernel, copies); 00218 deepCopyField(squared_kernel, copies); 00219 deepCopyField(kernel_gradient, copies); 00220 00221 } 00222 00224 void Supersampling2DModule::fprop(const Vec& input, Vec& output) const 00225 { 00226 // Check size 00227 if( input.size() != input_size ) 00228 PLERROR("Supersampling2DModule::fprop: input.size() should be equal" 00229 " to\n" 00230 "input_size (%i != %i).\n", input.size(), input_size); 00231 output.resize(output_size); 00232 00233 // Make input_images and output_images point to the right places 00234 for( int i=0 ; i<n_input_images ; i++ ) 00235 { 00236 input_images[i] = 00237 input.subVec(i*input_images_size, input_images_size) 00238 .toMat( input_images_length, input_images_width ); 00239 00240 output_images[i] = 00241 output.subVec(i*output_images_size, output_images_size) 00242 .toMat( output_images_length, output_images_width ); 00243 } 00244 00245 // Compute the values of the output_images 00246 for( int i=0 ; i<n_input_images ; i++ ) 00247 { 00248 output_images[i].fill( bias[i] ); 00249 kernel.fill( scale[i] ); 00250 backConvolve2D( output_images[i], kernel, input_images[i], 00251 kernel_length, kernel_width, true ); 00252 } 00253 } 00254 00255 /* THIS METHOD IS OPTIONAL 00266 void Supersampling2DModule::bpropUpdate(const Vec& input, const Vec& output, 00267 const Vec& output_gradient) 00268 { 00269 } 00270 */ 00271 00273 void Supersampling2DModule::bpropUpdate(const Vec& input, const Vec& output, 00274 Vec& input_gradient, 00275 const Vec& output_gradient, 00276 bool accumulate) 00277 { 00278 // Check size 00279 if( input.size() != input_size ) 00280 PLERROR("Supersampling2DModule::bpropUpdate: input.size() should be\n" 00281 "equal to input_size (%i != %i).\n", input.size(), input_size); 00282 if( output.size() != output_size ) 00283 PLERROR("Supersampling2DModule::bpropUpdate: output.size() should be\n" 00284 "equal to output_size (%i != %i).\n", 00285 output.size(), output_size); 00286 if( output_gradient.size() != output_size ) 00287 PLERROR("Supersampling2DModule::bpropUpdate: output_gradient.size()" 00288 " should be\n" 00289 "equal to output_size (%i != %i).\n", 00290 output_gradient.size(), output_size); 00291 00292 if( accumulate ) 00293 { 00294 PLASSERT_MSG( input_gradient.size() == input_size, 00295 "Cannot resize input_gradient AND accumulate into it" ); 00296 } 00297 else 00298 input_gradient.resize(input_size); 00299 00300 // Since fprop() has just been called, we assume that input_images, 00301 // output_images and gradient are up-to-date 00302 // Make input_gradients and output_gradients point to the right places 00303 for( int i=0 ; i<n_input_images ; i++ ) 00304 { 00305 input_gradients[i] = 00306 input_gradient.subVec(i*input_images_size, input_images_size) 00307 .toMat( input_images_length, input_images_width ); 00308 00309 output_gradients[i] = 00310 output_gradient.subVec(i*output_images_size, output_images_size) 00311 .toMat( output_images_length, output_images_width ); 00312 } 00313 00314 // Do the actual bprop and update 00315 learning_rate = start_learning_rate / (1+decrease_constant*step_number); 00316 for( int i=0 ; i<n_input_images ; i++ ) 00317 { 00318 kernel.fill( scale[i] ); 00319 kernel_gradient.clear(); 00320 backConvolve2Dbackprop( kernel, input_images[i], 00321 input_gradients[i], 00322 output_gradients[i], kernel_gradient, 00323 kernel_length, kernel_width, accumulate ); 00324 00325 // The scale's gradient is the sum of contributions to kernel_gradient 00326 scale[i] -= learning_rate * sum( kernel_gradient ); 00327 bias[i] -= learning_rate * sum( output_gradients[i] ); 00328 } 00329 } 00330 00333 void Supersampling2DModule::forget() 00334 { 00335 bias.clear(); 00336 00337 if( !random_gen ) 00338 { 00339 PLWARNING( "Supersampling2DModule: cannot forget() without random_gen" 00340 ); 00341 return; 00342 } 00343 real scale_factor = 1./(kernel_length*kernel_width); 00344 random_gen->fill_random_uniform( scale, -scale_factor, scale_factor ); 00345 } 00346 00347 /* THIS METHOD IS OPTIONAL 00352 void Supersampling2DModule::finalize() 00353 { 00354 } 00355 */ 00356 00357 /* THIS METHOD IS OPTIONAL 00360 bool Supersampling2DModule::bpropDoesNothing() 00361 { 00362 } 00363 */ 00364 00365 /* THIS METHOD IS OPTIONAL 00375 void Supersampling2DModule::bbpropUpdate(const Vec& input, const Vec& output, 00376 const Vec& output_gradient, 00377 const Vec& output_diag_hessian) 00378 { 00379 } 00380 */ 00381 00386 void Supersampling2DModule::bbpropUpdate(const Vec& input, const Vec& output, 00387 Vec& input_gradient, 00388 const Vec& output_gradient, 00389 Vec& input_diag_hessian, 00390 const Vec& output_diag_hessian, 00391 bool accumulate) 00392 { 00393 // This version forwards the second order information, but does not 00394 // actually use it for the update. 00395 00396 // Check size 00397 if( output_diag_hessian.size() != output_size ) 00398 PLERROR("Supersampling2DModule::bbpropUpdate:" 00399 " output_diag_hessian.size()\n" 00400 "should be equal to output_size (%i != %i).\n", 00401 output_diag_hessian.size(), output_size); 00402 00403 if( accumulate ) 00404 { 00405 PLASSERT_MSG( input_diag_hessian.size() == input_size, 00406 "Cannot resize input_diag_hessian AND accumulate into it" 00407 ); 00408 } 00409 else 00410 input_diag_hessian.resize(input_size); 00411 00412 // Make input_diag_hessians and output_diag_hessians point to the right 00413 // places 00414 for( int i=0 ; i<n_input_images ; i++ ) 00415 { 00416 input_diag_hessians[i] = 00417 input_diag_hessian.subVec(i*input_images_size, input_images_size) 00418 .toMat( input_images_length, input_images_width ); 00419 00420 output_diag_hessians[i] = 00421 output_diag_hessian.subVec(i*output_images_size,output_images_size) 00422 .toMat( output_images_length, output_images_width ); 00423 } 00424 00425 // Propagates to input_diag_hessian 00426 for( int i=0 ; i<n_input_images ; i++ ) 00427 { 00428 kernel.fill( scale[i] ); 00429 squared_kernel.fill( scale[i]*scale[i] ); 00430 convolve2D( output_diag_hessians[i], squared_kernel, 00431 input_diag_hessians[i], 00432 kernel_length, kernel_width, accumulate ); 00433 } 00434 00435 // Call bpropUpdate() 00436 bpropUpdate( input, output, input_gradient, output_gradient ); 00437 } 00438 00439 00440 } // end of namespace PLearn 00441 00442 00443 /* 00444 Local Variables: 00445 mode:c++ 00446 c-basic-offset:4 00447 c-file-style:"stroustrup" 00448 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00449 indent-tabs-mode:nil 00450 fill-column:79 00451 End: 00452 */ 00453 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :