PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // SquaredErrorCostModule.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 "SquaredErrorCostModule.h" 00042 #include <plearn/math/TMat_maths.h> 00043 00044 namespace PLearn { 00045 using namespace std; 00046 00047 PLEARN_IMPLEMENT_OBJECT( 00048 SquaredErrorCostModule, 00049 "Computes the sum of squared difference between input and target.", 00050 ""); 00051 00052 SquaredErrorCostModule::SquaredErrorCostModule() 00053 { 00054 output_size = 1; 00055 } 00056 00057 void SquaredErrorCostModule::declareOptions(OptionList& ol) 00058 { 00059 // declareOption(ol, "myoption", &SquaredErrorCostModule::myoption, 00060 // OptionBase::buildoption, 00061 // "Help text describing this option"); 00062 00063 // Now call the parent class' declareOptions 00064 inherited::declareOptions(ol); 00065 } 00066 00068 // build_ // 00070 void SquaredErrorCostModule::build_() 00071 { 00072 target_size = input_size; 00073 } 00074 00076 // build // 00078 void SquaredErrorCostModule::build() 00079 { 00080 inherited::build(); 00081 build_(); 00082 } 00083 00084 00086 // makeDeepCopyFromShallowCopy // 00088 void SquaredErrorCostModule::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00089 { 00090 inherited::makeDeepCopyFromShallowCopy(copies); 00091 } 00092 00093 00095 // fprop // 00097 void SquaredErrorCostModule::fprop(const TVec<Mat*>& ports_value) 00098 { 00099 PLASSERT( ports_value.length() == 3 ); 00100 Mat* pred = ports_value[0]; 00101 Mat* target = ports_value[1]; 00102 Mat* mse = ports_value[2]; 00103 if (mse && mse->isEmpty()) { 00104 PLASSERT( pred && !pred->isEmpty() && target && !target->isEmpty() ); 00105 mse->resize(pred->length(), 1); 00106 // TODO It may be possible to come up with a more efficient 00107 // implementation. 00108 for (int i = 0; i < pred->length(); i++) { 00109 (*mse)(i, 0) = powdistance( (*pred)(i), (*target)(i) ); 00110 } 00111 } 00112 checkProp(ports_value); 00113 } 00114 00115 void SquaredErrorCostModule::fprop(const Vec& input, const Vec& target, 00116 Vec& cost) const 00117 { 00118 PLASSERT( input.size() == input_size ); 00119 PLASSERT( target.size() == target_size ); 00120 cost.resize( output_size ); 00121 00122 cost[0] = powdistance( input, target ); 00123 } 00124 00126 // bpropUpdate // 00128 void SquaredErrorCostModule::bpropUpdate(const Vec& input, const Vec& target, 00129 real cost, Vec& input_gradient, 00130 bool accumulate) 00131 { 00132 PLASSERT( input.size() == input_size ); 00133 PLASSERT( target.size() == target_size ); 00134 00135 if( accumulate ) 00136 { 00137 PLASSERT_MSG( input_gradient.size() == input_size, 00138 "Cannot resize input_gradient AND accumulate into it" ); 00139 } 00140 else 00141 { 00142 input_gradient.resize( input_size ); 00143 input_gradient.clear(); 00144 } 00145 00146 // input_gradient = 2*(input - target) 00147 for( int i=0 ; i<input_size ; i++ ) 00148 { 00149 input_gradient[i] += 2*(input[i] - target[i]); 00150 } 00151 } 00152 00153 void SquaredErrorCostModule::bpropUpdate(const Mat& inputs, const Mat& targets, 00154 const Vec& costs, Mat& input_gradients, bool accumulate) 00155 { 00156 PLASSERT( inputs.width() == input_size ); 00157 PLASSERT( targets.width() == target_size ); 00158 00159 if( accumulate ) 00160 { 00161 PLASSERT_MSG( input_gradients.width() == input_size && 00162 input_gradients.length() == inputs.length(), 00163 "Cannot resize input_gradients AND accumulate into it" ); 00164 } 00165 else 00166 { 00167 input_gradients.resize( inputs.length(), input_size ); 00168 input_gradients.clear(); 00169 } 00170 00171 // input_gradient = 2*(input - target) 00172 // TODO This is a dumb unefficient implementation, for testing purpose. 00173 for (int k = 0; k < inputs.length(); k++) 00174 for( int i=0 ; i<input_size ; i++ ) 00175 { 00176 input_gradients(k, i) += 2*(inputs(k, i) - targets(k, i)); 00177 } 00178 } 00179 00181 // bbpropUpdate // 00183 void SquaredErrorCostModule::bbpropUpdate(const Vec& input, const Vec& target, 00184 real cost, 00185 Vec& input_gradient, 00186 Vec& input_diag_hessian, 00187 bool accumulate) 00188 { 00189 if( accumulate ) 00190 { 00191 PLASSERT_MSG( input_diag_hessian.size() == input_size, 00192 "Cannot resize input_diag_hessian AND accumulate into it" 00193 ); 00194 input_diag_hessian += real(2.); 00195 } 00196 else 00197 { 00198 input_diag_hessian.resize( input_size ); 00199 input_diag_hessian.fill( 2. ); 00200 } 00201 00202 bpropUpdate( input, target, cost, input_gradient, accumulate ); 00203 } 00204 00205 TVec<string> SquaredErrorCostModule::costNames() 00206 { 00207 if (name == "" || name == classname()) 00208 return TVec<string>(1, "mse"); 00209 else 00210 return TVec<string>(1, name + ".mse"); 00211 } 00212 00213 } // end of namespace PLearn 00214 00215 00216 /* 00217 Local Variables: 00218 mode:c++ 00219 c-basic-offset:4 00220 c-file-style:"stroustrup" 00221 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00222 indent-tabs-mode:nil 00223 fill-column:79 00224 End: 00225 */ 00226 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :