SHOGUN  v3.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
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() : CDotKernel()
00024 {
00025     init();
00026 }
00027 
00028 CGaussianKernel::CGaussianKernel(int32_t size, float64_t w) : CDotKernel(size)
00029 {
00030     init();
00031     set_width(w);
00032 }
00033 
00034 CGaussianKernel::CGaussianKernel(CDotFeatures* l, CDotFeatures* r,
00035         float64_t w, int32_t size) : CDotKernel(size)
00036 {
00037     init();
00038     set_width(w);
00039     init(l,r);
00040 }
00041 
00042 CGaussianKernel::~CGaussianKernel()
00043 {
00044     cleanup();
00045 }
00046 
00047 CGaussianKernel* CGaussianKernel::obtain_from_generic(CKernel* kernel)
00048 {
00049     if (kernel->get_kernel_type()!=K_GAUSSIAN)
00050     {
00051         SG_SERROR("CGaussianKernel::obtain_from_generic(): provided kernel is "
00052                 "not of type CGaussianKernel!\n");
00053     }
00054 
00055     /* since an additional reference is returned */
00056     SG_REF(kernel);
00057     return (CGaussianKernel*)kernel;
00058 }
00059 
00060 #include <typeinfo>
00061 CSGObject *CGaussianKernel::shallow_copy() const
00062 {
00063     // TODO: remove this after all the classes get shallow_copy properly implemented
00064     // this assert is to avoid any subclass of CGaussianKernel accidentally called
00065     // with the implement here
00066     ASSERT(typeid(*this) == typeid(CGaussianKernel))
00067     CGaussianKernel *ker = new CGaussianKernel(cache_size, width);
00068     if (lhs)
00069     {
00070         ker->init(lhs, rhs);
00071     }
00072     return ker;
00073 }
00074 
00075 void CGaussianKernel::cleanup()
00076 {
00077     if (sq_lhs != sq_rhs)
00078         SG_FREE(sq_rhs);
00079     sq_rhs = NULL;
00080 
00081     SG_FREE(sq_lhs);
00082     sq_lhs = NULL;
00083 
00084     CKernel::cleanup();
00085 }
00086 
00087 void CGaussianKernel::precompute_squared_helper(float64_t* &buf, CDotFeatures* df)
00088 {
00089     ASSERT(df)
00090     int32_t num_vec=df->get_num_vectors();
00091     buf=SG_MALLOC(float64_t, num_vec);
00092 
00093     for (int32_t i=0; i<num_vec; i++)
00094         buf[i]=df->dot(i,df, i);
00095 }
00096 
00097 bool CGaussianKernel::init(CFeatures* l, CFeatures* r)
00098 {
00100     cleanup();
00101 
00102     CDotKernel::init(l, r);
00103     precompute_squared();
00104     return init_normalizer();
00105 }
00106 
00107 float64_t CGaussianKernel::compute(int32_t idx_a, int32_t idx_b)
00108 {
00109     if (!m_compact)
00110     {
00111         float64_t result=sq_lhs[idx_a]+sq_rhs[idx_b]
00112                 -2*CDotKernel::compute(idx_a, idx_b);
00113         return CMath::exp(-result/width);
00114     }
00115 
00116     int32_t len_features, power;
00117     len_features=((CDenseFeatures<float64_t>*) lhs)->get_num_features();
00118     power=(len_features%2==0) ? (len_features+1):len_features;
00119 
00120     float64_t result=sq_lhs[idx_a]+sq_rhs[idx_b]-2*CDotKernel::compute(idx_a,idx_b);
00121     float64_t result_multiplier=1-(sqrt(result/width))/3;
00122 
00123     if (result_multiplier<=0)
00124         result_multiplier=0;
00125     else
00126         result_multiplier=pow(result_multiplier, power);
00127 
00128     return result_multiplier*exp(-result/width);
00129 }
00130 
00131 void CGaussianKernel::load_serializable_post() throw (ShogunException)
00132 {
00133     CKernel::load_serializable_post();
00134     precompute_squared();
00135 }
00136 
00137 void CGaussianKernel::precompute_squared()
00138 {
00139     if (!lhs || !rhs)
00140         return;
00141 
00142     precompute_squared_helper(sq_lhs, (CDotFeatures*) lhs);
00143 
00144     if (lhs==rhs)
00145         sq_rhs=sq_lhs;
00146     else
00147         precompute_squared_helper(sq_rhs, (CDotFeatures*) rhs);
00148 }
00149 
00150 SGMatrix<float64_t> CGaussianKernel::get_parameter_gradient(
00151         const TParameter* param, index_t index)
00152 {
00153     REQUIRE(lhs && rhs, "Features not set!\n")
00154 
00155     if (!strcmp(param->m_name, "width"))
00156     {
00157         SGMatrix<float64_t> derivative=SGMatrix<float64_t>(num_lhs, num_rhs);
00158 
00159         for (int j=0; j<num_lhs; j++)
00160             for (int k=0; k<num_rhs; k++)
00161             {
00162                 float64_t element=sq_lhs[j]+sq_rhs[k]-2*CDotKernel::compute(j,k);
00163                 derivative(j,k)=exp(-element/width)*element/(width*width);
00164             }
00165 
00166         return derivative;
00167     }
00168     else
00169     {
00170         SG_ERROR("Can't compute derivative wrt %s parameter\n", param->m_name);
00171         return SGMatrix<float64_t>();
00172     }
00173 }
00174 
00175 void CGaussianKernel::init()
00176 {
00177     set_width(1.0);
00178     set_compact_enabled(false);
00179     sq_lhs=NULL;
00180     sq_rhs=NULL;
00181     SG_ADD(&width, "width", "Kernel width", MS_AVAILABLE, GRADIENT_AVAILABLE);
00182     SG_ADD(&m_compact, "compact", "Compact enabled option", MS_AVAILABLE);
00183 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation