PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // PLearn (A C++ Machine Learning Library) 00004 // Copyright (C) 1998 Pascal Vincent 00005 // Copyright (C) 1999-2002 Pascal Vincent, Yoshua Bengio and University of Montreal 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 00036 00037 00038 /* ******************************************************* 00039 * $Id: ObjectOptionVariable.cc 5354 2006-04-11 18:04:57Z tihocan $ 00040 * This file is part of the PLearn library. 00041 ******************************************************* */ 00042 00043 #include "ObjectOptionVariable.h" 00044 #include <plearn/base/TypeTraits.h> 00045 #include <plearn/base/OptionBase.h> 00046 #include <plearn/base/lexical_cast.h> 00047 #include <plearn/math/TMat_maths.h> 00048 00049 namespace PLearn { 00050 using namespace std; 00051 00054 PLEARN_IMPLEMENT_OBJECT( 00055 ObjectOptionVariable, 00056 "Variable which wraps an option of an object.", 00057 "The option can refer to either an integer, a real value, a vector or a\n" 00058 "matrix within the object: the option will discover its size automatically.\n" 00059 "Furthermore, upon performing an fprop on the variable, this translates into\n" 00060 "a changeOption on the object.\n"); 00061 00062 ObjectOptionVariable::ObjectOptionVariable() 00063 : m_final_object(0), 00064 m_option_type(OptionTypeUnknown), 00065 m_option_int(0), 00066 m_index(-1) 00067 { } 00068 00069 ObjectOptionVariable::ObjectOptionVariable(PP<Object> root, const string& option_name, 00070 const string& initial_value) 00071 : m_root(root), 00072 m_option_name(option_name), 00073 m_initial_value(initial_value), 00074 m_final_object(0), 00075 m_option_type(OptionTypeUnknown), 00076 m_option_int(0), 00077 m_index(-1) 00078 { 00079 if (m_root) 00080 build(); 00081 } 00082 00083 00084 void ObjectOptionVariable::declareOptions(OptionList& ol) 00085 { 00086 inherited::declareOptions(ol); 00087 } 00088 00089 00090 void ObjectOptionVariable::build_() 00091 { 00092 PLASSERT( m_root ); 00093 PLASSERT( ! m_option_name.empty() ); 00094 if (! m_initial_value.empty()) 00095 m_root->changeOption(m_option_name, m_initial_value); 00096 00097 // Infer the option type from the option, set related member variables, and 00098 // initialize the base-class variable size 00099 OptionList::iterator option_iter; 00100 string option_index; 00101 if (m_root->parseOptionName(m_option_name, m_final_object, 00102 option_iter, option_index)) 00103 { 00104 PLASSERT( m_final_object ); 00105 void* bound_option = (*option_iter)->getAsVoidPtr(m_final_object); 00106 string option_type = (*option_iter)->optiontype(); 00107 if (! option_index.empty()) 00108 m_index = lexical_cast<int>(option_index); 00109 else 00110 m_index = -1; 00111 00112 // Set the appropriate pointer depending on the actual option type. If 00113 // an index is specified, don't immediately dereference it. Wait until 00114 // very last minute since the actual memory location the vector points 00115 // to may change with vector resizes/reallocations. 00116 if (option_type == TypeTraits<int>::name()) { 00117 m_option_type = OptionTypeInt; 00118 m_option_int = static_cast<int*>(bound_option); 00119 } 00120 else if (option_type == TypeTraits<real>::name()) { 00121 m_option_type = OptionTypeReal; 00122 m_option_real = static_cast<real*>(bound_option); 00123 } 00124 else if (option_type == TypeTraits<Vec>::name()) { 00125 m_option_type = OptionTypeVec; 00126 m_option_vec = static_cast<Vec*>(bound_option); 00127 } 00128 else if (option_type == TypeTraits<Mat>::name()) { 00129 m_option_type = OptionTypeMat; 00130 m_option_mat = static_cast<Mat*>(bound_option); 00131 } 00132 else 00133 PLERROR("ObjectOptionVariable::build: unhandled type \"%s\" the option " 00134 "\"%s\"; supported types are: { %s, %s, %s, %s }", 00135 option_type.c_str(), 00136 m_option_name.c_str(), 00137 TypeTraits<int>::name() .c_str(), 00138 TypeTraits<real>::name().c_str(), 00139 TypeTraits<Vec>::name() .c_str(), 00140 TypeTraits<Mat>::name() .c_str()); 00141 } 00142 00143 // Now properly set the size and initial contents of the variable 00144 switch (m_option_type) { 00145 case OptionTypeInt: 00146 PLASSERT( m_option_int ); 00147 inherited::resize(1,1); 00148 value[0] = *m_option_int; 00149 break; 00150 00151 case OptionTypeReal: 00152 PLASSERT( m_option_real ); 00153 inherited::resize(1,1); 00154 value[0] = *m_option_real; 00155 break; 00156 00157 case OptionTypeVec: 00158 // Assume row vector 00159 PLASSERT( m_option_vec ); 00160 if (m_index < 0 || m_option_vec->size() == 0) { 00161 inherited::resize(1, m_option_vec->size()); 00162 value << *m_option_vec; 00163 } 00164 else { 00165 inherited::resize(1,1); 00166 value[0] = (*m_option_vec)[m_index]; 00167 } 00168 break; 00169 00170 case OptionTypeMat: 00171 // Indexing works for ROWS in the case of matrices 00172 PLASSERT( m_option_mat ); 00173 if (m_index < 0 || m_option_mat->length() == 0) { 00174 inherited::resize(m_option_mat->length(), m_option_mat->width()); 00175 matValue << *m_option_mat; 00176 } 00177 else { 00178 inherited::resize(1, m_option_mat->width()); 00179 value << (*m_option_mat)(m_index); 00180 } 00181 break; 00182 00183 default: 00184 PLASSERT( false ); 00185 } 00186 } 00187 00188 void ObjectOptionVariable::build() 00189 { 00190 inherited::build(); 00191 build_(); 00192 } 00193 00194 00195 00196 void ObjectOptionVariable::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00197 { 00198 inherited::makeDeepCopyFromShallowCopy(copies); 00199 deepCopyField(m_root, copies); 00200 build(); 00201 } 00202 00203 void ObjectOptionVariable::fprop() 00204 { 00205 // Depending on the type of the option, set the proper contents of the option. 00206 switch (m_option_type) { 00207 case OptionTypeInt: 00208 { 00209 PLASSERT( m_option_int ); 00210 *m_option_int = int(value[0]); 00211 break; 00212 } 00213 00214 case OptionTypeReal: 00215 { 00216 PLASSERT( m_option_real ); 00217 *m_option_real = value[0]; 00218 break; 00219 } 00220 00221 case OptionTypeVec: 00222 { 00223 PLASSERT( m_option_vec ); 00224 if (m_index < 0) 00225 *m_option_vec << value; 00226 else 00227 (*m_option_vec)[m_index] = value[0]; 00228 break; 00229 } 00230 00231 case OptionTypeMat: 00232 { 00233 PLASSERT( m_option_mat ); 00234 if (m_index < 0) 00235 *m_option_mat << matValue; 00236 else 00237 (*m_option_mat)(m_index)<< value; 00238 break; 00239 } 00240 00241 default: 00242 PLASSERT( false ); 00243 } 00244 00245 // Rebuild the object to reflect the change; we should find a smart way to 00246 // optimize this away in the future 00247 PLASSERT( m_final_object ); 00248 m_final_object->build(); 00249 } 00250 00251 void ObjectOptionVariable::setParents(const VarArray& parents) 00252 { 00253 PLERROR("ObjectOptionVariable::setParents: this variable has no parents."); 00254 } 00255 00256 void ObjectOptionVariable::bprop() {} // No input: nothing to bprop 00257 void ObjectOptionVariable::bbprop() {} // No input: nothing to bbprop 00258 void ObjectOptionVariable::rfprop() {} // No input: nothing to rfprop 00259 void ObjectOptionVariable::symbolicBprop() {} // No input: nothing to bprop 00260 00261 VarArray ObjectOptionVariable::sources() 00262 { 00263 if (!marked) 00264 { 00265 setMark(); 00266 return Var(this); 00267 } 00268 return VarArray(0,0); 00269 } 00270 00271 VarArray ObjectOptionVariable::random_sources() 00272 { 00273 if (!marked) 00274 setMark(); 00275 return VarArray(0,0); 00276 } 00277 00278 VarArray ObjectOptionVariable::ancestors() 00279 { 00280 if (marked) 00281 return VarArray(0,0); 00282 setMark(); 00283 return Var(this); 00284 } 00285 00286 void ObjectOptionVariable::unmarkAncestors() 00287 { 00288 if (marked) 00289 clearMark(); 00290 } 00291 00292 VarArray ObjectOptionVariable::parents() 00293 { 00294 return VarArray(0,0); 00295 } 00296 00297 bool ObjectOptionVariable::markPath() 00298 { 00299 return marked; 00300 } 00301 00302 void ObjectOptionVariable::buildPath(VarArray& proppath) 00303 { 00304 if(marked) 00305 { 00306 proppath.append(Var(this)); 00307 clearMark(); 00308 } 00309 } 00310 00311 00312 //##### update* ############################################################# 00313 00314 bool ObjectOptionVariable::update(real step_size, Vec direction_vec, real coeff, real b) 00315 { 00316 bool ret = inherited::update(step_size, direction_vec, coeff, b); 00317 fprop(); 00318 return ret; 00319 } 00320 00321 bool ObjectOptionVariable::update(Vec step_sizes, Vec direction_vec, real coeff, real b) 00322 { 00323 bool ret = inherited::update(step_sizes, direction_vec, coeff, b); 00324 fprop(); 00325 return ret; 00326 } 00327 00328 bool ObjectOptionVariable::update(real step_size, bool clear) 00329 { 00330 bool ret = inherited::update(step_size, clear); 00331 fprop(); 00332 return ret; 00333 } 00334 00335 bool ObjectOptionVariable::update(Vec new_value) 00336 { 00337 bool ret = inherited::update(new_value); 00338 fprop(); 00339 return ret; 00340 } 00341 00342 void ObjectOptionVariable::updateAndClear() 00343 { 00344 inherited::updateAndClear(); 00345 fprop(); 00346 } 00347 00348 void ObjectOptionVariable::updateWithWeightDecay(real step_size, real weight_decay, 00349 bool L1, bool clear) 00350 { 00351 inherited::updateWithWeightDecay(step_size, weight_decay, L1, clear); 00352 fprop(); 00353 } 00354 00355 00356 } // end of namespace PLearn 00357 00358 00359 /* 00360 Local Variables: 00361 mode:c++ 00362 c-basic-offset:4 00363 c-file-style:"stroustrup" 00364 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00365 indent-tabs-mode:nil 00366 fill-column:79 00367 End: 00368 */ 00369 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :