PLearn 0.1
StackedModulesModule.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // StackedModulesModule.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 
00041 #include "StackedModulesModule.h"
00042 
00043 namespace PLearn {
00044 using namespace std;
00045 
00046 PLEARN_IMPLEMENT_OBJECT(
00047     StackedModulesModule,
00048     "Wraps a stack of OnlineLearningModule, which are layers",
00049     "The OnlineLearningModule's are disposed like superposed layers:\n"
00050     "outputs of module i are the inputs of module (i+1), the last layer is\n"
00051     "the output layer.\n");
00052 
00053 StackedModulesModule::StackedModulesModule() :
00054     last_layer_is_cost( false ),
00055     target_size( 0 ),
00056     nmodules( 0 )
00057 {
00058 }
00059 
00060 void StackedModulesModule::declareOptions(OptionList& ol)
00061 {
00062     /*
00063     declareOption(ol, "", &StackedModulesModule::,
00064                   OptionBase::buildoption,
00065                   "");
00066      */
00067     declareOption(ol, "modules", &StackedModulesModule::modules,
00068                   OptionBase::buildoption,
00069                   "Underlying layers of the Module");
00070 
00071     declareOption(ol, "last_layer_is_cost",
00072                   &StackedModulesModule::last_layer_is_cost,
00073                   OptionBase::buildoption,
00074                   "Indicates if the last layer is a cost layer (taking input"
00075                   " and target\n"
00076                   "as input, and outputing the cost we will minimize),"
00077                   " allowing this\n"
00078                   "module to behave the same way.\n");
00079 
00080     declareOption(ol, "target_size", &StackedModulesModule::target_size,
00081                   OptionBase::buildoption,
00082                   "If last_layer_is_cost, the size of the target");
00083 
00084     declareOption(ol, "nmodules", &StackedModulesModule::nmodules,
00085                   OptionBase::learntoption,
00086                   "Number of module layers");
00087 
00088     // Now call the parent class' declareOptions
00089     inherited::declareOptions(ol);
00090 }
00091 
00092 void StackedModulesModule::build_()
00093 {
00094     // initialize random generator from seed
00095     if( !random_gen )
00096         random_gen = new PRandom();
00097     else
00098         random_gen->manual_seed( random_gen->seed_ );
00099 
00100     // get some options
00101     nmodules = modules.length();
00102     if( nmodules == 0 )
00103         return;
00104 
00105     if( last_layer_is_cost && target_size <= 0 )
00106         PLERROR("StackedModulesModule::build_() - Please provide a target_size"
00107                 "  > 0\n"
00108                 "(is '%d').\n", target_size );
00109     if( !last_layer_is_cost )
00110         target_size = 0;
00111 
00112     PLASSERT( modules[0]->input_size >= 0 );
00113     input_size = modules[0]->input_size + target_size;
00114 
00115 //    int last_module_output_size = modules[nmodules-1]->output_size;
00116 //    if( last_layer_is_cost )
00117 //        last_module_output_size = 1;
00118 
00119     output_size = modules[nmodules-1]->output_size;
00120 
00121     // build the modules
00122     buildLayers();
00123 
00124 }
00125 
00126 void StackedModulesModule::buildLayers()
00127 {
00128     // first values will be "input" values
00129     int size = input_size - target_size;
00130     values.resize( nmodules+1 );
00131     values[0].resize( size );
00132     gradients.resize( nmodules+1 );
00133     gradients[0].resize( size );
00134     // TODO: use it only if we actually use bbprop?
00135     diag_hessians.resize( nmodules+1 );
00136     diag_hessians[0].resize( size );
00137 
00138     for( int i=0 ; i<nmodules ; i++ )
00139     {
00140         modules[i]->estimate_simpler_diag_hessian =
00141             estimate_simpler_diag_hessian;
00142         modules[i]->random_gen = random_gen;
00143         modules[i]->build();
00144 
00145         size = modules[i]->output_size;
00146         values[i+1].resize( size );
00147         gradients[i+1].resize( size );
00148         diag_hessians[i+1].resize( size );
00149     }
00150 
00151     // stores the input of the last module, and the target if there is one
00152     cost_layer_input = values[nmodules-1];
00153     if( last_layer_is_cost )
00154         cost_layer_input.resize( cost_layer_input.size() + target_size );
00155 }
00156 
00157 void StackedModulesModule::build()
00158 {
00159     inherited::build();
00160     build_();
00161 }
00162 
00163 
00164 void StackedModulesModule::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00165 {
00166     inherited::makeDeepCopyFromShallowCopy(copies);
00167 
00168     deepCopyField(modules, copies);
00169     deepCopyField(values, copies);
00170     deepCopyField(cost_layer_input, copies);
00171     deepCopyField(gradients, copies);
00172     deepCopyField(diag_hessians, copies);
00173 }
00174 
00176 void StackedModulesModule::fprop(const Vec& input, Vec& output) const
00177 {
00178     PLASSERT( input.size() == input_size );
00179     PLASSERT( modules[0]->input_size + target_size == input_size );
00180     int last_input_size = values[nmodules-1].size();
00181 
00182     values[0] << input.subVec(0, input_size - target_size );
00183 
00184     for( int i=0 ; i<nmodules-1 ; i++ )
00185         modules[i]->fprop( values[i], values[i+1] );
00186 
00187     if( last_layer_is_cost )
00188     {
00189         cost_layer_input.subVec( last_input_size, target_size )
00190             << input.subVec( input_size - target_size, target_size );
00191     }
00192 
00193     modules[nmodules-1]->fprop( cost_layer_input, values[nmodules] );
00194     output.resize( output_size );
00195     output << values[ nmodules ];
00196 }
00197 
00200 void StackedModulesModule::bpropUpdate(const Vec& input, const Vec& output,
00201                                        Vec& input_gradient,
00202                                        const Vec& output_gradient)
00203 {
00204     // If last_layer_is_cost, the gradient wrt it is 1
00205     if( last_layer_is_cost )
00206         gradients[nmodules][0] = 1;
00207     else
00208         gradients[nmodules] << output_gradient;
00209 
00210     // values should have the values given by fprop(), so
00211     // values[nmodules] should already be equal to output
00212     modules[nmodules-1]->bpropUpdate( cost_layer_input, values[nmodules],
00213                                       gradients[nmodules-1],
00214                                       gradients[nmodules] );
00215 
00216     for( int i=nmodules-2 ; i>=0 ; i-- )
00217         modules[i]->bpropUpdate( values[i], values[i+1],
00218                                  gradients[i], gradients[i+1] );
00219 
00220     input_gradient = gradients[0].copy();
00221 }
00222 
00225 void StackedModulesModule::forget()
00226 {
00227     random_gen->manual_seed( random_gen->seed_ );
00228 
00229     // reset inputs
00230     values[0].clear();
00231     gradients[0].clear();
00232     diag_hessians[0].clear();
00233 
00234     // reset modules and outputs
00235     for( int i=0 ; i<nmodules ; i++ )
00236     {
00237         modules[i]->forget();
00238         values[i+1].clear();
00239         gradients[i+1].clear();
00240         diag_hessians[i+1].clear();
00241     }
00242 }
00243 
00244 /* THIS METHOD IS OPTIONAL
00249 void StackedModulesModule::finalize()
00250 {
00251 }
00252 */
00253 
00260 void StackedModulesModule::bbpropUpdate(const Vec& input, const Vec& output,
00261                                         Vec& input_gradient,
00262                                         const Vec& output_gradient,
00263                                         Vec& input_diag_hessian,
00264                                         const Vec& output_diag_hessian)
00265 {
00266     // If last_layer_is_cost, the gradient wrt it is 1 and hessian is 0
00267     if( last_layer_is_cost )
00268     {
00269         gradients[nmodules][0] = 1;
00270         diag_hessians[nmodules][0] = 1;
00271     }
00272     else
00273     {
00274         gradients[nmodules] << output_gradient;
00275         diag_hessians[nmodules] << output_diag_hessian;
00276     }
00277 
00278     // values should have the values given by fprop(), so
00279     // values[nmodules] should already be equal to output
00280     for( int i=nmodules-1 ; i>=0 ; i-- )
00281         modules[i]->bbpropUpdate( values[i], values[i+1],
00282                                   gradients[i], gradients[i+1],
00283                                   diag_hessians[i], diag_hessians[i+1] );
00284 
00285     input_gradient = gradients[0].copy();
00286     input_diag_hessian = diag_hessians[0].copy();
00287 }
00288 
00289 
00290 } // end of namespace PLearn
00291 
00292 
00293 /*
00294   Local Variables:
00295   mode:c++
00296   c-basic-offset:4
00297   c-file-style:"stroustrup"
00298   c-file-offsets:((innamespace . 0)(inline-open . 0))
00299   indent-tabs-mode:nil
00300   fill-column:79
00301   End:
00302 */
00303 // 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