PLearn 0.1
HeterogenuousAffineTransformVariable.cc
Go to the documentation of this file.
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines