PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // RandomGaussMix.cc 00004 // 00005 // Copyright (C) 2006 Olivier Delalleau 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: Olivier Delalleau 00036 00040 #include "RandomGaussMix.h" 00041 #include <plearn/io/load_and_save.h> 00042 00043 namespace PLearn { 00044 using namespace std; 00045 00046 PLEARN_IMPLEMENT_OBJECT( 00047 RandomGaussMix, 00048 "Mixture of Gaussians where the means and covariances are randomly chosen", 00049 "The means' distribution is provided by the user. The principal\n" 00050 "directions are obtained from Gram-Schmidt orthogonalization of a random\n" 00051 "matrix. The variances in the principal directions are obtained from\n" 00052 "a user-provided distribution. The weights of the Gaussians are also\n" 00053 "taken from another user-provided distribution.\n" 00054 "Note that for the sake of simplicity, this is an unconditional\n" 00055 "distribution.\n" 00056 ); 00057 00059 // RandomGaussMix // 00061 RandomGaussMix::RandomGaussMix() 00062 { 00063 type = "general"; 00064 } 00065 00067 // declareOptions // 00069 void RandomGaussMix::declareOptions(OptionList& ol) 00070 { 00071 // ### Declare all of this object's options here 00072 // ### For the "flags" of each option, you should typically specify 00073 // ### one of OptionBase::buildoption, OptionBase::learntoption or 00074 // ### OptionBase::tuningoption. Another possible flag to be combined with 00075 // ### is OptionBase::nosave 00076 00077 declareOption(ol, "mean_distribution", 00078 &RandomGaussMix::mean_distribution, 00079 OptionBase::buildoption, 00080 "The distribution from which means are sampled. A sample from this\n" 00081 "distribution should be a D-dimensional vector, representing the mean\n" 00082 "of a Gaussian in the input space."); 00083 00084 declareOption(ol, "variance_distribution", 00085 &RandomGaussMix::variance_distribution, 00086 OptionBase::buildoption, 00087 "The distribution from which variances are sampled. A sample from\n" 00088 "this distribution should be a D-dimensional vector, representing\n" 00089 "the variance in each of the D principal directions of the Gaussian."); 00090 00091 declareOption(ol, "weight_distribution", 00092 &RandomGaussMix::weight_distribution, 00093 OptionBase::buildoption, 00094 "The distribution from which the weight of each Gaussian is sampled.\n" 00095 "It should output a single non-negative scalar (the weights will be\n" 00096 "normalized afterwards so that they sum to 1)."); 00097 00098 // Now call the parent class' declareOptions(). 00099 inherited::declareOptions(ol); 00100 00101 // Hide unused options. 00102 redeclareOption(ol, "type", &RandomGaussMix::type, 00103 OptionBase::nosave, 00104 "Not used in RandomGaussMix."); 00105 00106 redeclareOption(ol, "n_eigen", &RandomGaussMix::n_eigen, 00107 OptionBase::nosave, 00108 "Not used in RandomGaussMix."); 00109 00110 redeclareOption(ol, "efficient_missing", 00111 &RandomGaussMix::efficient_missing, 00112 OptionBase::nosave, 00113 "Not used in RandomGaussMix."); 00114 00115 redeclareOption(ol, "efficient_k_median", 00116 &RandomGaussMix::efficient_k_median, 00117 OptionBase::nosave, 00118 "Not used in RandomGaussMix."); 00119 00120 redeclareOption(ol, "efficient_k_median_iter", 00121 &RandomGaussMix::efficient_k_median_iter, 00122 OptionBase::nosave, 00123 "Not used in RandomGaussMix."); 00124 00125 redeclareOption(ol, "impute_missing", &RandomGaussMix::impute_missing, 00126 OptionBase::nosave, 00127 "Not used in RandomGaussMix."); 00128 00129 redeclareOption(ol, "kmeans_iterations", 00130 &RandomGaussMix::kmeans_iterations, 00131 OptionBase::nosave, 00132 "Not used in RandomGaussMix."); 00133 00134 redeclareOption(ol, "alpha_min", &RandomGaussMix::alpha_min, 00135 OptionBase::nosave, 00136 "Not used in RandomGaussMix."); 00137 00138 redeclareOption(ol,"sigma_min", &RandomGaussMix::sigma_min, 00139 OptionBase::nosave, 00140 "Not used in RandomGaussMix."); 00141 00142 redeclareOption(ol, "epsilon", &RandomGaussMix::epsilon, 00143 OptionBase::nosave, 00144 "Not used in RandomGaussMix."); 00145 00146 redeclareOption(ol, "predictor_size", 00147 &RandomGaussMix::predictor_size, 00148 OptionBase::nosave, 00149 "Not used in RandomGaussMix."); 00150 00151 redeclareOption(ol, "predicted_size", 00152 &RandomGaussMix::predicted_size, 00153 OptionBase::nosave, 00154 "Not used in RandomGaussMix."); 00155 00156 redeclareOption(ol, "predictor_part", 00157 &RandomGaussMix::predictor_part, 00158 OptionBase::nosave, 00159 "Not used in RandomGaussMix."); 00160 00161 redeclareOption(ol, "n_predictor", 00162 &RandomGaussMix::n_predictor, 00163 OptionBase::nosave, 00164 "Not used in RandomGaussMix."); 00165 00166 redeclareOption(ol, "expdir", &RandomGaussMix::expdir, 00167 OptionBase::nosave, 00168 "Not used in RandomGaussMix."); 00169 00170 redeclareOption(ol, "forget_when_training_set_changes", 00171 &RandomGaussMix::forget_when_training_set_changes, 00172 OptionBase::nosave, 00173 "Not used in RandomGaussMix."); 00174 00175 redeclareOption(ol, "nstages", &RandomGaussMix::nstages, 00176 OptionBase::nosave, 00177 "Not used in RandomGaussMix."); 00178 00179 redeclareOption(ol, "nservers", &RandomGaussMix::nservers, 00180 OptionBase::nosave, 00181 "Not used in RandomGaussMix."); 00182 00183 redeclareOption(ol, "save_trainingset_prefix", 00184 &RandomGaussMix::save_trainingset_prefix, 00185 OptionBase::nosave, 00186 "Not used in RandomGaussMix."); 00187 } 00188 00190 // build // 00192 void RandomGaussMix::build() 00193 { 00194 inherited::build(); 00195 build_(); 00196 } 00197 00199 // build_ // 00201 void RandomGaussMix::build_() 00202 { 00203 if (!variance_distribution || !mean_distribution || !weight_distribution) 00204 return; 00205 00206 // Need to reset the underlying distributions' seeds so that the generated 00207 // values are always the same at each build. 00208 mean_distribution->resetGenerator(mean_distribution->seed_); 00209 variance_distribution->resetGenerator(variance_distribution->seed_); 00210 weight_distribution->resetGenerator(weight_distribution->seed_); 00211 00212 D = mean_distribution->getNPredicted(); 00213 00214 // Generate random Gaussian parameters. 00215 eigenvalues.resize(L, D); 00216 center.resize(L, D); 00217 alpha.resize(L); 00218 eigenvectors.resize(L); 00219 for (int j = 0; j < L; j++) { 00220 // Generate random matrix and perform Gram-Schmidt orthonormalization. 00221 Mat& eigenvecs = eigenvectors[j]; 00222 eigenvecs.resize(D, D); 00223 int n_basis = -1; 00224 // It might happen that the rows of the random matrix are not 00225 // sufficiently independent, in which case we just try again. 00226 while (n_basis != D) { 00227 random_gen->fill_random_uniform(eigenvecs, -1, 1); 00228 n_basis = GramSchmidtOrthogonalization(eigenvecs); 00229 } 00230 // Generate random eigenvalues. 00231 Vec eigenvals = eigenvalues(j); 00232 variance_distribution->generate(eigenvals); 00233 PLASSERT( eigenvals.length() == D ); 00234 // Note that eigenvalues must be sorted in decreasing order. 00235 sortElements(eigenvals); 00236 eigenvals.swap(); 00237 // Generate random mean. 00238 Vec mean_j = center(j); 00239 mean_distribution->generate(mean_j); 00240 PLASSERT( mean_j.length() == D ); 00241 // Generate random weight. 00242 Vec alpha_j = alpha.subVec(j, 1); 00243 weight_distribution->generate(alpha_j); 00244 PLASSERT( alpha_j.length() == 1 ); 00245 } 00246 // Normalize 'alpha' so that it sums to 1. 00247 real sum = 0; 00248 for (int j = 0; j < L; j++) { 00249 real alpha_j = alpha[j]; 00250 if (alpha_j < 0) 00251 PLERROR("In RandomGaussMix::build_ - The weight of a Gaussian " 00252 "cannot be negative"); 00253 sum += alpha_j; 00254 } 00255 PLASSERT( sum > 0 ); 00256 alpha /= sum; 00257 // Set a few parameters that are needed. 00258 alpha_min = min(alpha); 00259 sigma_min = 1e-10; 00260 inputsize_ = D; 00261 n_eigen_computed = D; 00262 stage = 1; 00263 // Rebuild the mixture. 00264 inherited::build(); 00265 } 00266 00268 // makeDeepCopyFromShallowCopy // 00270 void RandomGaussMix::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00271 { 00272 inherited::makeDeepCopyFromShallowCopy(copies); 00273 00274 // ### Call deepCopyField on all "pointer-like" fields 00275 // ### that you wish to be deepCopied rather than 00276 // ### shallow-copied. 00277 // ### ex: 00278 // deepCopyField(trainvec, copies); 00279 00280 // ### Remove this line when you have fully implemented this method. 00281 PLERROR("RandomGaussMix::makeDeepCopyFromShallowCopy not fully (correctly) implemented yet!"); 00282 } 00283 00285 // train // 00287 void RandomGaussMix::train() 00288 { 00289 // This class does not need to be trained. 00290 return; 00291 } 00292 00293 } // end of namespace PLearn 00294 00295 00296 /* 00297 Local Variables: 00298 mode:c++ 00299 c-basic-offset:4 00300 c-file-style:"stroustrup" 00301 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00302 indent-tabs-mode:nil 00303 fill-column:79 00304 End: 00305 */ 00306 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :