PLearn 0.1
|
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 :