PLearn 0.1
ConstrainVariable.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // ConstrainVariable.cc
00004 //
00005 // Copyright (C) 2008 Pascal Vincent
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 Vincent
00036 
00039 #include "ConstrainVariable.h"
00040 // #include "Var_operators.h"
00041 //#include "Var_utils.h"
00042 
00043 namespace PLearn {
00044 using namespace std;
00045 
00046 
00049 PLEARN_IMPLEMENT_OBJECT(
00050         ConstrainVariable,
00051         "Correctly enforces the box constraint defined by min_value and max_value on each element.",
00052         "Also makes sure the sum of each row does not exceed max_rowsum.\n"
00053         "If a row sum exceeds max_rowsum, then all its elements are scaled by max_rowsum/current_row_sum.\n"
00054         "BEWARE: the gradient backprop depends on the sign of the gradient received.\n"
00055         "it is intentioally *not* symmetric w.r.t. that sign when stuck a box constraint.\n"
00056         "It is designed to work correctly if the sign of the gradient received indicates the direction \n"
00057         "in which the downstream variables would like this variable's output to move. \n"
00058         "This means for ex. that if you are doing gradient descent, then the cost should have been\n"
00059         "given a negative value (ex: -1) in its 'gradient'"
00060 );
00061 
00063 // ConstrainVariable //
00065 
00066 ConstrainVariable::ConstrainVariable():
00067     max_rowsum(FLT_MAX)
00068 {}
00069 
00070 ConstrainVariable::ConstrainVariable(Variable* input, bool call_build_):
00071     inherited(input, min(input->length(), input->width()), 1, call_build_),
00072     max_rowsum(FLT_MAX)
00073 {
00074     if (call_build_)
00075         build_();
00076 }
00077 
00079 // declareOptions //
00081 void Variable::declareOptions(OptionList& ol)
00082 {
00083     declareOption(ol, "max_rowsum", &ConstrainVariable::max_rowsum, OptionBase::buildoption, 
00084                   "maximum value the sum of elements in a row is allowed to reach\n");
00085 
00086     inherited::declareOptions(ol);
00087 }
00088 
00090 // build //
00092 void ConstrainVariable::build() {
00093     inherited::build();
00094     build_();
00095 }
00096 
00098 // build_ //
00100 void ConstrainVariable::build_() {
00101     // Nothing to do here.
00102 }
00103 
00105 // recomputeSize //
00107 void ConstrainVariable::recomputeSize(int& l, int& w) const
00108 {
00109     if (input) 
00110     {
00111         l = input->length();
00112         w = input->width();
00113     } 
00114     else
00115         l = w = 0;
00116 }
00117 
00118 
00119 void ConstrainVariable::fprop()
00120 {
00121     Mat U = input->matValue;
00122     int l = U.length();
00123     int w = U.width();
00124     for(int i=0; i<l; i++)
00125     {
00126         real* ui = U[i];
00127         real* vi = matValue[i];
00128         real tot = 0;
00129         for(int j=0; j<w; j++)
00130         {
00131             real x = box_constrain(ui[j]);
00132             tot += x;
00133             vi[j] = x;
00134         }
00135         if(tot>max_rowsum)
00136         {
00137             real coef = max_rowsum/tot;
00138             for(int j=0; j<w; j++)
00139                 vi[j] *= coef;
00140         }
00141     }
00142 }
00143 
00144 void ConstrainVariable::bprop()
00145 {
00146     Mat U = input->matValue;
00147     Mat Ug = input->matGradient;
00148     int l = U.length();
00149     int w = U.width();
00150     for(int i=0; i<l; i++)
00151     {
00152         real* ui = U[i];
00153         real* ugi = Ug[i];
00154         real* vgi = matGradient[i];
00155 
00156         real tot = 0;
00157         for(int j=0; j<w; j++)
00158             tot += box_constrain(ui[j]);
00159 
00160         real coef = 1;
00161         if(tot>max_rowsum)
00162             coef = max_rowsum/tot;
00163 
00164         for(int j=0; j<w; j++)
00165         {
00166             real v = ui[j];
00167             real g = vgi[j];                
00168             if((g<0 && v>min_value) || (g>0 && v<max_value))
00169                 ugi[j] += g*coef;
00170         }
00171     }
00172 
00173 }
00174 
00175 
00176 void ConstrainVariable::bbprop()
00177 {
00178     PLERROR("bbprop not implemented for this variable");
00179 }
00180 
00181 
00182 void ConstrainVariable::symbolicBprop()
00183 {
00184     PLERROR("symbolic bprop not yet implemented for this variable");
00185 }
00186 
00187 
00188 void ConstrainVariable::rfprop()
00189 {
00190     PLERROR("rfprop no yet implemented for this vairable");
00191 }
00192 
00193 
00194 
00195 } // end of namespace PLearn
00196 
00197 
00198 /*
00199   Local Variables:
00200   mode:c++
00201   c-basic-offset:4
00202   c-file-style:"stroustrup"
00203   c-file-offsets:((innamespace . 0)(inline-open . 0))
00204   indent-tabs-mode:nil
00205   fill-column:79
00206   End:
00207 */
00208 // 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