PLearn 0.1
ClassSeparationSplitter.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // ClassSeparationSplitter.cc
00004 //
00005 // Copyright (C) 2006 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 /* *******************************************************
00036    * $Id: .pyskeleton_header 544 2003-09-01 00:05:31Z plearner $
00037    ******************************************************* */
00038 
00039 // Authors: Hugo Larochelle
00040 
00043 #include "SelectRowsVMatrix.h"
00044 #include "ClassSeparationSplitter.h"
00045 
00046 namespace PLearn {
00047 using namespace std;
00048 
00049 PLEARN_IMPLEMENT_OBJECT(
00050     ClassSeparationSplitter,
00051     "Splitter that separates examples of some classes (test) from the examples of other classes (train)",
00052     "This splitter is intended to measure inductive transfer performance from some tasks to another task"
00053     );
00054 
00055 ClassSeparationSplitter::ClassSeparationSplitter()
00056     :Splitter(), numsplits(-1), nclasses(-1), nclasses_test_set(1), select_classes_randomly(1), append_train(0), seed(-1)
00057 {
00058     random_gen = new PRandom();
00059 }
00060 
00061 void ClassSeparationSplitter::declareOptions(OptionList& ol)
00062 {
00063     declareOption(ol, "numsplits", &ClassSeparationSplitter::numsplits, OptionBase::buildoption,
00064                   "Number of splits. If <= 0, then it is set to nclasses.");
00065     declareOption(ol, "nclasses", &ClassSeparationSplitter::nclasses, OptionBase::buildoption,
00066                   "Number of classes.");
00067     declareOption(ol, "nclasses_test_set", &ClassSeparationSplitter::nclasses_test_set, OptionBase::buildoption,
00068                   "Number of classes in the test sets.");
00069     declareOption(ol, "classes", &ClassSeparationSplitter::classes, OptionBase::buildoption,
00070                   "Classes to isolate from the others, for each split. When this field is specified,\n"
00071                   "then nclasses, nclasses_test_set and nsplit are ignored.");
00072     declareOption(ol, "select_classes_randomly", &ClassSeparationSplitter::select_classes_randomly, OptionBase::buildoption,
00073                   "Indication that the classes should be chosen at random.\n"
00074                   "Otherwise, the classes are selected by order of their index.");
00075     declareOption(ol, "append_train", &ClassSeparationSplitter::append_train, OptionBase::buildoption,
00076                   "Indication that the training set should be appended to the split sets lists.");
00077 
00078     declareOption(ol, "seed", &ClassSeparationSplitter::seed, OptionBase::buildoption,
00079                   "Seed of random generator");
00080 
00081     // Now call the parent class' declareOptions
00082     inherited::declareOptions(ol);
00083 }
00084 
00085 void ClassSeparationSplitter::build_()
00086 {
00087     if (seed != 0)
00088         random_gen->manual_seed(seed);
00089 
00090     if(classes.length() == 0)
00091     {
00092         if(nclasses <= 0) PLERROR("In ClassSeparationSplitter::build_(): nclasses should be > 0");
00093         if(nclasses_test_set <= 0) PLERROR("In ClassSeparationSplitter::build_(): nclasses_test_set should be > 0");
00094         if(nclasses_test_set >= nclasses) PLERROR("In ClassSeparationSplitter::build_(): nclasses_test_set should be < nclasses");
00095         if(numsplits <= 0) numsplits = nclasses;
00096 
00097         classes.resize(numsplits);
00098         int it = 0;
00099         for(int i=0; i<numsplits; i++)
00100         {
00101             if(select_classes_randomly)
00102             {
00103                 classes[i].resize(nclasses);
00104                 for(int j=0; j<nclasses; j++)
00105                     classes[i][j] = j;
00106                 random_gen->shuffleElements(classes[i]);
00107                 classes.resize(nclasses_test_set);
00108             }
00109             else
00110             {
00111                 classes[i].resize(nclasses_test_set);
00112                 for(int j=0; j<nclasses_test_set; j++)
00113                 {
00114                     classes[i][j] = it%nclasses;
00115                     it++;
00116                 }
00117             }
00118         }
00119     }
00120 }
00121 
00122 // ### Nothing to add here, simply calls build_
00123 void ClassSeparationSplitter::build()
00124 {
00125     inherited::build();
00126     build_();
00127 }
00128 
00129 void ClassSeparationSplitter::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00130 {
00131     inherited::makeDeepCopyFromShallowCopy(copies);
00132 
00133     deepCopyField(classes, copies);
00134     deepCopyField(random_gen, copies);
00135 
00136     //PLERROR("ClassSeparationSplitter::makeDeepCopyFromShallowCopy not fully (correctly) implemented yet!");
00137 }
00138 
00139 int ClassSeparationSplitter::nsplits() const
00140 {
00141     return classes.length();
00142 }
00143 
00144 int ClassSeparationSplitter::nSetsPerSplit() const
00145 {
00146     return append_train ? 3 : 2;
00147 }
00148 
00149 TVec<VMat> ClassSeparationSplitter::getSplit(int k)
00150 {
00151 
00152     if (k >= nsplits())
00153         PLERROR("ClassSeparationSplitter::getSplit() - k (%d) cannot be greater than "
00154                 " the number of splits (%d)", k, nsplits());
00155 
00156     TVec<int> classes_k = classes[k];
00157     Vec row(dataset->width());
00158     TVec<int> indices(0);
00159     for(int i=0; i<dataset->length(); i++)
00160     {
00161         dataset->getRow(i,row);
00162         if(classes_k.find((int)row[dataset->inputsize()]) >= 0)
00163         {
00164             indices.push_back(i);
00165         }
00166     }
00167 
00168     TVec<VMat> split(2);
00169     split[0] = new SelectRowsVMatrix(dataset,indices, true);
00170     split[1] = new SelectRowsVMatrix(dataset,indices);
00171     if(append_train) split.append(split[0]);
00172     return split;
00173 }
00174 
00175 
00176 } // end of namespace PLearn
00177 
00178 
00179 /*
00180   Local Variables:
00181   mode:c++
00182   c-basic-offset:4
00183   c-file-style:"stroustrup"
00184   c-file-offsets:((innamespace . 0)(inline-open . 0))
00185   indent-tabs-mode:nil
00186   fill-column:79
00187   End:
00188 */
00189 // 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