PLearn 0.1
Supersampling2DModule.cc
Go to the documentation of this file.
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines