PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // LIBSVMSparseVMatrix.cc 00004 // 00005 // Copyright (C) 2008 Hugo Larochelle 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 // Authors: Hugo Larochelle 00036 00040 #include "LIBSVMSparseVMatrix.h" 00041 #include "plearn/io/openFile.h" 00042 #include "plearn/io/fileutils.h" 00043 00044 namespace PLearn { 00045 using namespace std; 00046 00047 00048 PLEARN_IMPLEMENT_OBJECT( 00049 LIBSVMSparseVMatrix, 00050 "VMatrix containing data from a libsvm format file", 00051 "The libsvm format file is particularly useful for sparse inputs.\n" 00052 "The sparsity information (i.e. indices of non-zero inputs) is provided\n" 00053 "via the extra fields, and the input given by getExample() only contains\n" 00054 "the values for non-zero inputs. Since the sparsity can change from one example to\n" 00055 "another, getExtra() (and getExample()) will adapt the size of the extra (input)\n" 00056 "fields vector accordingly. However, since it only works for fixed length inputs,\n" 00057 "getRow() returns an error when called in sparse mode.\n" 00058 "This class can also be used in \"coarse\" mode (i.e. use_coarse_representation=true),\n" 00059 "where getRow() and getExample() will then provide inputs in a fixed vector form, with\n" 00060 "non-zero fields taking their given values and other fields set explicitely to 0.\n" 00061 "However, in coarse mode, no extra information is given (i.e. extrasize() is 0), since\n" 00062 "it is implicitly incorporated in the input vector." 00063 ); 00064 00065 LIBSVMSparseVMatrix::LIBSVMSparseVMatrix(): use_coarse_representation(false) 00066 { 00067 } 00068 00069 LIBSVMSparseVMatrix::LIBSVMSparseVMatrix(PPath filename, bool use_coarse_representation): 00070 libsvm_file(filename), 00071 use_coarse_representation(use_coarse_representation) 00072 { 00073 build(); 00074 } 00075 00076 void LIBSVMSparseVMatrix::getNewRow(int i, const Vec& v) const 00077 { 00078 if( !use_coarse_representation ) 00079 PLERROR("In LIBSVMSparseVMatrix::getNewRow(): not compatible with sparse representations. Use use_coarse_representation=true."); 00080 real* in = libsvm_input_data[i].data(); 00081 real* ex = libsvm_extra_data[i].data(); 00082 v.clear(); 00083 for( int j=0; j<libsvm_input_data[i].length(); j++ ) 00084 v[(int)round(ex[j])] = in[j]; 00085 00086 v[inputsize_] = libsvm_target_data[i]; 00087 } 00088 00089 void LIBSVMSparseVMatrix::declareOptions(OptionList& ol) 00090 { 00091 declareOption(ol, "class_strings", &LIBSVMSparseVMatrix::class_strings, 00092 OptionBase::buildoption, 00093 "Strings associated to the different classes. If not present we suppose classes are int.\n"); 00094 00095 declareOption(ol, "libsvm_file", &LIBSVMSparseVMatrix::libsvm_file, 00096 OptionBase::buildoption, 00097 "File name of libsvm data.\n"); 00098 00099 declareOption(ol, "use_coarse_representation", &LIBSVMSparseVMatrix::use_coarse_representation, 00100 OptionBase::buildoption, 00101 "Indication that a coarse (i.e. fixed length, filled with 0's) representation\n" 00102 "of the data in the .libsvm file should be used.\n"); 00103 00104 //declareOption(ol, "libsvm_input_data", 00105 // &LIBSVMSparseVMatrix::libsvm_input_data, 00106 // OptionBase::learntoption, 00107 // "Input data.\n"); 00108 // 00109 //declareOption(ol, "libsvm_extra_data", 00110 // &LIBSVMSparseVMatrix::libsvm_extra_data, 00111 // OptionBase::learntoption, 00112 // "Extra data.\n"); 00113 // 00114 //declareOption(ol, "libsvm_target_data", 00115 // &LIBSVMSparseVMatrix::libsvm_target_data, 00116 // OptionBase::learntoption, 00117 // "Target data.\n"); 00118 00119 // Now call the parent class' declareOptions 00120 inherited::declareOptions(ol); 00121 } 00122 00123 void LIBSVMSparseVMatrix::build_() 00124 { 00125 00126 if(libsvm_file.isEmpty()) 00127 return; 00128 00129 // Read data 00130 PStream libsvm_stream = openFile(libsvm_file, PStream::raw_ascii); 00131 updateMtime(libsvm_file); 00132 libsvm_stream.skipBlanks(); 00133 int input_index = 0; 00134 int largest_input_index = -1; 00135 int target_index = 0; 00136 int n_inputs = 0; 00137 string line; 00138 vector<string> tokens; 00139 length_ = 0; 00140 width_ = -1; 00141 libsvm_input_data.resize(0); 00142 libsvm_extra_data.resize(0); 00143 libsvm_target_data.resize(0); 00144 while(!libsvm_stream.eof()) 00145 { 00146 libsvm_stream.getline(line); 00147 line = removeblanks(line); 00148 libsvm_stream.skipBlanks(); 00149 tokens = split(line,": "); 00150 00151 // Get target 00152 target_index = class_strings.find(tokens[0]); 00153 if( target_index < 0){ 00154 double d; 00155 if(pl_isnumber(tokens[0],&d) && ((double)((int)d))==d) 00156 target_index=(int)d; 00157 else 00158 PLERROR("In LIBSVMSparseVMatrix::build_(): target %s unknown and not an int", 00159 tokens[0].c_str()); 00160 } 00161 if( (tokens.size()-1)%2 != 0 ) 00162 PLERROR("In LIBSVMSparseVMatrix::build_(): line %s has incompatible " 00163 "format", line.c_str()); 00164 libsvm_target_data.push_back(target_index); 00165 00166 n_inputs = (tokens.size()-1)/2; 00167 Vec input_vec(n_inputs); 00168 Vec extra_vec(n_inputs); 00169 // Get inputs 00170 for( int i=0; i<n_inputs; i++) 00171 { 00172 input_index = toint(tokens[2*i+1])-1; 00173 extra_vec[i] = input_index; 00174 if( input_index > largest_input_index ) 00175 largest_input_index = input_index; 00176 input_vec[i] = toreal(tokens[2*i+2]); 00177 } 00178 libsvm_input_data.push_back(input_vec); 00179 libsvm_extra_data.push_back(extra_vec); 00180 length_++; 00181 } 00182 00183 // Set sizes 00184 if( inputsize_ < 0 ) inputsize_ = largest_input_index+1; 00185 if( targetsize_ < 0 ) targetsize_ = 1; 00186 if( weightsize_ < 0 ) weightsize_ = 0; 00187 if( use_coarse_representation ) 00188 extrasize_ = 0; 00189 else 00190 extrasize_ = largest_input_index+1; 00191 if( width_ < 0 ) width_ = inputsize_ + targetsize_ + weightsize_; 00192 } 00193 00194 00195 // ### Nothing to add here, simply calls build_ 00196 void LIBSVMSparseVMatrix::build() 00197 { 00198 inherited::build(); 00199 build_(); 00200 } 00201 00202 void LIBSVMSparseVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00203 { 00204 inherited::makeDeepCopyFromShallowCopy(copies); 00205 00206 deepCopyField(class_strings, copies); 00207 deepCopyField(libsvm_file, copies); 00208 deepCopyField(libsvm_input_data, copies); 00209 deepCopyField(libsvm_extra_data, copies); 00210 deepCopyField(libsvm_target_data, copies); 00211 } 00212 00213 void LIBSVMSparseVMatrix::getExample(int i, Vec& input, Vec& target, real& weight) 00214 { 00215 if( use_coarse_representation ) 00216 inherited::getExample(i,input,target,weight); 00217 else 00218 { 00219 if( i>= length_ || i < 0 ) 00220 PLERROR("In LIBSVMSparseVMatrix::getExample(): row index should " 00221 "be between 0 and length_-1"); 00222 input.resize(libsvm_input_data[i].length()); 00223 input << libsvm_input_data[i]; 00224 target.resize(targetsize_); 00225 target[0] = libsvm_target_data[i]; 00226 weight = 1; 00227 } 00228 } 00229 00230 void LIBSVMSparseVMatrix::getExamples(int i_start, int length, Mat& inputs, Mat& targets, 00231 Vec& weights, Mat* extras, bool allow_circular) 00232 { 00233 PLERROR("In LIBSVMSparseVMatrix::getExamples(): not compatible with " 00234 "sparse inputs"); 00235 } 00236 00237 void LIBSVMSparseVMatrix::getExtra(int i, Vec& extra) 00238 { 00239 if( use_coarse_representation ) 00240 extra.resize(0); 00241 else 00242 { 00243 if( i>= length_ || i < 0 ) 00244 PLERROR("In LIBSVMSparseVMatrix::getExample(): row index should " 00245 "be between 0 and length_-1"); 00246 extra.resize(libsvm_extra_data[i].length()); 00247 extra << libsvm_extra_data[i]; 00248 } 00249 } 00250 00251 VMatrixExtensionRegistrar* LIBSVMSparseVMatrix::extension_registrar = 00252 new VMatrixExtensionRegistrar( 00253 "libsvm", 00254 &LIBSVMSparseVMatrix::instantiateFromPPath, 00255 "libsvm format(good for sparce input)."); 00256 00257 } // end of namespace PLearn 00258 00259 00260 /* 00261 Local Variables: 00262 mode:c++ 00263 c-basic-offset:4 00264 c-file-style:"stroustrup" 00265 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00266 indent-tabs-mode:nil 00267 fill-column:79 00268 End: 00269 */ 00270 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :