PLearn 0.1
RBMConnection.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // RBMConnection.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 #include "RBMConnection.h"
00041 #include <plearn/math/TMat_maths.h>
00042 #include <plearn/base/stringutils.h>
00043 #include <plearn/base/RemoteMethodMap.h>
00044 
00045 namespace PLearn {
00046 using namespace std;
00047 
00048 PLEARN_IMPLEMENT_ABSTRACT_OBJECT(
00049     RBMConnection,
00050     "Virtual class for the linear transformation between two layers of an RBM",
00051     "");
00052 
00054 // RBMConnection //
00056 RBMConnection::RBMConnection(real the_learning_rate, bool call_build_):
00057     inherited("", call_build_),
00058     learning_rate(the_learning_rate),
00059     momentum(0.),
00060     down_size(-1),
00061     up_size(-1),
00062     going_up(true),
00063     pos_count(0),
00064     neg_count(0)
00065 {
00066     if (call_build_)
00067         build_();
00068 }
00069 
00071 // declareOptions //
00073 void RBMConnection::declareOptions(OptionList& ol)
00074 {
00075     declareOption(ol, "down_size", &RBMConnection::down_size,
00076                   OptionBase::buildoption,
00077                   "Number of units in down layer.");
00078 
00079     declareOption(ol, "up_size", &RBMConnection::up_size,
00080                   OptionBase::buildoption,
00081                   "Number of units in up layer.");
00082 
00083     declareOption(ol, "learning_rate", &RBMConnection::learning_rate,
00084                   OptionBase::buildoption,
00085                   "The learning rate, used both in update() and bpropUpdate() "
00086                   "methods\n");
00087 
00088     declareOption(ol, "momentum", &RBMConnection::momentum,
00089                   OptionBase::buildoption,
00090                   "The momentum, used both in update() and bpropUpdate() "
00091                   "methods\n");
00092 
00093     declareOption(ol, "initialization_method",
00094                   &RBMConnection::initialization_method,
00095                   OptionBase::buildoption,
00096                   "The method used to initialize the weights:\n"
00097                   "  - \"uniform_linear\" = a uniform law in [-1/d, 1/d]\n"
00098                   "  - \"uniform_sqrt\"   = a uniform law in [-1/sqrt(d),"
00099                   " 1/sqrt(d)]\n"
00100                   "  - \"zero\"           = all weights are set to 0,\n"
00101                   "where d = max( up_layer_size, down_layer_size ).\n");
00102 
00103     // Now call the parent class' declareOptions
00104     inherited::declareOptions(ol);
00105 
00106     redeclareOption(ol, "input_size", &RBMConnection::input_size,
00107                     OptionBase::learntoption,
00108                     "Equals to down_size");
00109 
00110     redeclareOption(ol, "output_size", &RBMConnection::output_size,
00111                     OptionBase::learntoption,
00112                     "Equals to up_size");
00113 }
00114 
00115 void RBMConnection::declareMethods(RemoteMethodMap& rmm)
00116 {
00117     rmm.inherited(inherited::_getRemoteMethodMap_());
00118 
00119     declareMethod(rmm, "setAsDownInput", &RBMConnection::setAsDownInput,
00120                   (BodyDoc("Sets 'input_vec' to 'input', and 'going_up' to true. \n"
00121                            "Note that no data copy is made, so 'input' should not be modified \n"
00122                            "afterwards."),
00123                    ArgDoc("const Vec& input", "The input vector")));
00124     declareMethod(rmm, "setAsUpInput", &RBMConnection::setAsUpInput,
00125                   (BodyDoc("Sets 'input_vec' to 'input', and 'going_up' to false. \n"
00126                            "Note that no data copy is made, so 'input' should not be modified \n"
00127                            "afterwards."),
00128                    ArgDoc("const Vec& input", "The input vector")));
00129 }
00130 
00132 // build_ //
00134 void RBMConnection::build_()
00135 {
00136     string im = lowerstring( initialization_method );
00137     if( im == "" || im == "uniform_sqrt" )
00138         initialization_method = "uniform_sqrt";
00139     else if( im == "uniform_linear" )
00140         initialization_method = im;
00141     else if( im == "zero" )
00142         initialization_method = im;
00143     else
00144         PLERROR( "RBMConnection::build_ - initialization_method\n"
00145                  "\"%s\" unknown.\n", initialization_method.c_str() );
00146 
00147     // for the "OnlineLearningModule" interface
00148     if( down_size < 0 )
00149         down_size = input_size;
00150     else
00151         input_size = down_size;
00152 
00153     if( up_size < 0 )
00154         up_size = output_size;
00155     else
00156         output_size = up_size;
00157 
00158     ports.resize(2);
00159     ports[0] = "down";
00160     ports[1] = "up";
00161     // NOT weights here, because it only makes sense with an
00162     // RBMMatrixConnection
00163 
00164     port_sizes.resize(nPorts(), 2);
00165     port_sizes.column(0).fill(-1);
00166     port_sizes(0, 1) = down_size;
00167     port_sizes(1, 1) = up_size;
00168 }
00169 
00171 // build //
00173 void RBMConnection::build()
00174 {
00175     inherited::build();
00176     build_();
00177 }
00178 
00179 
00181 // makeDeepCopyFromShallowCopy //
00183 void RBMConnection::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00184 {
00185     inherited::makeDeepCopyFromShallowCopy(copies);
00186 
00187     deepCopyField(input_vec, copies);
00188     deepCopyField(inputs_mat, copies);
00189 }
00190 
00192 // setLearningRate //
00194 void RBMConnection::setLearningRate( real the_learning_rate )
00195 {
00196     learning_rate = the_learning_rate;
00197 }
00198 
00200 // setMomentum //
00202 void RBMConnection::setMomentum( real the_momentum )
00203 {
00204     momentum = the_momentum;
00205 }
00206 
00208 // setAsUpInput //
00210 void RBMConnection::setAsUpInput( const Vec& input ) const
00211 {
00212     PLASSERT( input.size() == up_size );
00213     input_vec = input;
00214     going_up = false;
00215 }
00216 
00218 // setAsUpInputs //
00220 void RBMConnection::setAsUpInputs( const Mat& inputs ) const
00221 {
00222     PLASSERT( inputs.width() == up_size );
00223     inputs_mat = inputs;
00224     going_up = false;
00225 }
00226 
00228 // setAsDownInput //
00230 void RBMConnection::setAsDownInput( const Vec& input ) const
00231 {
00232     PLASSERT( input.size() == down_size );
00233     input_vec = input;
00234     going_up = true;
00235 }
00236 
00238 // setAsDownInputs //
00240 void RBMConnection::setAsDownInputs( const Mat& inputs ) const
00241 {
00242     PLASSERT( inputs.width() == down_size );
00243     inputs_mat = inputs;
00244     going_up = true;
00245 }
00246 
00248 // update //
00250 void RBMConnection::update( const Vec& pos_down_values,
00251                             const Vec& pos_up_values,
00252                             const Vec& neg_down_values,
00253                             const Vec& neg_up_values)
00254 {
00255     // Not-so-efficient implementation
00256     accumulatePosStats( pos_down_values, pos_up_values );
00257     accumulateNegStats( neg_down_values, neg_up_values );
00258     update();
00259 }
00260 
00261 void RBMConnection::update( const Mat& pos_down_values,
00262                             const Mat& pos_up_values,
00263                             const Mat& neg_down_values,
00264                             const Mat& neg_up_values)
00265 {
00266     // Not-so-efficient implementation.
00267     accumulatePosStats( pos_down_values, pos_up_values );
00268     accumulateNegStats( neg_down_values, neg_up_values );
00269     update();
00270 }
00271 
00272 // neg_stats <-- gibbs_chain_statistics_forgetting_factor * neg_stats
00273 //              +(1-gibbs_chain_statistics_forgetting_factor)
00274 //               * gibbs_neg_up_values'*gibbs_neg_down_values
00275 // delta w = lrate * ( pos_up_values'*pos_down_values
00276 //                  - ( background_gibbs_update_ratio*neg_stats
00277 //                     +(1-background_gibbs_update_ratio)
00278 //                      * cd_neg_up_values'*cd_neg_down_values))
00279 void RBMConnection::updateCDandGibbs( const Mat& pos_down_values,
00280                                       const Mat& pos_up_values,
00281                                       const Mat& cd_neg_down_values,
00282                                       const Mat& cd_neg_up_values,
00283                                       const Mat& gibbs_neg_down_values,
00284                                       const Mat& gibbs_neg_up_values,
00285                                       real background_gibbs_update_ratio)
00286 {
00287     PLASSERT_MSG(false, "Not implemented by subclass!");
00288 }
00289 
00290 // neg_stats <-- gibbs_chain_statistics_forgetting_factor * neg_stats
00291 //              +(1-gibbs_chain_statistics_forgetting_factor)
00292 //               * gibbs_neg_up_values'*gibbs_neg_down_values
00293 // delta w = lrate * ( pos_up_values'*pos_down_values - neg_stats )
00294 void RBMConnection::updateGibbs( const Mat& pos_down_values,
00295                                  const Mat& pos_up_values,
00296                                  const Mat& gibbs_neg_down_values,
00297                                  const Mat& gibbs_neg_up_values)
00298 {
00299     PLASSERT_MSG(false, "Not implemented by subclass!");
00300 }
00301 
00303 // fprop //
00305 void RBMConnection::fprop(const Vec& input, Vec& output) const
00306 {
00307     // propagates the activations.
00308     setAsDownInput( input );
00309     output.resize( output_size );
00310     computeProduct( 0, output_size, output );
00311 }
00312 
00313 void RBMConnection::fprop(const Mat& inputs, Mat& outputs)
00314 {
00315     int batch_size = inputs.length();
00316     // propagates the activations.
00317     setAsDownInputs(inputs);
00318     outputs.resize(batch_size, output_size);
00319     computeProducts(0, output_size, outputs);
00320 }
00321 
00322 void RBMConnection::getAllWeights(Mat& rbm_weights) const
00323 {
00324     PLERROR("In RBMConnection::getAllWeights(): not implemented");
00325 }
00326 
00327 void RBMConnection::setAllWeights(const Mat& rbm_weights)
00328 {
00329     PLERROR("In RBMConnection::setAllWeights(): not implemented");
00330 }
00331 
00332 void RBMConnection::petiteCulotteOlivierUpdate(
00333     const Vec& input, const Mat& rbm_weights,
00334     const Vec& output,
00335     Vec& input_gradient,
00336     Mat& rbm_weights_gradient,
00337     const Vec& output_gradient,
00338     bool accumulate)
00339 {
00340     PLERROR("In RBMConnection::bpropUpdate(): not implemented");
00341 }
00342 
00343 
00345 // bpropCD //
00347 void RBMConnection::petiteCulotteOlivierCD(Mat& weights_gradient,
00348                                            bool accumulate)
00349 {
00350     PLERROR("In RBMConnection::petiteCulotteOlivierCD(): not implemented");
00351 }
00352 
00353 void RBMConnection::petiteCulotteOlivierCD( const Vec& pos_down_values,
00354                                             const Vec& pos_up_values,
00355                                             const Vec& neg_down_values,
00356                                             const Vec& neg_up_values,
00357                                             Mat& weights_gradient,
00358                                             bool accumulate)
00359 {
00360     PLERROR("In RBMConnection::petiteCulotteOlivierCD(): not implemented");
00361 }
00362 
00364 // getPorts //
00366 const TVec<string>& RBMConnection::getPorts()
00367 {
00368     return ports;
00369 }
00370 
00372 // getPortSizes //
00374 const TMat<int>& RBMConnection::getPortSizes()
00375 {
00376     return port_sizes;
00377 }
00378 
00379 } // end of namespace PLearn
00380 
00381 
00382 /*
00383   Local Variables:
00384   mode:c++
00385   c-basic-offset:4
00386   c-file-style:"stroustrup"
00387   c-file-offsets:((innamespace . 0)(inline-open . 0))
00388   indent-tabs-mode:nil
00389   fill-column:79
00390   End:
00391 */
00392 // 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