PLearn 0.1
|
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 :