PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // HeterogenuousAffineTransformVariable.cc 00004 // 00005 // Copyright (C) 2006 Hugo Larochelle 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: Hugo Larochelle 00036 00040 #include "HeterogenuousAffineTransformVariable.h" 00041 00042 namespace PLearn { 00043 using namespace std; 00044 00047 PLEARN_IMPLEMENT_OBJECT( 00048 HeterogenuousAffineTransformVariable, 00049 "Affine transform with continuous and discrete input", 00050 "Affine transform that supports continuous and discrete input. The input\n" 00051 "(varray[0]) can contain a continuous value or the index of a symbol (e.g. a word).\n" 00052 "This is determined by the field input_is_discrete, which contains the information\n" 00053 "about which components are discrete.\n" 00054 "All the weights (varray[1..end], with varray.last() being the biases) have the\n" 00055 "same width, which corresponds to the size of this variable. The input must be a\n" 00056 "row or column vector, and this variable is either going to be a row or column\n" 00057 "vector, depending on the input." 00058 ); 00059 00060 HeterogenuousAffineTransformVariable::HeterogenuousAffineTransformVariable() 00061 {} 00062 00063 // constructors from input variables. 00064 HeterogenuousAffineTransformVariable::HeterogenuousAffineTransformVariable(Var input, VarArray weights, TVec<bool> the_input_is_discrete) 00065 : inherited(input & weights, 1, 1), input_is_discrete(the_input_is_discrete) 00066 // : inherited(input & weights, input->length() != 1 ? weights[0]->width() : 1 , input->width() != 1 ? weights[0]->width() : 1) 00067 { 00068 build(); 00069 } 00070 00071 void HeterogenuousAffineTransformVariable::recomputeSize(int& l, int& w) const 00072 { 00073 if (varray.size() > 1) 00074 { 00075 if(varray[0]->width() != 1) 00076 { 00077 l = 1; 00078 w = varray[1]->width(); 00079 } 00080 else 00081 { 00082 l = varray[1]->width() ; 00083 w = 1; 00084 } 00085 00086 } else 00087 l = w = 0; 00088 } 00089 00090 void HeterogenuousAffineTransformVariable::fprop() 00091 { 00092 matValue << varray.last()->matValue; 00093 int n = size(); 00094 int l = varray.length()-1; 00095 for(int i=1; i<l; i++) 00096 { 00097 if(input_is_discrete[i-1]) 00098 { 00099 real* row = varray[i]->matValue.row((int)varray[0]->valuedata[i-1]).data(); 00100 for(int j=0; j<n; j++) 00101 valuedata[j] += *row++; 00102 } 00103 else 00104 { 00105 for(int j=0; j<n; j++) 00106 valuedata[j] += varray[0]->valuedata[i-1]*varray[i]->valuedata[j]; 00107 } 00108 } 00109 } 00110 00111 void HeterogenuousAffineTransformVariable::bprop() 00112 { 00113 varray.last()->gradient += gradient; 00114 int n = size(); 00115 int l = varray.length()-1; 00116 for(int i=1; i<l; i++) 00117 { 00118 if(input_is_discrete[i-1]) 00119 { 00120 int r = (int)varray[0]->valuedata[i-1]; 00121 real* row = varray[i]->matGradient.row(r).data(); 00122 for(int j=0; j<n; j++) 00123 row[j] += gradientdata[j] ; 00124 varray[i]->updateRow(r); 00125 } 00126 else 00127 { 00128 for(int j=0; j<n; j++) 00129 { 00130 varray[i]->gradientdata[j] += gradientdata[j]*varray[0]->valuedata[i-1]; 00131 varray[0]->gradientdata[i-1] += gradientdata[j]*varray[i]->valuedata[j]; 00132 } 00133 } 00134 } 00135 00136 } 00137 00138 void HeterogenuousAffineTransformVariable::build() 00139 { 00140 inherited::build(); 00141 build_(); 00142 } 00143 00144 void HeterogenuousAffineTransformVariable::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00145 { 00146 inherited::makeDeepCopyFromShallowCopy(copies); 00147 00148 deepCopyField(input_is_discrete, copies); 00149 //PLERROR("HeterogenuousAffineTransformVariable::makeDeepCopyFromShallowCopy not fully (correctly) implemented yet!"); 00150 } 00151 00152 void HeterogenuousAffineTransformVariable::declareOptions(OptionList& ol) 00153 { 00154 declareOption(ol, "input_is_discrete", &HeterogenuousAffineTransformVariable::input_is_discrete, 00155 OptionBase::buildoption, 00156 "Indication whether each component of the input is discrete or not."); 00157 00158 // Now call the parent class' declareOptions 00159 inherited::declareOptions(ol); 00160 } 00161 00162 void HeterogenuousAffineTransformVariable::build_() 00163 { 00164 if(varray[0]->size() != varray.length()-2) 00165 PLERROR("In HeterogenuousAffineTransformVariable::build_(): The number of weight variables (%d) and input size (%d) is not the same", varray.length()-2, varray[0]->size()); 00166 if(input_is_discrete.length() != varray[0]->size()) 00167 PLERROR("In HeterogenuousAffineTransformVariable::build_(): input_is_discrete size (%d) and input size (%d) does not match", input_is_discrete.length(), varray[0]->size()); 00168 if(!varray[0]->isVec()) 00169 PLERROR("In HeterogenuousAffineTransformVariable::build_(): input should be a vector"); 00170 for(int i=1; i<varray.length(); i++) 00171 { 00172 if(varray[i]->width() != varray[1]->width()) 00173 PLERROR("In HeterogenuousAffineTransformVariable::build_(): %dth weight matrix has width %d, should be %d", i, varray[i]->width(), size()); 00174 if(i<varray.length()-1 && input_is_discrete[i-1]) 00175 varray[i-1]->allowPartialUpdates(); 00176 } 00177 } 00178 00179 00180 } // end of namespace PLearn 00181 00182 00183 /* 00184 Local Variables: 00185 mode:c++ 00186 c-basic-offset:4 00187 c-file-style:"stroustrup" 00188 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00189 indent-tabs-mode:nil 00190 fill-column:79 00191 End: 00192 */ 00193 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :