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