PLearn 0.1
LIBSVMSparseVMatrix.cc
Go to the documentation of this file.
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines