PLearn 0.1
AppendNeighborsVMatrix.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // AppendNeighborsVMatrix.cc
00004 //
00005 // Copyright (C) 2004 Martin Monperrus 
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  * $Id: AppendNeighborsVMatrix.cc 3994 2005-08-25 13:35:03Z chapados $ 
00037  ******************************************************* */
00038 
00039 // Authors: Hugo Larochelle
00040 
00044 #include "AppendNeighborsVMatrix.h"
00045 #include "GetInputVMatrix.h"
00046 #include "VMat_computeNearestNeighbors.h"
00047 #include <plearn/math/TMat_maths_impl.h>
00048 
00049 namespace PLearn {
00050 using namespace std;
00051 
00052 
00053 AppendNeighborsVMatrix::AppendNeighborsVMatrix()
00054     :inherited(), n_neighbors(1), append_neighbor_indices(false)
00055     /* ### Initialise all fields to their default value */
00056 {
00057 }
00058 
00059 PLEARN_IMPLEMENT_OBJECT(AppendNeighborsVMatrix, 
00060                         "Appends the nearest neighbors of the input samples of a source VMatrix.", 
00061                         "Takes a source VMatrix and appends in the input part the\n"
00062                         "nearest neighbors of the input vector, for each row. \n"
00063                         "The current row is excluded of the nearest neighbors\n"
00064                         "for that row.\n"
00065                         "Also, keeps the target and weight information.\n"
00066                         "Finally, the user can define a transformation function\n"
00067                         "to map the nearest neighbors to some other space. Note that\n"
00068                         "the nearest neighbors are still computed in the source VMatrix\n"
00069                         "input space."
00070     );
00071 
00072 void AppendNeighborsVMatrix::getNewRow(int i, const Vec& v) const
00073 {
00074     if (width_<0)
00075         PLERROR("AppendNeighborsVMatrix::getNewRow called but build was not done yet");
00076 
00077     for(int j=0; j<input_parts.width(); j++)
00078     {
00079         source->getExample(input_parts(i,j),input,target,weight);
00080         if(transformation)
00081         {
00082             transformation->fprop(input,transf);
00083             v.subVec(j*transf.length(),transf.length()) << transf;
00084             if(j==0) 
00085             {
00086                 if(append_neighbor_indices)
00087                     v.subVec(input_parts.width()*transf.length(),input_parts.width()) << input_parts(i);
00088                 v.subVec(inputsize_,source->targetsize()) << target;
00089                 if(weightsize() > 0) v[width_-1] = weight;
00090             }
00091                     
00092         }
00093         else
00094         {
00095             v.subVec(j*source->inputsize(),source->inputsize()) << input;
00096             if(j==0) 
00097             {         
00098                 if(append_neighbor_indices)
00099                     v.subVec(input_parts.width()*source->inputsize(),input_parts.width()) << input_parts(i);
00100                 v.subVec(inputsize_,source->targetsize()) << target;
00101                 if(weightsize() > 0) v[width_-1] = weight;
00102             }
00103 
00104         }
00105     }
00106 }
00107 
00108 void AppendNeighborsVMatrix::declareOptions(OptionList& ol)
00109 {
00110     declareOption(ol, "n_neighbors", &AppendNeighborsVMatrix::n_neighbors, OptionBase::buildoption,
00111                   "Number of nearest neighbors. Determines the width of this vmatrix, which\n"
00112                   "is source->width() * n_neighbors.\n");
00113 
00114     declareOption(ol, "transformation", &AppendNeighborsVMatrix::transformation, OptionBase::buildoption,
00115                   "Transformation to apply on the nearest neighbors\n");
00116 
00117     declareOption(ol, "append_neighbor_indices", &AppendNeighborsVMatrix::append_neighbor_indices, OptionBase::buildoption,
00118                   "Indication that the nearest neighbor indices should\n"
00119                   "appended to the input part. The index of the current\n"
00120                   "sample is also appended.\n");
00121 
00122     // Now call the parent class' declareOptions
00123     inherited::declareOptions(ol);
00124 }
00125 
00126 void AppendNeighborsVMatrix::build_()
00127 {
00128     updateMtime(source);
00129     // find the nearest neighbors, if not done already
00130     if (source && (input_parts.length() != source->length() || input_parts.width() != n_neighbors+1 ))
00131         // WARNING: will not work if source is changed but has the same dimensions
00132     {
00133         if(n_neighbors <=0)
00134            PLERROR("In  AppendNeighborsVMatrix::build_(): n_neighbors should be > 0"); 
00135         input_parts.resize(source->length(),n_neighbors+1); // +1 because we also get current row
00136 
00137         input.resize(source->inputsize());
00138         target.resize(source->targetsize());
00139 
00140         VMat neighbors_source;
00141         if(source->targetsize() + source->weightsize() > 0)
00142         {
00143             GetInputVMatrix* givm = new GetInputVMatrix(source);
00144             neighbors_source = givm;
00145         }
00146         else
00147             neighbors_source = source;
00148 
00149         for (int i=0;i<source->length();i++)
00150         {
00151             source->getExample(i,input,target,weight);
00152             TVec<int> neighbors_of_i = input_parts(i);
00153             computeNearestNeighbors(neighbors_source,input,neighbors_of_i,-1);
00154         }
00155     }
00156 
00157     if(source->length()!=length_ || (transformation ? transformation->outputs.nelems() * input_parts.width() : source->inputsize() * input_parts.width()) 
00158        + (append_neighbor_indices ? input_parts.width() : 0) + source->targetsize() + source->weightsize() != width_)
00159     {
00160         if(transformation)
00161         {
00162             if(transformation->inputs.nelems() != source->inputsize())
00163                 PLERROR("Cannot use transformation with input size different from source->inputsize()");
00164             transf.resize(transformation->outputs.nelems());
00165 
00166             width_ = transformation->outputs.nelems() * input_parts.width()
00167                 + (append_neighbor_indices ? input_parts.width() : 0) 
00168                 + source->targetsize() + source->weightsize();
00169             length_ = source->length();
00170 
00171             if(inputsize_ < 0) 
00172                 inputsize_ = transformation->outputs.nelems() * input_parts.width()
00173                     + (append_neighbor_indices ? input_parts.width() : 0);
00174             if(targetsize_ < 0) targetsize_ = source->targetsize();
00175             if(weightsize_ < 0) weightsize_ = source->weightsize();            
00176         }
00177         else
00178         {
00179             width_ = source->inputsize() * input_parts.width() 
00180                 + (append_neighbor_indices ? input_parts.width() : 0) 
00181                 + source->targetsize() + source->weightsize();
00182             length_ = source->length();
00183 
00184             if(inputsize_ < 0) 
00185                 inputsize_ = source->inputsize() * input_parts.width()
00186                     + (append_neighbor_indices ? input_parts.width() : 0);
00187             if(targetsize_ < 0) targetsize_ = source->targetsize();
00188             if(weightsize_ < 0) weightsize_ = source->weightsize();            
00189 
00190         }
00191 
00192         if(width_ != inputsize_ + targetsize_ + weightsize_)
00193             PLERROR("In  AppendNeighborsVMatrix::build_(): width_ != inputsize_ + targetsize_ + weightsize_");
00194     }
00195 }
00196 
00197 // ### Nothing to add here, simply calls build_
00198 void AppendNeighborsVMatrix::build()
00199 {
00200     inherited::build();
00201     build_();
00202 }
00203 
00204 void AppendNeighborsVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00205 {
00206     inherited::makeDeepCopyFromShallowCopy(copies);
00207     deepCopyField(input, copies);
00208     deepCopyField(target, copies);
00209     deepCopyField(input_parts, copies);
00210     deepCopyField(transf, copies);
00211     deepCopyField(transformation, copies);
00212     
00213 }
00214 
00215 } // end of namespace PLearn
00216 
00217 
00218 /*
00219   Local Variables:
00220   mode:c++
00221   c-basic-offset:4
00222   c-file-style:"stroustrup"
00223   c-file-offsets:((innamespace . 0)(inline-open . 0))
00224   indent-tabs-mode:nil
00225   fill-column:79
00226   End:
00227 */
00228 // 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