PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // PLearn (A C++ Machine Learning Library) 00004 // Copyright (C) 2003 Pascal Vincent, Olivier Delalleau 00005 // 00006 // Redistribution and use in source and binary forms, with or without 00007 // modification, are permitted provided that the following conditions are met: 00008 // 00009 // 1. Redistributions of source code must retain the above copyright 00010 // notice, this list of conditions and the following disclaimer. 00011 // 00012 // 2. Redistributions in binary form must reproduce the above copyright 00013 // notice, this list of conditions and the following disclaimer in the 00014 // documentation and/or other materials provided with the distribution. 00015 // 00016 // 3. The name of the authors may not be used to endorse or promote 00017 // products derived from this software without specific prior written 00018 // permission. 00019 // 00020 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00021 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00022 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00023 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00024 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00025 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00026 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00027 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00028 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 // 00031 // This file is part of the PLearn library. For more information on the PLearn 00032 // library, go to the PLearn Web site at www.plearn.org 00033 00034 00035 /* ******************************************************* 00036 * $Id: IndexedVMatrix.cc 5557 2006-05-10 20:36:58Z lamblin $ 00037 ******************************************************* */ 00038 00039 #include "IndexedVMatrix.h" 00040 00041 namespace PLearn { 00042 using namespace std; 00043 00044 PLEARN_IMPLEMENT_OBJECT(IndexedVMatrix, "ONE LINE DESCR", 00045 "VMat class that sees its source as a collection of\n" 00046 "triplets (row, column, value). Thus it is a N x 3" 00047 " matrix,\n" 00048 "with N = the number of elements in source.\n"); 00049 00050 00051 IndexedVMatrix::IndexedVMatrix(bool call_build_) 00052 : inherited(call_build_), 00053 need_fix_mappings(false) 00054 { 00055 if( call_build_ ) 00056 build_(); 00057 } 00058 00059 IndexedVMatrix::IndexedVMatrix(VMat the_source, bool the_fully_check_mappings, 00060 bool call_build_) 00061 : inherited(the_source, call_build_), 00062 need_fix_mappings(false), 00063 fully_check_mappings(the_fully_check_mappings) 00064 { 00065 if( call_build_ ) 00066 build_(); 00067 } 00068 00069 00070 void IndexedVMatrix::declareOptions(OptionList& ol) 00071 { 00072 declareOption(ol, "m", &IndexedVMatrix::source, 00073 (OptionBase::learntoption | OptionBase::nosave), 00074 "DEPRECATED - use 'source' instead."); 00075 00076 declareOption(ol, "fully_check_mappings", 00077 &IndexedVMatrix::fully_check_mappings, 00078 OptionBase::buildoption, 00079 "If set to 1, then columns for which there is a" 00080 " string <-> real mapping\n" 00081 "will be examined, to ensure that no numerical data in a\n" 00082 "column conflicts with a mapping in another column.\n"); 00083 00084 inherited::declareOptions(ol); 00085 } 00086 00087 void IndexedVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00088 { 00089 inherited::makeDeepCopyFromShallowCopy(copies); 00090 00091 deepCopyField(fixed_mappings, copies); 00092 } 00093 00094 void IndexedVMatrix::build() 00095 { 00096 inherited::build(); 00097 build_(); 00098 } 00099 00101 // build_ // 00103 void IndexedVMatrix::build_() 00104 { 00105 width_ = 3; 00106 length_ = source->length() * source->width(); 00107 00108 ensureMappingsConsistency(); 00109 00110 if( fully_check_mappings ) 00111 fullyCheckMappings(); 00112 00113 if( need_fix_mappings && !fully_check_mappings ) 00114 PLWARNING( "In IndexedVMatrix::build_ - Mappings need to be fixed,\n" 00115 "but you did not set 'fully_check_mappings' to true,\n" 00116 "this might be dangerous.\n" ); 00117 00118 TVec<string> fieldnames(3); 00119 fieldnames[0] = "row"; 00120 fieldnames[1] = "column"; 00121 fieldnames[2] = "value"; 00122 declareFieldNames( fieldnames ); 00123 00124 setMetaInfoFromSource(); 00125 } 00126 00128 // getNewRow // 00130 void IndexedVMatrix::getNewRow(int i, const Vec& v) const 00131 { 00132 #ifdef BOUNDCHECK 00133 if(i<0 || i>=length()) 00134 PLERROR("In IndexedVMatrix::getNewRow OUT OF BOUNDS"); 00135 if(v.length() != width()) 00136 PLERROR("In IndexedVMatrix::getNewRow v.length() must be equal to 3"); 00137 #endif 00138 00139 int w = source->width(); 00140 int i_ = i / w; // the value of the first column at row i 00141 int j_ = i % w; // the value of the second column at row i 00142 real val = source->get(i_,j_); 00143 00144 if( need_fix_mappings && fixed_mappings[j_].size()>0 && !is_missing(val) ) 00145 { 00146 map<real, real>::iterator it = fixed_mappings[j_].find(val); 00147 if( it != fixed_mappings[j_].end() ) 00148 { 00149 // We need to modify this value. 00150 val = it->second; 00151 } 00152 } 00153 00154 v[0] = i_; 00155 v[1] = j_; 00156 v[2] = val; 00157 } 00158 00159 /* implemented in RowBufferedVMatrix 00161 // get // 00163 real IndexedVMatrix::get(int i, int j) const { 00164 int w = source->width(); 00165 int i_ = i / w; // the value of the first column at row i 00166 int j_ = i % w; // the value of the second column at row i 00167 switch (j) { 00168 case 0: 00169 return i_; 00170 case 1: 00171 return j_; 00172 case 2: 00173 return source->get(i_, j_); 00174 default: 00175 PLERROR("In IndexedVMatrix::get IndexedVMatrix has only 3 columns\n"); 00176 return 0; 00177 } 00178 } 00179 */ 00180 00182 // put // 00184 void IndexedVMatrix::put(int i, int j, real value) { 00185 if (j != 2) { 00186 PLERROR("In IndexedVMatrix::put You can only modify the third column\n"); 00187 } 00188 int w = source->width(); 00189 int i_ = i / w; // the value of the first column at row i 00190 int j_ = i % w; // the value of the second column at row i 00191 source->put(i_, j_, value); 00192 } 00193 00195 // ensureMappingsConsistency // 00197 void IndexedVMatrix::ensureMappingsConsistency() 00198 { 00199 // Make sure the string mappings are consistent. 00200 // For this, we start from the mapping of the first column, and add 00201 // missing mappings obtained from the other columns. If another 00202 // column has a different mapping for the same string, we remember 00203 // it in order to fix the output when a getxxxx() method is called. 00204 need_fix_mappings = false; 00205 setStringMapping(2, source->getStringToRealMapping(0)); 00206 map<string, real>* first_map = &map_sr[2]; 00207 map<string, real> other_map; 00208 map<string, real>::iterator it, find_map; 00209 00210 // Find the maximum mapping value for first column. 00211 real max = -REAL_MAX; 00212 for( it = first_map->begin() ; it != first_map->end() ; it++ ) 00213 if( it->second > max ) 00214 max = it->second; 00215 00216 for( int i = 1 ; i < source->width() ; i++ ) 00217 { 00218 other_map = source->getStringToRealMapping(i); 00219 for( it = other_map.begin() ; it != other_map.end() ; it++ ) 00220 { 00221 find_map = first_map->find( it->first ); 00222 if( find_map != first_map->end() ) 00223 { 00224 // The string mapped in column 'i' is also mapped in our first 00225 // mapping. 00226 if( !fast_exact_is_equal(find_map->second, it->second) ) 00227 { 00228 // But the same string is not mapped to the same value. 00229 // This needs to be fixed. 00230 need_fix_mappings = true; 00231 fixed_mappings.resize( source->width() ); 00232 fixed_mappings[i][it->second] = find_map->second; 00233 } 00234 } 00235 else 00236 { 00237 // The string mapped in VMat 'i' is not mapped in our 00238 // current mapping. We need to add this mapping. 00239 // But we must make sure there is no existing mapping to 00240 // the same real number. 00241 real new_map_val = it->second; 00242 if( getValString(2, it->second) != "" ) 00243 { 00244 // There is already a mapping to this real number. 00245 need_fix_mappings = true; 00246 fixed_mappings.resize( source->width() ); 00247 // We pick for the number the maximum of the current mapped 00248 // numbers, +1. 00249 max++; 00250 fixed_mappings[i][it->second] = max; 00251 new_map_val = max; 00252 } 00253 else 00254 { 00255 // There is no mapping to this real number, it is thus ok 00256 // to add it. 00257 if( new_map_val > max ) 00258 max = new_map_val; 00259 } 00260 addStringMapping(2, it->first, new_map_val); 00261 } 00262 } 00263 } 00264 } 00265 00267 // fullyCheckMappings // 00269 void IndexedVMatrix::fullyCheckMappings() 00270 { 00271 if( map_sr[2].size() == 0 ) 00272 return; 00273 00274 Vec row( source->width() ); 00275 for( int i = 0 ; i < source->length() ; i++ ) 00276 { 00277 source->getRow(i, row); 00278 for( int j = 0 ; j < source->width() ; j++ ) 00279 { 00280 if( !is_missing(row[j]) ) 00281 { 00282 // Note that if the value is missing, we should not 00283 // look for a mapping from this value, because it would 00284 // find it even if it does not exist (see the STL map 00285 // documentation to understand why this happens). 00286 if( source->getValString(j, row[j]) == "" ) 00287 { 00288 // It is a numerical value for the source's j-th column 00289 if( map_rs[2].find(row[j]) != map_rs[2].end() ) 00290 { 00291 // And, unfortunately, we have used this 00292 // numerical value in the column (2) string 00293 // mapping. It could be fixed, but this would be 00294 // pretty annoying, thus we just raise an error. 00295 PLERROR("In IndexedVMatrix::fullyCheckMappings - In" 00296 " column %d (%s) of source, the row %d\n" 00297 "contains a numerical value (%f) that is used" 00298 " in a string mapping (mapped to %s).\n", 00299 j, source->fieldName(j).c_str(), i, 00300 row[j], map_rs[2][ row[j] ].c_str() ); 00301 } 00302 } 00303 } 00304 } 00305 } 00306 } 00307 00308 00309 } // end of namespace PLearn 00310 00311 00312 /* 00313 Local Variables: 00314 mode:c++ 00315 c-basic-offset:4 00316 c-file-style:"stroustrup" 00317 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00318 indent-tabs-mode:nil 00319 fill-column:79 00320 End: 00321 */ 00322 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :