SHOGUN
v2.0.0
|
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 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00010 * Copyright (C) 2010 Berlin Institute of Technology 00011 */ 00012 00013 #include <shogun/lib/common.h> 00014 #include <shogun/base/Parameter.h> 00015 #include <shogun/kernel/GaussianKernel.h> 00016 #include <shogun/features/DotFeatures.h> 00017 #include <shogun/features/DenseFeatures.h> 00018 #include <shogun/io/SGIO.h> 00019 00020 using namespace shogun; 00021 00022 CGaussianKernel::CGaussianKernel() 00023 : CDotKernel() 00024 { 00025 init(); 00026 } 00027 00028 CGaussianKernel::CGaussianKernel(int32_t size, float64_t w) 00029 : CDotKernel(size) 00030 { 00031 init(); 00032 set_width(w); 00033 } 00034 00035 CGaussianKernel::CGaussianKernel( 00036 CDotFeatures* l, CDotFeatures* r, float64_t w, int32_t size) 00037 : CDotKernel(size) 00038 { 00039 init(); 00040 set_width(w); 00041 init(l,r); 00042 } 00043 00044 CGaussianKernel::~CGaussianKernel() 00045 { 00046 cleanup(); 00047 } 00048 00049 #include <typeinfo> 00050 CSGObject *CGaussianKernel::shallow_copy() const 00051 { 00052 // TODO: remove this after all the classes get shallow_copy properly implemented 00053 // this assert is to avoid any subclass of CGaussianKernel accidentally called 00054 // with the implement here 00055 ASSERT(typeid(*this) == typeid(CGaussianKernel)); 00056 CGaussianKernel *ker = new CGaussianKernel(width, cache_size); 00057 if (lhs) 00058 { 00059 ker->init(lhs, rhs); 00060 } 00061 return ker; 00062 } 00063 00064 void CGaussianKernel::cleanup() 00065 { 00066 if (sq_lhs != sq_rhs) 00067 SG_FREE(sq_rhs); 00068 sq_rhs = NULL; 00069 00070 SG_FREE(sq_lhs); 00071 sq_lhs = NULL; 00072 00073 CKernel::cleanup(); 00074 } 00075 00076 void CGaussianKernel::precompute_squared_helper(float64_t* &buf, CDotFeatures* df) 00077 { 00078 ASSERT(df); 00079 int32_t num_vec=df->get_num_vectors(); 00080 buf=SG_MALLOC(float64_t, num_vec); 00081 00082 for (int32_t i=0; i<num_vec; i++) 00083 buf[i]=df->dot(i,df, i); 00084 } 00085 00086 bool CGaussianKernel::init(CFeatures* l, CFeatures* r) 00087 { 00089 cleanup(); 00090 00091 CDotKernel::init(l, r); 00092 precompute_squared(); 00093 return init_normalizer(); 00094 } 00095 00096 float64_t CGaussianKernel::compute(int32_t idx_a, int32_t idx_b) 00097 { 00098 if (!m_compact) 00099 { 00100 float64_t result=sq_lhs[idx_a]+sq_rhs[idx_b] 00101 -2*CDotKernel::compute(idx_a, idx_b); 00102 return CMath::exp(-result/width); 00103 } 00104 00105 int32_t len_features, power; 00106 len_features=((CDenseFeatures<float64_t>*) lhs)->get_num_features(); 00107 power=(len_features%2==0) ? (len_features+1):len_features; 00108 00109 float64_t result=sq_lhs[idx_a]+sq_rhs[idx_b]-2*CDotKernel::compute(idx_a,idx_b); 00110 float64_t result_multiplier=1-(sqrt(result/width))/3; 00111 00112 if (result_multiplier<=0) 00113 result_multiplier=0; 00114 else 00115 result_multiplier=pow(result_multiplier, power); 00116 00117 return result_multiplier*exp(-result/width); 00118 } 00119 00120 void CGaussianKernel::load_serializable_post() throw (ShogunException) 00121 { 00122 CKernel::load_serializable_post(); 00123 precompute_squared(); 00124 } 00125 00126 void CGaussianKernel::precompute_squared() 00127 { 00128 if (!lhs || !rhs) 00129 return; 00130 00131 precompute_squared_helper(sq_lhs, (CDotFeatures*) lhs); 00132 00133 if (lhs==rhs) 00134 sq_rhs=sq_lhs; 00135 else 00136 precompute_squared_helper(sq_rhs, (CDotFeatures*) rhs); 00137 } 00138 00139 SGMatrix<float64_t> CGaussianKernel::get_parameter_gradient(TParameter* param, 00140 CSGObject* obj, index_t index) 00141 { 00142 00143 if (strcmp(param->m_name, "width") == 0 && obj == this) 00144 { 00145 SGMatrix<float64_t> derivative = SGMatrix<float64_t>(num_lhs, num_rhs); 00146 00147 for (int j = 0; j < num_lhs; j++) 00148 { 00149 for (int k = 0; k < num_rhs; k++) 00150 { 00151 float64_t element = sq_lhs[j]+sq_rhs[k]-2*CDotKernel::compute(j,k); 00152 derivative(j,k) = exp(-element/width)*element/(width*width); 00153 } 00154 } 00155 00156 return derivative; 00157 } 00158 00159 else 00160 { 00161 return SGMatrix<float64_t>(0,0); 00162 } 00163 } 00164 00165 void CGaussianKernel::init() 00166 { 00167 set_width(1.0); 00168 set_compact_enabled(false); 00169 sq_lhs=NULL; 00170 sq_rhs=NULL; 00171 SG_ADD(&width, "width", "Kernel width.", MS_AVAILABLE); 00172 SG_ADD(&m_compact, "compact", "Compact Enabled Option.", MS_AVAILABLE); 00173 }