PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // BetaKernel.cc 00004 // 00005 // Copyright (C) 2008 Dumitru Erhan 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: Dumitru Erhan 00036 00040 #include "BetaKernel.h" 00041 #include <plearn/math/distr_maths.h> 00042 00043 namespace PLearn { 00044 using namespace std; 00045 00046 PLEARN_IMPLEMENT_OBJECT( 00047 BetaKernel, 00048 "Several implementatins of the Beta kernel, for distributions that have support in the [0;1] range", 00049 "Useful for performing Parzen Windows-style density estimation. Need to specify the type of the kernel\n" 00050 "- simple: the basic Beta kernel \n" 00051 "- alternative: the alternative, faster converging version \n" 00052 "output_type should be set to either log_value or normal" ); 00053 00055 // BetaKernel // 00057 BetaKernel::BetaKernel() 00058 : width(1.), 00059 kernel_type("simple"), 00060 output_type("normal") 00061 { 00062 } 00063 00065 // declareOptions // 00067 void BetaKernel::declareOptions(OptionList& ol) 00068 { 00069 00070 declareOption(ol, "width", &BetaKernel::width, 00071 OptionBase::buildoption, 00072 "The (positive, real-valued) smoothing parameter of the kernel (note that this does not quite correspond to the variance). If you use the Beta Kernel to do density estimation, this should go towards zero as the number of samples goes to infinity"); 00073 00074 declareOption(ol, "kernel_type", &BetaKernel::kernel_type, 00075 OptionBase::buildoption, 00076 "A string containing the type of Beta kernel. The \"simple\" kernel has a particularly simple mathematical form and is easily shown to integrate to 1 (thus is a density). The \"alternative\" kernel is slightly more complicated, but is better suited for those distributions that have a lot of mass near the boundaries (0 or 1). It will converge faster, but asymptotically both kernels are boundary bias free. Also, the \"alternative\" kernel is not yet shown by us to integrate to 1, thus we don't know for sure whether it's a valid density. Default is simple"); 00077 00078 declareOption(ol, "output_type", &BetaKernel::output_type, 00079 OptionBase::buildoption, 00080 "A string specifying whether we want log densities as outputs (\"log_value\" ) or just densities (\"normal\"; default)"); 00081 00082 // Now call the parent class' declareOptions 00083 inherited::declareOptions(ol); 00084 } 00085 00087 // build // 00089 void BetaKernel::build() 00090 { 00091 // ### Nothing to add here, simply calls build_ 00092 inherited::build(); 00093 build_(); 00094 } 00095 00097 // build_ // 00099 void BetaKernel::build_() 00100 { 00101 } 00102 00104 // evaluate // 00106 real BetaKernel::evaluate(const Vec& x1, const Vec& x2) const { 00107 #ifdef BOUNDCHECK 00108 if(x1.length()!=x2.length()) 00109 PLERROR("In BetaKernel::evaluate x1 and x2 must have the same length"); 00110 #endif 00111 int l = x1.length(); 00112 real* px1 = x1.data(); 00113 real* px2 = x2.data(); 00114 real kvalue = 0.; 00115 00116 //kernel_type = lowerstring(kernel_type); 00117 00118 // check http://www.sta.nus.edu.sg/documents/publication_chen2.pdf for an 00119 // explanation of the estimators ("Beta kernel estimators for 00120 // density functions" is the paper title) 00121 if (kernel_type=="simple") 00122 for(int i=0; i<l; i++) 00123 { 00124 real a = px1[i] / width + 1.0; 00125 real b = (1.0 - px1[i]) / width + 1.0; 00126 real val = log_beta_density(px2[i],a,b); 00127 kvalue += val; 00128 } 00129 else if (kernel_type=="alternative") 00130 for(int i=0; i<l; i++) 00131 { 00132 real x = px1[i]; 00133 real a, b; 00134 00135 PLASSERT_MSG(x<0 || x >1 || px2[i] < 0 || px2[i] > 1, "In BetaKernel::evaluate x1 and x2 must contain values in the (closed) interval [0;1]"); 00136 00137 if ((x >= 2*width) && (x <= 1 - 2*width)) { 00138 a = x / width; 00139 b = (1 - x) / width; 00140 } 00141 else if ((x >= 0) & (x <= 2*width)) { 00142 a = 2*pow(width,real(2)) + 2.5 - sqrt(4*pow(width,real(4)) + 6*pow(width,real(2)) + 2.25 - x*x - x / width); 00143 b = (1 - x) / width; 00144 } 00145 else { 00146 a = x / width; 00147 real y = 1-x; 00148 b = 2*pow(width,real(2)) + 2.5 - sqrt(4*pow(width,real(4))+ 6*pow(width,real(2)) + 2.25 - y*y - y / width); 00149 } 00150 00151 real val = log_beta_density(px2[i],a,b); 00152 kvalue += val; 00153 } 00154 else 00155 PLERROR("In BetaKernel::evaluate kernel_type must be either \"simple\" or \"alternative\""); 00156 00157 real retval = 0.0; 00158 00159 if (output_type=="log_value") 00160 retval = kvalue; 00161 else if (output_type=="normal") 00162 retval = exp(kvalue); 00163 else 00164 PLERROR("In BetaKernel::evaluate output_type must be either \"log_value\" or \"normal\""); 00165 00166 return retval; 00167 } 00168 00169 /* ### This method will very often be overridden. 00171 // evaluate_i_j // 00173 real BetaKernel::evaluate_i_j(int i, int j) const { 00174 // ### Evaluate the kernel on a pair of training points. 00175 } 00176 */ 00177 00179 // makeDeepCopyFromShallowCopy // 00181 void BetaKernel::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00182 { 00183 inherited::makeDeepCopyFromShallowCopy(copies); 00184 } 00185 00186 /* ### This method will be overridden if computations need to be done, 00187 ### or to forward the call to another object. 00188 ### In this case, be careful that it may be called BEFORE the build_() 00189 ### method has been called, if the 'specify_dataset' option is used. 00191 // setDataForKernelMatrix // 00193 void BetaKernel::setDataForKernelMatrix(VMat the_data) { 00194 } 00195 */ 00196 00197 } // end of namespace PLearn 00198 00199 00200 /* 00201 Local Variables: 00202 mode:c++ 00203 c-basic-offset:4 00204 c-file-style:"stroustrup" 00205 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00206 indent-tabs-mode:nil 00207 fill-column:79 00208 End: 00209 */ 00210 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :