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