PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // PLearn (A C++ Machine Learning Library) 00004 // Copyright (C) 1998 Pascal Vincent 00005 // Copyright (C) 1999-2001 Pascal Vincent, Yoshua Bengio, Rejean Ducharme and University of Montreal 00006 // Copyright (C) 2002 Pascal Vincent, Julien Keable, Xavier Saint-Mleux 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are met: 00010 // 00011 // 1. Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // 00014 // 2. Redistributions in binary form must reproduce the above copyright 00015 // notice, this list of conditions and the following disclaimer in the 00016 // documentation and/or other materials provided with the distribution. 00017 // 00018 // 3. The name of the authors may not be used to endorse or promote 00019 // products derived from this software without specific prior written 00020 // permission. 00021 // 00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00033 // This file is part of the PLearn library. For more information on the PLearn 00034 // library, go to the PLearn Web site at www.plearn.org 00035 00036 00037 /* ******************************************************* 00038 * $Id: OneHotVMatrix.cc 9457 2008-09-15 19:05:16Z tihocan $ 00039 ******************************************************* */ 00040 00041 #include "OneHotVMatrix.h" 00042 #include <plearn/math/TMat_maths.h> 00043 00044 namespace PLearn { 00045 using namespace std; 00046 00047 00050 PLEARN_IMPLEMENT_OBJECT(OneHotVMatrix, 00051 "Transform an index into a one-hot vector.", 00052 "Sampling from this VMat will return the corresponding sample from\n" 00053 "the source VMat with last element ('target_classnum') replaced by\n" 00054 "a vector of target_values of size nclasses in which only\n" 00055 "target_values[target_classnum] is set to hot_value, and all the\n" 00056 "others are set to cold_value.\n" 00057 "In the special case where the VMat is built with nclasses==1, then\n" 00058 "it is assumed that we have a 2 class classification problem but\n" 00059 "we are using a single valued target. For this special case only\n" 00060 "the_cold_value is used as target for classnum 0 and the_hot_value\n" 00061 "is used for classnum 1.\n" 00062 ); 00063 00065 // OneHotVMatrix // 00067 OneHotVMatrix::OneHotVMatrix(bool call_build_) 00068 : inherited(call_build_), 00069 nclasses(0), cold_value(0.0), hot_value(1.0), index(-1) 00070 { 00071 if( call_build_ ) 00072 build_(); 00073 } 00074 00075 OneHotVMatrix::OneHotVMatrix(VMat the_source, int the_nclasses, 00076 real the_cold_value, real the_hot_value, 00077 int the_index, bool call_build_) 00078 : inherited(the_source, 00079 the_source->length(), 00080 the_source->width()+the_nclasses-1, 00081 call_build_), 00082 nclasses(the_nclasses), 00083 cold_value(the_cold_value), 00084 hot_value(the_hot_value), 00085 index(the_index) 00086 { 00087 if( call_build_ ) 00088 build_(); 00089 } 00090 00092 // build // 00094 void OneHotVMatrix::build() 00095 { 00096 inherited::build(); 00097 build_(); 00098 } 00099 00101 // build_ // 00103 void OneHotVMatrix::build_() 00104 { 00105 int source_inputsize = source->inputsize(); 00106 int source_targetsize = source->targetsize(); 00107 int source_weightsize = source->weightsize(); 00108 int source_width = source->width(); 00109 int source_length = source->length(); 00110 00111 length_ = source_length; 00112 width_ = source_width + nclasses - 1; 00113 00114 if(source_inputsize+source_targetsize+source_weightsize != source_width 00115 || source_targetsize != 1 ) // source->sizes are inconsistent 00116 { 00117 if( index < 0 ) 00118 { 00119 index = source_width - 1; 00120 updateNClassesAndWidth(); 00121 } 00122 if( inputsize_ + targetsize_ + weightsize_ != width() ) 00123 { 00124 // sizes are not set, or inconsistently 00125 inputsize_ = index; 00126 targetsize_ = nclasses; 00127 weightsize_ = width() - inputsize_ - targetsize_; 00128 } 00129 } 00130 else // source->sizes are consistent 00131 { 00132 if( index < 0 ) 00133 { 00134 index = source_inputsize; 00135 updateNClassesAndWidth(); 00136 } 00137 if( inputsize_ + targetsize_ + weightsize_ != width() ) 00138 { 00139 inputsize_ = source_inputsize; 00140 targetsize_ = source_targetsize; 00141 weightsize_ = source_weightsize; 00142 00143 if( index < inputsize_ ) 00144 inputsize_ += nclasses-1; 00145 else if( index < inputsize_ + targetsize_ ) 00146 targetsize_ += nclasses-1; 00147 else 00148 weightsize_ += nclasses-1; 00149 } 00150 } 00151 00152 TVec<string> fieldnames = source->fieldNames().copy(); 00153 00154 string target_name = fieldnames[ index ]; 00155 fieldnames.resize( width() ); 00156 for( int i=0 ; i<nclasses ; i++ ) 00157 fieldnames[ index+i ] = target_name + "_" + tostring(i); 00158 00159 fieldnames.subVec( index + nclasses, width() - index - nclasses ) 00160 << source->fieldNames().subVec( index + 1, source_width - index - 1 ); 00161 00162 00163 declareFieldNames( fieldnames ); 00164 setMetaInfoFromSource(); 00165 } 00166 00168 // declareOptions // 00170 void OneHotVMatrix::declareOptions(OptionList &ol) 00171 { 00172 declareOption(ol, "underlying_distr", &OneHotVMatrix::source, 00173 (OptionBase::learntoption | OptionBase::nosave), 00174 "DEPRECATED - use 'source' instead."); 00175 00176 declareOption(ol, "nclasses", &OneHotVMatrix::nclasses, 00177 OptionBase::buildoption, 00178 "Number of classes. If set to zero, then this number will be\n" 00179 "automatically found from the source VMat."); 00180 00181 declareOption(ol, "cold_value", &OneHotVMatrix::cold_value, 00182 OptionBase::buildoption, 00183 "Value used for non active elements in the one-hot vector."); 00184 00185 declareOption(ol, "hot_value", &OneHotVMatrix::hot_value, 00186 OptionBase::buildoption, 00187 "Value used for the active element in the one-hot vector."); 00188 00189 declareOption(ol, "index", &OneHotVMatrix::index, 00190 OptionBase::buildoption, 00191 "Index of the column on which we apply the one-hot transformation.\n" 00192 "By default, if targetsize==1 we take the target column, otherwise\n" 00193 "we take the last column."); 00194 00195 inherited::declareOptions(ol); 00196 } 00197 00199 // getNewRow // 00201 void OneHotVMatrix::getNewRow(int i, const Vec& samplevec) const 00202 { 00203 #ifdef BOUNDCHECK 00204 if(i<0 || i>=length()) 00205 PLERROR("In OneHotVMatrix::getNewRow OUT OF BOUNDS"); 00206 if(samplevec.length()!=width()) 00207 PLERROR("In OneHotVMatrix::getNewRow samplevec.length() must be\n" 00208 "equal to the VMat's width\n"); 00209 #endif 00210 Vec left = samplevec.subVec(0, index); 00211 Vec modified = samplevec.subVec(index, nclasses); 00212 Vec right = samplevec.subVec(index+nclasses, width()-index-nclasses); 00213 source->getSubRow(i, 0, left); 00214 int classnum = int(round(source->get(i, index))); 00215 fill_one_hot(modified, classnum, cold_value, hot_value); 00216 source->getSubRow(i, index+1, right); 00217 } 00218 00220 // dot // 00222 real OneHotVMatrix::dot(int i1, int i2, int inputsize) const 00223 { 00224 return source->dot(i1, i2, inputsize); 00225 } 00226 00227 real OneHotVMatrix::dot(int i, const Vec& v) const 00228 { 00229 return source->dot(i, v); 00230 } 00231 00232 00234 // updateNClassesAndWidth // 00236 void OneHotVMatrix::updateNClassesAndWidth() 00237 { 00238 if (nclasses > 0) 00239 return; 00240 PLASSERT( nclasses == 0 && index >= 0 ); 00241 real max = -1; 00242 for (int i = 0; i < source->length(); i++) { 00243 real val = source->get(i, index); 00244 if (val > max) 00245 max = val; 00246 } 00247 nclasses = int(round(max)) + 1; 00248 width_ += nclasses; 00249 } 00250 00251 } // end of namespace PLearn 00252 00253 00254 /* 00255 Local Variables: 00256 mode:c++ 00257 c-basic-offset:4 00258 c-file-style:"stroustrup" 00259 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00260 indent-tabs-mode:nil 00261 fill-column:79 00262 End: 00263 */ 00264 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :