00001 // -*- C++ -*- 00002 00003 // Isomap.cc 00004 // 00005 // Copyright (C) 2004 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 /* ******************************************************* 00036 * $Id: Isomap.cc,v 1.6 2004/07/22 19:10:02 tihocan Exp $ 00037 ******************************************************* */ 00038 00039 // Authors: Olivier Delalleau 00040 00043 #include <plearn/ker/DistanceKernel.h> 00044 #include <plearn/ker/GeodesicDistanceKernel.h> 00045 #include "Isomap.h" 00046 00047 namespace PLearn { 00048 using namespace std; 00049 00051 // Isomap // 00053 Isomap::Isomap() 00054 : geodesic_file(""), 00055 knn(10) 00056 { 00057 kernel_is_distance = true; 00058 // Default distance kernel is the classical Euclidean distance. 00059 distance_kernel = new DistanceKernel(2); 00060 } 00061 00062 PLEARN_IMPLEMENT_OBJECT(Isomap, 00063 "Performs ISOMAP dimensionality reduction.", 00064 "Be careful that when looking for the 'knn' nearest neighbors of a point x,\n" 00065 "we consider all points from the training data D, including x itself if it\n" 00066 "belongs to D. Thus, to obtain the same result as with the classical ISOMAP\n" 00067 "algorithm, one should use one more neighbor.\n" 00068 "Note also that when used out-of-sample, this will result in a different output\n" 00069 "than an algorithm applying the same formula, but considering one less neighbor.\n" 00070 ); 00071 00073 // declareOptions // 00075 void Isomap::declareOptions(OptionList& ol) 00076 { 00077 // ### Declare all of this object's options here 00078 // ### For the "flags" of each option, you should typically specify 00079 // ### one of OptionBase::buildoption, OptionBase::learntoption or 00080 // ### OptionBase::tuningoption. Another possible flag to be combined with 00081 // ### is OptionBase::nosave 00082 00083 // declareOption(ol, "myoption", &Isomap::myoption, OptionBase::buildoption, 00084 // "Help text describing this option"); 00085 // ... 00086 00087 declareOption(ol, "knn", &Isomap::knn, OptionBase::buildoption, 00088 "The number of nearest neighbors considered."); 00089 00090 declareOption(ol, "distance_kernel", &Isomap::distance_kernel, OptionBase::buildoption, 00091 "The kernel used to compute the input space distances."); 00092 00093 declareOption(ol, "geodesic_file", &Isomap::geodesic_file, OptionBase::buildoption, 00094 "If provided, the geodesic distances will be saved in this file in binary format."); 00095 00096 // Now call the parent class' declareOptions 00097 inherited::declareOptions(ol); 00098 00099 // Modify some options from KernelPCA so as to hide them. 00100 redeclareOption(ol, "kernel_is_distance", &Isomap::kernel_is_distance, OptionBase::nosave, 00101 "In ISOMAP, the kernel is always a distance"); 00102 00103 redeclareOption(ol, "kernel", &Isomap::kpca_kernel, OptionBase::learntoption, 00104 "The underlying KPCA kernel is now obtained from 'distance_kernel'."); 00105 00106 } 00107 00109 // build // 00111 void Isomap::build() 00112 { 00113 inherited::build(); 00114 build_(); 00115 } 00116 00118 // build_ // 00120 void Isomap::build_() 00121 { 00122 // Obtain the "real" KPCA kernel by computing the geodesic distances from 00123 // the 'distance_kernel'. 00124 // We have to do this iff: 00125 // 1. A 'distance_kernel' is provided, and 00126 // 2. either: 00127 // 2.a. the 'kpca_kernel' field is not set, or 00128 // 2.b. the 'kpca_kernel' field is not a GeodesicDistanceKernel acting on 'distance_kernel'. 00129 // This is to ensure that a loaded 'kpca_kernel' won't be overwritten. 00130 if (distance_kernel && 00131 (!kpca_kernel || 00132 (dynamic_cast<GeodesicDistanceKernel*>((Kernel*) kpca_kernel))->distance_kernel != distance_kernel)) { 00133 this->kpca_kernel = new GeodesicDistanceKernel(distance_kernel, knn, geodesic_file, true); 00134 // We have modified the KPCA kernel, we must rebuild the KPCA. 00135 inherited::build(); 00136 } 00137 if (kpca_kernel) 00138 kpca_kernel->report_progress = report_progress; 00139 } 00140 00142 // forget // 00144 void Isomap::forget() 00145 { 00146 inherited::forget(); 00147 } 00148 00150 // makeDeepCopyFromShallowCopy // 00152 void Isomap::makeDeepCopyFromShallowCopy(map<const void*, void*>& copies) 00153 { 00154 inherited::makeDeepCopyFromShallowCopy(copies); 00155 00156 // ### Call deepCopyField on all "pointer-like" fields 00157 // ### that you wish to be deepCopied rather than 00158 // ### shallow-copied. 00159 // ### ex: 00160 // deepCopyField(trainvec, copies); 00161 00162 // ### Remove this line when you have fully implemented this method. 00163 PLERROR("Isomap::makeDeepCopyFromShallowCopy not fully (correctly) implemented yet!"); 00164 } 00165 00166 } // end of namespace PLearn 00167