PLearn 0.1
|
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 :