PLearn 0.1
|
00001 00002 00003 // -*- C++ -*- 00004 00005 // TrainTestSplitter.cc 00006 // 00007 // Copyright (C) 1998 Pascal Vincent 00008 // Copyright (C) 1999,2000 Pascal Vincent, Yoshua Bengio and University of Montreal 00009 // Copyright (C) 2002 Frederic Morin 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. The name of the authors may not be used to endorse or promote 00022 // products derived from this software without specific prior written 00023 // permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00026 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00027 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00028 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00029 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00030 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00031 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00032 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00033 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00034 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00035 // 00036 // This file is part of the PLearn library. For more information on the PLearn 00037 // library, go to the PLearn Web site at www.plearn.org 00038 00039 /* ******************************************************* 00040 * $Id: TrainTestSplitter.cc 6242 2006-09-22 21:07:35Z chapados $ 00041 ******************************************************* */ 00042 00045 #define PL_LOG_MODULE_NAME "TrainTestSplitter" 00046 00047 #include "TrainTestSplitter.h" 00048 #include <plearn/io/pl_log.h> 00049 #include <plearn/math/PRandom.h> 00050 #include <plearn/vmat/SelectRowsVMatrix.h> 00051 00052 namespace PLearn { 00053 using namespace std; 00054 00055 TrainTestSplitter::TrainTestSplitter(real the_test_fraction) 00056 : append_train(false), 00057 test_fraction(the_test_fraction), 00058 calc_with_pct(true), 00059 test_fraction_abs(0), 00060 shuffle_seed(-1) 00061 { } 00062 00063 TrainTestSplitter::TrainTestSplitter(int the_test_fraction_abs) 00064 : append_train(false), 00065 test_fraction(0.0), 00066 calc_with_pct(false), 00067 test_fraction_abs(the_test_fraction_abs), 00068 shuffle_seed(-1) 00069 { } 00070 00071 PLEARN_IMPLEMENT_OBJECT( 00072 TrainTestSplitter, 00073 "Simple splitter to split between train and test sets.", 00074 "TrainTestSplitter implements a single split of the dataset into a\n" 00075 "training set and a test set (the test part being the last few samples\n" 00076 "of the dataset)\n" 00077 ); 00078 00079 void TrainTestSplitter::declareOptions(OptionList& ol) 00080 { 00081 declareOption( 00082 ol, "append_train", &TrainTestSplitter::append_train, OptionBase::buildoption, 00083 "if set to 1, the trainset will be appended after the test set " 00084 "(thus each split will contain three sets)"); 00085 00086 declareOption( 00087 ol, "calc_with_pct", &TrainTestSplitter::calc_with_pct, OptionBase::buildoption, 00088 "Boolean value : if it's true it will compute the examples in the test " 00089 "set with the test_fraction value"); 00090 00091 declareOption( 00092 ol, "test_fraction", &TrainTestSplitter::test_fraction, OptionBase::buildoption, 00093 "the fraction of the dataset reserved to the test set"); 00094 00095 declareOption( 00096 ol, "test_fraction_abs", &TrainTestSplitter::test_fraction_abs, OptionBase::buildoption, 00097 "the number of example of the dataset reserved to the test set"); 00098 00099 declareOption( 00100 ol, "shuffle_seed", &TrainTestSplitter::shuffle_seed, OptionBase::buildoption, 00101 "if seed is >0, the vmat should be shuffled before being split (using this seed)\n" 00102 "NOTE: the records in each subset remain in the original order"); 00103 00104 inherited::declareOptions(ol); 00105 } 00106 00107 void TrainTestSplitter::build_() 00108 { 00109 if(calc_with_pct && (test_fraction < 0.0 || test_fraction > 1.0)) 00110 PLERROR("TrainTestSplitter: test_fraction must be between 0 and 1; " 00111 "%f is not a valid value.", test_fraction); 00112 00113 } 00114 00115 // ### Nothing to add here, simply calls build_ 00116 void TrainTestSplitter::build() 00117 { 00118 inherited::build(); 00119 build_(); 00120 } 00121 00122 int TrainTestSplitter::nsplits() const 00123 { 00124 return 1; // only one split 00125 } 00126 00127 int TrainTestSplitter::nSetsPerSplit() const 00128 { 00129 if (append_train) 00130 return 3; 00131 else 00132 return 2; 00133 } 00134 00135 TVec<VMat> TrainTestSplitter::getSplit(int k) 00136 { 00137 if (k) 00138 PLERROR("TrainTestSplitter::getSplit() - k cannot be greater than 0"); 00139 00140 TVec<VMat> split_(2); 00141 00142 int l = dataset->length(); 00143 int test_length = calc_with_pct ? int(test_fraction*l) : test_fraction_abs; 00144 int train_length = l - test_length; 00145 00146 // Generate the shuffled elements if required, but don't do it more than 00147 // once (would be wasteful for a splitter used inside an hyperoptimizer, 00148 // for instance) 00149 if(0 < shuffle_seed && (train_indices.size() == 0 || test_indices.size() == 0)) 00150 getRandomSubsets(train_length, test_length); 00151 00152 if(train_length == l) 00153 split_[0] = dataset;//to get the right metadatadir when its the same matrix 00154 else 00155 split_[0] = ( 0<shuffle_seed? 00156 new SelectRowsVMatrix(dataset, train_indices) 00157 : dataset.subMatRows(0, train_length) ); 00158 00159 if(test_length == l) 00160 split_[1] = dataset;//to get the right metadatadir when its the same matrix 00161 else 00162 split_[1] = ( 0<shuffle_seed? 00163 new SelectRowsVMatrix(dataset, test_indices) 00164 : dataset.subMatRows(train_length, test_length) ); 00165 00166 if (append_train) { 00167 split_.resize(3); 00168 split_[2] = split_[0]; 00169 } 00170 return split_; 00171 } 00172 00173 00175 // getRandomSubsets // 00177 void TrainTestSplitter::getRandomSubsets(int train_length, int test_length) 00178 { 00179 int n= train_length+test_length; 00180 TVec<int> v(n); 00181 for(int i= 0; i < n; ++i) 00182 v[i]= i; 00183 00184 PRandom(shuffle_seed).shuffleElements(v); 00185 00186 train_indices= v.subVec(0, train_length); 00187 test_indices= v.subVec(train_length, test_length); 00188 00189 sortElements(train_indices); 00190 sortElements(test_indices); 00191 00192 MODULE_LOG 00193 << "Shuffling train-test elements yields:\n" 00194 << "Train indices: " << train_indices << '\n' 00195 << "Test indices: " << test_indices 00196 << endl; 00197 } 00198 00200 // makeDeepCopyFromShallowCopy // 00202 void TrainTestSplitter::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00203 { 00204 inherited::makeDeepCopyFromShallowCopy(copies); 00205 deepCopyField(train_indices, copies); 00206 deepCopyField(test_indices, copies); 00207 } 00208 00209 } // end of namespace PLearn 00210 00211 00212 /* 00213 Local Variables: 00214 mode:c++ 00215 c-basic-offset:4 00216 c-file-style:"stroustrup" 00217 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00218 indent-tabs-mode:nil 00219 fill-column:79 00220 End: 00221 */ 00222 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :