PLearn 0.1
MultiInstanceVMatrix.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // MultiInstanceVMatrix.cc
00004 //
00005 // Copyright (C) 2004 Norman Casagrande
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: MultiInstanceVMatrix.cc 8617 2008-03-03 17:45:54Z nouiz $
00037  ******************************************************* */
00038 
00039 // Authors: Norman Casagrande
00040 
00043 #include "MultiInstanceVMatrix.h"
00044 #include <map>
00045 #include <algorithm>
00046 #include <iterator>
00047 #include <plearn/var/SumOverBagsVariable.h>
00048 #include <plearn/base/stringutils.h>
00049 #include <plearn/io/fileutils.h>
00050 #include <plearn/io/openFile.h>
00051 
00052 namespace PLearn {
00053 using namespace std;
00054 
00055 MultiInstanceVMatrix::MultiInstanceVMatrix()
00056     :inherited(), data_(Mat()), source_targetsize(1),
00057      header_lines_to_skip(0)
00058 {
00059     // ### You may or may not want to call build_() to finish building the object
00060     //build_();
00061 }
00062 
00063 //MultiInstanceVMatrix::MultiInstanceVMatrix(const string& filename)
00064 //  :inherited(), filename_(abspath(filename))
00065 //{
00066 //  //build();
00067 //}
00068 
00069 
00070 PLEARN_IMPLEMENT_OBJECT(MultiInstanceVMatrix, "Virtual Matrix for a multi instance dataset",
00071                         "In a multi-instance dataset examples come in 'bags' with only one target label\n"
00072                         "for each bag. This class is built upon a source text file that describes such\n"
00073                         "a dataset (see the help on the 'filename' option for format details).\n"
00074                         "The resulting VMatrix shows the following structure in its rows, with\n"
00075                         "all the rows of a bag being consecutive. Each row represents an instance and has:\n"
00076                         "  - the input features for the instance\n"
00077                         "  - the bag's source_targetsize target values (repeated over bag instances)\n"
00078                         "  - a bag signal integer that identifies the beginning and end of the bag:\n"
00079                         "     1 means the first instance of the bag\n"
00080                         "     2 means the last instance of the bag\n"
00081                         "     3 is for a bag with a single row (= 1+2)\n"
00082                         "     0 is for intermediate instances.\n"
00083                         "The targetsize of the VMatrix is automatically set to source_targetsize+1\n"
00084                         "since the bag_signal is included (appended) in the target vector\n"
00085     );
00086 
00087 void MultiInstanceVMatrix::getNewRow(int i, const Vec& v) const
00088 {
00089     v << data_(i);
00090 }
00091 
00092 void MultiInstanceVMatrix::declareOptions(OptionList& ol)
00093 {
00094     declareOption(ol, "source_targetsize", &MultiInstanceVMatrix::source_targetsize, OptionBase::buildoption,
00095                   "The source targetsize");
00096 
00097     declareOption(ol, "filename", &MultiInstanceVMatrix::filename_, OptionBase::buildoption,
00098                   "This is the name of the ascii 'mimat' format filename. It is a supervised learning dataset\n"
00099                   "in which each input object can come in several instances (e.g. conformations) and the target is given to the\n"
00100                   "whole bag of these instances, not to individual instances. The expected format is the following:\n"
00101                   "Each row contains:\n"
00102                   "  - the object name (a string without white space)\n"
00103                   "  - the instance number (a non-negative integer)\n"
00104                   "  - the inputsize features for that instance (numeric, white-separated)\n"
00105                   "  - the source_targetsize target values for the bag (repeated on each row).\n"
00106                   "If the inputsize option is not specified it is inferred from the text file.\n"
00107         );
00108 
00109     declareOption(ol, "header_lines_to_skip", &MultiInstanceVMatrix::header_lines_to_skip, OptionBase::buildoption,
00110                   "The number of lines to skip at the beginning of the file (they may be garbage, or \n"
00111                   "a header for a TextFilesVMatrix for instance).");
00112 
00113     // Now call the parent class' declareOptions
00114     inherited::declareOptions(ol);
00115 }
00116 
00117 void MultiInstanceVMatrix::build_()
00118 {
00119 
00120     updateMtime(filename_);
00121     //this->setMetaDataDir(filename_ + ".metadata");
00122 
00123     // To be used in the end.. it is about 5 secs slower in debug
00124     //int nRows = countNonBlankLinesOfFile(filename_);
00125     
00126     PStream inFile = openFile(filename_, PStream::raw_ascii, "r");
00127 //    PStream inFile = openFile(filename_, PStream::raw_ascii, "r");
00128 
00129     // inFile.seekg(0); TODO See if it still works without this.
00130     skipBlanksAndComments(inFile);
00131 
00132     string lastName = "";
00133     string newName,configNum;
00134     string aLine;
00135     string inp_element;
00136     int bagType;
00137     int nComp = 0;
00138         
00139     int i;
00140 
00141     real* mat_i = NULL;
00142 
00143     // one more column for the bag signal
00144     targetsize_ = source_targetsize + 1;
00145 
00146     // Check the number of columns
00147     for (i = 0; i < header_lines_to_skip; i++) {
00148         inFile.getline(aLine, '\n');
00149     }
00150     inFile.getline(aLine, '\n');
00151     vector<string> entries = split(aLine);
00152     int nFields = (int)entries.size();
00153     if (inputsize_>=0)
00154     {
00155         if ( (nFields-2) != inputsize_ + source_targetsize) // 2 for the object name and the instance number
00156         {
00157             PLERROR("Either inputsize or source_targetsize are inconsistent with the specified file!\n"
00158                     " Got %d+%d (inputsize+source_targetsize) = %d, and found %d! If unsure about inputsize, don't specify it or set to -1.",
00159                     inputsize_, source_targetsize, inputsize_+source_targetsize, nFields - 2);
00160         }
00161     } else inputsize_ = nFields-2-source_targetsize;
00162 
00163     int lastColumn = inputsize_ + source_targetsize;
00164 
00165     inFile = openFile(filename_, PStream::raw_ascii, "r");
00166     // inFile.seekg(0); // TODO See if it still works without this.
00167     skipBlanksAndComments(inFile);
00168     for (i = 0; i < header_lines_to_skip; i++) {
00169         inFile.getline(aLine, '\n');
00170     }
00171     skipBlanksAndComments(inFile);
00172 
00173     int nRows = inFile.count('\n');
00174     /* TODO Make sure it works like the old code:
00175        int nRows = count(istreambuf_iterator<char>(inFile),
00176        istreambuf_iterator<char>(), '\n');
00177     */
00178 
00179     inFile = openFile(filename_, PStream::raw_ascii, "r");
00180     // inFile.seekg(0); // TODO See if it still works without this.
00181     skipBlanksAndComments(inFile);
00182     for (i = 0; i < header_lines_to_skip; i++) {
00183         inFile.getline(aLine, '\n');
00184     }
00185     skipBlanksAndComments(inFile);
00186 
00187     data_.resize(nRows, inputsize_ + targetsize_);
00188 
00189     width_ = inputsize_ + targetsize_;
00190     length_ = nRows;
00191 
00192     for (int lineNum = 0; !inFile.eof() && lineNum < nRows; ++lineNum)
00193     {
00194         // first column: name of the compound
00195         inFile >> newName;
00196         if (newName != lastName)
00197         {
00198             lastName = newName;
00199             names_.push_back( make_pair(newName, lineNum) );
00200             bagType = SumOverBagsVariable::TARGET_COLUMN_FIRST;
00201             if (mat_i != NULL)
00202             {
00203                 if (nComp > 1)
00204                     mat_i[lastColumn] = SumOverBagsVariable::TARGET_COLUMN_LAST;
00205                 else
00206                     mat_i[lastColumn] = SumOverBagsVariable::TARGET_COLUMN_SINGLE;
00207             }
00208             nComp = 0;
00209         }
00210         else
00211         {
00212             bagType = SumOverBagsVariable::TARGET_COLUMN_INTERMEDIATE;
00213         }
00214         nComp++;
00215 
00216         // get next column: the number of the compound
00217         inFile >> configNum;
00218 
00219         configs_.push_back(configNum);
00220 
00221         // get the actual data columns + the target
00222         mat_i = data_[lineNum];
00223         for(int k = 0; k < inputsize_ + source_targetsize; k++)
00224         {
00225             inFile >> inp_element;
00226             mat_i[k] = pl_strtod(inp_element.c_str(), 0);
00227         }
00228 
00229         // close the last bag if necessary
00230         if (lineNum+1==nRows)
00231         {
00232             if (nComp > 1)
00233                 mat_i[lastColumn] = SumOverBagsVariable::TARGET_COLUMN_LAST;
00234             else
00235                 mat_i[lastColumn] = SumOverBagsVariable::TARGET_COLUMN_SINGLE;
00236         }
00237         else
00238             mat_i[lastColumn] = bagType;
00239     }
00240 
00241 
00242     //ofstream test("g:/test.txt");
00243     //test << data_;
00244     //test.close();
00245 
00246     this->updateMtime(filename_);
00247 }
00248 
00249 // ### Nothing to add here, simply calls build_
00250 void MultiInstanceVMatrix::build()
00251 {
00252     inherited::build();
00253     build_();
00254 }
00255 
00256 void MultiInstanceVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00257 {
00258     inherited::makeDeepCopyFromShallowCopy(copies);
00259 
00260     // ### Call deepCopyField on all "pointer-like" fields
00261     // ### that you wish to be deepCopied rather than
00262     // ### shallow-copied.
00263     // ### ex:
00264 
00265     deepCopyField(data_, copies);
00266 
00267     // TODO: Copy also the other features
00268 
00269     // ### Remove this line when you have fully implemented this method.
00270     PLERROR("MultiInstanceVMatrix::makeDeepCopyFromShallowCopy not fully implemented yet!");
00271 }
00272 
00273 } // end of namespace PLearn
00274 
00275 
00276 /*
00277   Local Variables:
00278   mode:c++
00279   c-basic-offset:4
00280   c-file-style:"stroustrup"
00281   c-file-offsets:((innamespace . 0)(inline-open . 0))
00282   indent-tabs-mode:nil
00283   fill-column:79
00284   End:
00285 */
00286 // 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