GaussianKernel.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 1999-2010 Soeren Sonnenburg
00008  * Written (W) 2011 Abhinav Maurya
00009  * Written (W) 2012 Heiko Strathmann
00010  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
00011  * Copyright (C) 2010 Berlin Institute of Technology
00012  */
00013 
00014 #include <shogun/lib/common.h>
00015 #include <shogun/base/Parameter.h>
00016 #include <shogun/kernel/GaussianKernel.h>
00017 #include <shogun/features/DotFeatures.h>
00018 #include <shogun/features/DenseFeatures.h>
00019 #include <shogun/io/SGIO.h>
00020 
00021 using namespace shogun;
00022 
00023 CGaussianKernel::CGaussianKernel()
00024     : CDotKernel()
00025 {
00026     init();
00027 }
00028 
00029 CGaussianKernel::CGaussianKernel(int32_t size, float64_t w)
00030 : CDotKernel(size)
00031 {
00032     init();
00033     set_width(w);
00034 }
00035 
00036 CGaussianKernel::CGaussianKernel(
00037     CDotFeatures* l, CDotFeatures* r, float64_t w, int32_t size)
00038 : CDotKernel(size)
00039 {
00040     init();
00041     set_width(w);
00042     init(l,r);
00043 }
00044 
00045 CGaussianKernel::~CGaussianKernel()
00046 {
00047     cleanup();
00048 }
00049 
00050 CGaussianKernel* CGaussianKernel::obtain_from_generic(CKernel* kernel)
00051 {
00052     if (kernel->get_kernel_type()!=K_GAUSSIAN)
00053     {
00054         SG_SERROR("CGaussianKernel::obtain_from_generic(): provided kernel is "
00055                 "not of type CGaussianKernel!\n");
00056     }
00057 
00058     /* since an additional reference is returned */
00059     SG_REF(kernel);
00060     return (CGaussianKernel*)kernel;
00061 }
00062 
00063 #include <typeinfo>
00064 CSGObject *CGaussianKernel::shallow_copy() const
00065 {
00066     // TODO: remove this after all the classes get shallow_copy properly implemented
00067     // this assert is to avoid any subclass of CGaussianKernel accidentally called
00068     // with the implement here
00069     ASSERT(typeid(*this) == typeid(CGaussianKernel));
00070     CGaussianKernel *ker = new CGaussianKernel(cache_size, width);
00071     if (lhs)
00072     {
00073         ker->init(lhs, rhs);
00074     }
00075     return ker;
00076 }
00077 
00078 void CGaussianKernel::cleanup()
00079 {
00080     if (sq_lhs != sq_rhs)
00081         SG_FREE(sq_rhs);
00082     sq_rhs = NULL;
00083 
00084     SG_FREE(sq_lhs);
00085     sq_lhs = NULL;
00086 
00087     CKernel::cleanup();
00088 }
00089 
00090 void CGaussianKernel::precompute_squared_helper(float64_t* &buf, CDotFeatures* df)
00091 {
00092     ASSERT(df);
00093     int32_t num_vec=df->get_num_vectors();
00094     buf=SG_MALLOC(float64_t, num_vec);
00095 
00096     for (int32_t i=0; i<num_vec; i++)
00097         buf[i]=df->dot(i,df, i);
00098 }
00099 
00100 bool CGaussianKernel::init(CFeatures* l, CFeatures* r)
00101 {
00103     cleanup();
00104 
00105     CDotKernel::init(l, r);
00106     precompute_squared();
00107     return init_normalizer();
00108 }
00109 
00110 float64_t CGaussianKernel::compute(int32_t idx_a, int32_t idx_b)
00111 {
00112     if (!m_compact)
00113     {
00114         float64_t result=sq_lhs[idx_a]+sq_rhs[idx_b]
00115                 -2*CDotKernel::compute(idx_a, idx_b);
00116         return CMath::exp(-result/width);
00117     }
00118 
00119     int32_t len_features, power;
00120     len_features=((CDenseFeatures<float64_t>*) lhs)->get_num_features();
00121     power=(len_features%2==0) ? (len_features+1):len_features;
00122 
00123     float64_t result=sq_lhs[idx_a]+sq_rhs[idx_b]-2*CDotKernel::compute(idx_a,idx_b);
00124     float64_t result_multiplier=1-(sqrt(result/width))/3;
00125 
00126     if (result_multiplier<=0)
00127         result_multiplier=0;
00128     else
00129         result_multiplier=pow(result_multiplier, power);
00130 
00131     return result_multiplier*exp(-result/width);
00132 }
00133 
00134 void CGaussianKernel::load_serializable_post() throw (ShogunException)
00135 {
00136     CKernel::load_serializable_post();
00137     precompute_squared();
00138 }
00139 
00140 void CGaussianKernel::precompute_squared()
00141 {
00142     if (!lhs || !rhs)
00143         return;
00144 
00145     precompute_squared_helper(sq_lhs, (CDotFeatures*) lhs);
00146 
00147     if (lhs==rhs)
00148         sq_rhs=sq_lhs;
00149     else
00150         precompute_squared_helper(sq_rhs, (CDotFeatures*) rhs);
00151 }
00152 
00153 SGMatrix<float64_t> CGaussianKernel::get_parameter_gradient(TParameter* param,
00154         CSGObject* obj, index_t index)
00155 {
00156 
00157     if (strcmp(param->m_name, "width") == 0 && obj == this)
00158     {
00159         SGMatrix<float64_t> derivative = SGMatrix<float64_t>(num_lhs, num_rhs);
00160 
00161         for (int j = 0; j < num_lhs; j++)
00162         {
00163             for (int k = 0; k < num_rhs; k++)
00164             {
00165                 float64_t element = sq_lhs[j]+sq_rhs[k]-2*CDotKernel::compute(j,k);
00166                 derivative(j,k) = exp(-element/width)*element/(width*width);
00167             }
00168         }
00169 
00170         return derivative;
00171     }
00172 
00173     else
00174     {
00175         return SGMatrix<float64_t>(0,0);
00176     }
00177 }
00178 
00179 void CGaussianKernel::init()
00180 {
00181     set_width(1.0);
00182     set_compact_enabled(false); 
00183     sq_lhs=NULL;
00184     sq_rhs=NULL;
00185     SG_ADD(&width, "width", "Kernel width.", MS_AVAILABLE);
00186     SG_ADD(&m_compact, "compact", "Compact Enabled Option.", MS_AVAILABLE);
00187 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation