PLearn 0.1
UnfoldedFuncVariable.cc
Go to the documentation of this file.
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, Rejean Ducharme and University of Montreal
00006 // Copyright (C) 2001-2002 Nicolas Chapados, Ichiro Takeuchi, Jean-Sebastien Senecal
00007 // Copyright (C) 2002 Xiangdong Wang, Christian Dorion
00008 
00009 // Redistribution and use in source and binary forms, with or without
00010 // modification, are permitted provided that the following conditions are met:
00011 // 
00012 //  1. Redistributions of source code must retain the above copyright
00013 //     notice, this list of conditions and the following disclaimer.
00014 // 
00015 //  2. Redistributions in binary form must reproduce the above copyright
00016 //     notice, this list of conditions and the following disclaimer in the
00017 //     documentation and/or other materials provided with the distribution.
00018 // 
00019 //  3. The name of the authors may not be used to endorse or promote
00020 //     products derived from this software without specific prior written
00021 //     permission.
00022 // 
00023 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00024 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00025 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00026 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00027 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00028 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00029 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00030 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00031 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 // 
00034 // This file is part of the PLearn library. For more information on the PLearn
00035 // library, go to the PLearn Web site at www.plearn.org
00036 
00037 
00038 /* *******************************************************      
00039  * $Id: UnfoldedFuncVariable.cc 8580 2008-02-26 16:48:40Z tihocan $
00040  * This file is part of the PLearn library.
00041  ******************************************************* */
00042 
00043 #include "UnfoldedFuncVariable.h"
00044 //#include "PLMPI.h"
00045 //#include "DisplayUtils.h"
00046 
00047 namespace PLearn {
00048 using namespace std;
00049 
00050 
00051 
00054 PLEARN_IMPLEMENT_OBJECT(
00055         UnfoldedFuncVariable,
00056         "Computes the output of a Func over all elements on an input matrix.",
00057         "By default the function 'f' is applied over all rows of the input\n"
00058         "provided in 'input_matrix', but it may be applied on columns\n"
00059         "instead using the 'transpose' option.\n"
00060         "A separate propagation path is created (using the Func as a\n"
00061         "template) that maps each input to the corresponding output.\n"
00062         "The parents of this variable include the non-input parents of 'f'.");
00063 
00065 // UnfoldedFuncVariable //
00067 UnfoldedFuncVariable::UnfoldedFuncVariable():
00068     transpose(false)
00069 {}
00070 
00071 UnfoldedFuncVariable::UnfoldedFuncVariable(
00072         Var inputmatrix, Func the_f, bool the_transpose,
00073         Var bagsize, bool call_build_):
00074     inherited(VarArray(),
00075             the_transpose ? the_f->outputs[0]->length()
00076                                                 * the_f->outputs[0]->width()
00077                           : inputmatrix->length(),
00078             the_transpose ? inputmatrix->width()
00079                           : the_f->outputs[0]->length()
00080                                                 * the_f->outputs[0]->width(),
00081             call_build_),
00082       input_matrix(inputmatrix), 
00083       bag_size(bagsize),
00084       f(the_f),
00085       transpose(the_transpose)
00086 {
00087     if (call_build_)
00088         build_();
00089 }
00090 
00092 // build //
00094 void UnfoldedFuncVariable::build()
00095 {
00096     inherited::build();
00097     build_();
00098 }
00099 
00101 // build_ //
00103 void UnfoldedFuncVariable::build_()
00104 {
00105     if (f) {
00106         VarArray f_parents = nonInputParentsOfPath(f->inputs, f->outputs);
00107         varray.resize(f_parents.length() + 2);
00108         varray << (f_parents & input_matrix & bag_size);
00109 
00110         if(f->outputs.size()!=1)
00111             PLERROR("In UnfoldedFuncVariable: function must have a single variable output (maybe you can vconcat the vars into a single one prior to calling sumOf, if this is really what you want)");
00112         f->inputs.setDontBpropHere(true);
00113         int n_unfold = transpose ? input_matrix->width() : input_matrix->length();
00114         inputs.resize(n_unfold);
00115         outputs.resize(n_unfold);
00116         f_paths.resize(n_unfold);
00117         for (int i=0;i<n_unfold;i++)
00118         {
00119             inputs[i].resize(f->inputs.size());
00120             for (int j = 0; j < f->inputs.size(); j++) {
00121                 inputs[i][j] = Var(f->inputs[j]->length(), f->inputs[j]->width());
00122             }
00123             outputs[i] = f(inputs[i])[0];
00124             f_paths[i] = propagationPath(inputs[i],outputs[i]);
00125         }
00126         inherited::build(); // Re-build since varray has changed.
00127     }
00128 
00129     if (bag_size)
00130         PLASSERT( bag_size->isScalar() );
00131 }
00132 
00134 // declareOptions //
00136 void UnfoldedFuncVariable::declareOptions(OptionList& ol)
00137 {
00138     declareOption(ol, "f", &UnfoldedFuncVariable::f, OptionBase::buildoption, 
00139                   "    Func that is replicated for each element of the 'bag' taken from the VMat.");
00140 
00141     declareOption(ol, "input_matrix", &UnfoldedFuncVariable::input_matrix, OptionBase::buildoption, 
00142         "Var containing the data: multiple consecutive rows form one bag.");
00143 
00144     declareOption(ol, "bag_size", &UnfoldedFuncVariable::bag_size,
00145                   OptionBase::buildoption, 
00146         "Optional Var that contains the size of the bag being presented.\n"
00147         "If provided, then only the corresponding number of function values\n"
00148         "will be computed, while the rest of the output data matrix will be\n"
00149         "left untouched.");
00150 
00151     declareOption(ol, "transpose", &UnfoldedFuncVariable::transpose, OptionBase::buildoption, 
00152                   "    If set to 1, then instead puts in the columns of the output matrix the values\n"
00153                   "    of f at the columns of the input matrix.");
00154 
00155     inherited::declareOptions(ol);
00156 
00157     redeclareOption(ol, "varray", &UnfoldedFuncVariable::varray,
00158                     OptionBase::nosave,
00159             "This option is set at build time from other options.");
00160 }
00161 
00163 // recomputeSize //
00165 void UnfoldedFuncVariable::recomputeSize(int& l, int& w) const
00166 {
00167     if (f && f->outputs.size() > 0) {
00168         w = f->outputs[0]->length()*f->outputs[0]->width();
00169         if (transpose) {
00170             l = w;
00171             w = input_matrix->width();
00172         } else {
00173             l = input_matrix->length();
00174         }
00175     } else
00176         l = w = 0;
00177 }
00178 
00180 // makeDeepCopyFromShallowCopy //
00182 void UnfoldedFuncVariable::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00183 {
00184     inherited::makeDeepCopyFromShallowCopy(copies);
00185     deepCopyField(input_matrix, copies);
00186     deepCopyField(bag_size,     copies);
00187     deepCopyField(f,            copies);
00188     deepCopyField(inputs,       copies);
00189     deepCopyField(outputs,      copies);
00190     deepCopyField(f_paths,      copies);
00191 }
00192 
00194 // fprop //
00196 void UnfoldedFuncVariable::fprop()
00197 {
00198     int n_unfold = bag_size ? int(round(bag_size->value[0]))
00199                             : transpose ? input_matrix->width()
00200                                         : input_matrix->length();
00201     PLASSERT( !bag_size || is_equal(bag_size->value[0],
00202                                     round(bag_size->value[0])) );
00203     for (int i=0;i<n_unfold;i++) {
00204         if (transpose) {
00205             Vec tmp = input_matrix->matValue.column(i).toVecCopy(); // TODO something more efficient
00206             inputs[i] << tmp;
00207         } else {
00208             inputs[i] << input_matrix->matValue(i);
00209         }
00210         f_paths[i].fprop();
00211         if (transpose) {
00212             matValue.column(i) << outputs[i]->value;
00213         } else {
00214             matValue(i) << outputs[i]->value;
00215         }
00216     }
00217 }
00218 
00220 // bprop //
00222 void UnfoldedFuncVariable::bprop()
00223 { 
00224     int n_unfold = bag_size ? int(round(bag_size->value[0]))
00225                             : transpose ? input_matrix->width()
00226                                         : input_matrix->length();
00227     for (int i=0;i<n_unfold;i++)
00228     {
00229         f_paths[i].clearGradient();
00230         if (transpose) {
00231             Vec tmp = matGradient.column(i).toVecCopy(); // TODO more efficient + check while it compiled without tmp = toVecCopy
00232             outputs[i]->gradient << tmp;
00233         } else {
00234             outputs[i]->gradient << matGradient(i);
00235         }
00236         f_paths[i].bprop();
00237     }
00238 }
00239 
00241 // printInfo //
00243 void UnfoldedFuncVariable::printInfo(bool print_gradient)
00244 {
00245     int n_unfold = bag_size ? int(round(bag_size->value[0]))
00246                             : transpose ? input_matrix->width()
00247                                         : input_matrix->length();
00248     for (int i=0;i<n_unfold;i++)
00249         f_paths[i].printInfo(print_gradient);
00250     pout << info() << " : " << getName() << "[" << (void*)this << "]" 
00251          << "(input_matrix=" << (void*)input_matrix << " ";
00252     for(int i=0; i<n_unfold; i++)
00253         pout << (void*)outputs[i] << " ";
00254     pout << ") = " << value;
00255     if (print_gradient)
00256         pout << " gradient=" << gradient;
00257     pout << endl; 
00258 }
00259 
00260 } // end of namespace PLearn
00261 
00262 
00263 /*
00264   Local Variables:
00265   mode:c++
00266   c-basic-offset:4
00267   c-file-style:"stroustrup"
00268   c-file-offsets:((innamespace . 0)(inline-open . 0))
00269   indent-tabs-mode:nil
00270   fill-column:79
00271   End:
00272 */
00273 // 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