PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // InfiniteMNISTVMatrix.cc 00004 // 00005 // Copyright (C) 2008 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 // Authors: Hugo Larochelle 00036 00040 #include "InfiniteMNISTVMatrix.h" 00041 00042 namespace PLearn { 00043 using namespace std; 00044 00045 00046 // Initialize static variables 00047 mnistproblem_t* InfiniteMNISTVMatrix::dataset = 0; 00048 int InfiniteMNISTVMatrix::n_pointers_to_dataset = 0; 00049 00050 PLEARN_IMPLEMENT_OBJECT( 00051 InfiniteMNISTVMatrix, 00052 "VMatrix containing an \"infinite\" stream of MNIST samples.", 00053 "VMatrix that uses the code from \"Training Invariant Support Vector Machines\n" 00054 "using Selective Sampling\" by Loosli, Canu and Bottou (JMLR 2007), to generate\n" 00055 "\"infinite\" stream (i.e. INT_MAX sized set) of samples from the MNIST dataset. The samples\n" 00056 "are obtained by applying some class-invariante transformations on the original MNIST\n" 00057 "dataset.\n" 00058 ); 00059 00060 InfiniteMNISTVMatrix::InfiniteMNISTVMatrix(): 00061 include_test_examples(false), 00062 include_validation_examples(false), 00063 random_switch_to_original_training_set(false), 00064 proportion_of_switches(0.0), 00065 seed(1834), 00066 input_divisor(1.), 00067 test_images(TEST_IMAGES_PATH), 00068 test_labels(TEST_LABELS_PATH), 00069 train_images(TRAIN_IMAGES_PATH), 00070 train_labels(TRAIN_LABELS_PATH), 00071 fields(FIELDS_PATH), 00072 tangent_vectors(TANGVEC_PATH) 00073 /* ### Initialize all fields to their default value */ 00074 { 00075 InfiniteMNISTVMatrix::n_pointers_to_dataset++; 00076 random_gen = new PRandom(); 00077 image = (unsigned char*)malloc(EXSIZE); 00078 } 00079 00080 InfiniteMNISTVMatrix::~InfiniteMNISTVMatrix() 00081 { 00082 InfiniteMNISTVMatrix::n_pointers_to_dataset--; 00083 if( InfiniteMNISTVMatrix::dataset && InfiniteMNISTVMatrix::n_pointers_to_dataset == 0 ) 00084 { 00085 destroy_mnistproblem(dataset); 00086 InfiniteMNISTVMatrix::dataset = 0; 00087 } 00088 free( image ); 00089 } 00090 00091 void InfiniteMNISTVMatrix::getNewRow(int i, const Vec& v) const 00092 { 00093 int i_dataset; 00094 if( include_test_examples ) 00095 if( include_validation_examples ) 00096 i_dataset = i; 00097 else 00098 if( i < 10000) 00099 i_dataset = i; 00100 else 00101 i_dataset = i + ((i-10000)/50000)*10000; 00102 else 00103 if( include_validation_examples ) 00104 i_dataset = i+10000; 00105 else 00106 i_dataset = i + (i/50000)*10000 + 10000; 00107 00108 if( random_switch_to_original_training_set && 00109 random_gen->uniform_sample() < proportion_of_switches ) 00110 i_dataset = (i_dataset % 50000)+10000; 00111 00112 image = compute_transformed_vector_in_place(InfiniteMNISTVMatrix::dataset, i_dataset, image); 00113 00114 unsigned char* xj=image; 00115 real* vj=v.data(); 00116 for( int j=0; j<inputsize_; j++, xj++, vj++ ) 00117 *vj = *xj/input_divisor; 00118 00119 v.last() = InfiniteMNISTVMatrix::dataset->y[ (i_dataset<10000) ? i_dataset : 10000 + ((i_dataset - 10000) % 60000) ]; 00120 } 00121 00122 void InfiniteMNISTVMatrix::declareOptions(OptionList& ol) 00123 { 00124 declareOption(ol, "include_test_examples", &InfiniteMNISTVMatrix::include_test_examples, 00125 OptionBase::buildoption, 00126 "Indication that the test examples from the MNIST dataset should be included.\n" 00127 "This option is false by default. If true, these examples will be the first" 00128 "10000\n" 00129 "of this VMatrix.\n"); 00130 00131 declareOption(ol, "include_validation_examples", &InfiniteMNISTVMatrix::include_validation_examples, 00132 OptionBase::buildoption, 00133 "Indication that the validation set examples (the last 10000 examples from the\n" 00134 "training set) should be included in this VMatrix.\n"); 00135 00136 declareOption(ol, "random_switch_to_original_training_set", 00137 &InfiniteMNISTVMatrix::random_switch_to_original_training_set, 00138 OptionBase::buildoption, 00139 "Indication that the VMatrix should randomly (from time to time) provide\n" 00140 "an example from the original training set instead of an example\n" 00141 "from the global dataset.\n"); 00142 00143 declareOption(ol, "proportion_of_switches", &InfiniteMNISTVMatrix::proportion_of_switches, 00144 OptionBase::buildoption, 00145 "Proportion of switches to the original training set.\n"); 00146 00147 declareOption(ol, "seed", &InfiniteMNISTVMatrix::seed, 00148 OptionBase::buildoption, 00149 "Seed of random number generator.\n"); 00150 00151 declareOption(ol, "input_divisor", &InfiniteMNISTVMatrix::input_divisor, 00152 OptionBase::buildoption, 00153 "Value that the inputs should be divided by.\n"); 00154 00155 declareOption(ol, "test_images", &InfiniteMNISTVMatrix::test_images, 00156 OptionBase::buildoption, 00157 "File path of MNIST test images.\n"); 00158 00159 declareOption(ol, "test_labels", &InfiniteMNISTVMatrix::test_labels, 00160 OptionBase::buildoption, 00161 "File path of MNIST test labels.\n"); 00162 00163 declareOption(ol, "train_images", &InfiniteMNISTVMatrix::train_images, 00164 OptionBase::buildoption, 00165 "File path of MNIST train images.\n"); 00166 00167 declareOption(ol, "train_labels", &InfiniteMNISTVMatrix::train_labels, 00168 OptionBase::buildoption, 00169 "File path of MNIST train labels.\n"); 00170 00171 declareOption(ol, "fields", &InfiniteMNISTVMatrix::fields, 00172 OptionBase::buildoption, 00173 "File path of MNIST fields information.\n"); 00174 00175 declareOption(ol, "tangent_vectors", &InfiniteMNISTVMatrix::tangent_vectors, 00176 OptionBase::buildoption, 00177 "File paht of MNIST transformation tangent vectors.\n"); 00178 00179 // Now call the parent class' declareOptions 00180 inherited::declareOptions(ol); 00181 } 00182 00183 void InfiniteMNISTVMatrix::build_() 00184 { 00185 random_gen->manual_seed(seed); 00186 00187 if( !InfiniteMNISTVMatrix::dataset ) 00188 { 00189 char* test_images_char = new char[test_images.size()+1]; 00190 char* test_labels_char = new char[test_labels.size()+1]; 00191 char* train_images_char = new char[train_images.size()+1]; 00192 char* train_labels_char = new char[train_labels.size()+1]; 00193 char* fields_char = new char[fields.size()+1]; 00194 char* tangent_vectors_char = new char[tangent_vectors.size()+1]; 00195 00196 strcpy(test_images_char,test_images.c_str()); 00197 strcpy(test_labels_char,test_labels.c_str()); 00198 strcpy(train_images_char,train_images.c_str()); 00199 strcpy(train_labels_char,train_labels.c_str()); 00200 strcpy(fields_char,fields.c_str()); 00201 strcpy(tangent_vectors_char,tangent_vectors.c_str()); 00202 00203 InfiniteMNISTVMatrix::dataset = create_mnistproblem( 00204 test_images_char, 00205 test_labels_char, 00206 train_images_char, 00207 train_labels_char, 00208 fields_char, 00209 tangent_vectors_char); 00210 if( !InfiniteMNISTVMatrix::dataset ) 00211 PLERROR("In InfiniteMNISTVMatrix(): could not load MNIST dataset"); 00212 } 00213 00214 00215 if( include_test_examples ) 00216 if( include_validation_examples ) 00217 length_ = INT_MAX; 00218 else 00219 // Might be removing more samples than need, but we have so many anyways... 00220 length_ = INT_MAX - ((INT_MAX-10000)/50000)*10000 + 1; 00221 00222 else 00223 if( include_validation_examples ) 00224 length_ = INT_MAX - 10000+1; 00225 else 00226 // Might be removing more samples than need, but we have so many anyways... 00227 length_ = INT_MAX - ((INT_MAX-10000)/50000)*10000 - 10000 + 1; 00228 00229 inputsize_ = 784; 00230 targetsize_ = 1; 00231 weightsize_ = 0; 00232 extrasize_ = 0; 00233 width_ = 785; 00234 00235 // ### You should keep the line 'updateMtime(0);' if you don't implement the 00236 // ### update of the mtime. Otherwise you can have an mtime != 0 that is not valid. 00237 updateMtime(0); 00238 //updateMtime(filename); 00239 //updateMtime(VMat); 00240 } 00241 00242 // ### Nothing to add here, simply calls build_ 00243 void InfiniteMNISTVMatrix::build() 00244 { 00245 inherited::build(); 00246 build_(); 00247 } 00248 00249 void InfiniteMNISTVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00250 { 00251 inherited::makeDeepCopyFromShallowCopy(copies); 00252 00253 // ### Call deepCopyField on all "pointer-like" fields 00254 // ### that you wish to be deepCopied rather than 00255 // ### shallow-copied. 00256 // ### ex: 00257 // deepCopyField(trainvec, copies); 00258 00259 PLWARNING("InfiniteMNISTVMatrix::makeDeepCopyFromShallowCopy is not totally implemented. Need " 00260 "to figure out how to deep copy the \"dataset\" variable (mnistproblem_t*).\n"); 00261 InfiniteMNISTVMatrix::n_pointers_to_dataset++; 00262 image = (unsigned char*)malloc(EXSIZE); 00263 } 00264 00265 } // end of namespace PLearn 00266 00267 00268 /* 00269 Local Variables: 00270 mode:c++ 00271 c-basic-offset:4 00272 c-file-style:"stroustrup" 00273 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00274 indent-tabs-mode:nil 00275 fill-column:79 00276 End: 00277 */ 00278 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :