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 * (W) 2012 Jacob Walker 00008 * 00009 * Adapted from WeightedDegreeRBFKernel.cpp 00010 * 00011 */ 00012 00013 #include <shogun/lib/common.h> 00014 #include <shogun/kernel/GaussianARDKernel.h> 00015 #include <shogun/features/Features.h> 00016 #include <shogun/io/SGIO.h> 00017 00018 using namespace shogun; 00019 00020 CGaussianARDKernel::CGaussianARDKernel() 00021 : CLinearARDKernel() 00022 { 00023 init(); 00024 } 00025 00026 00027 CGaussianARDKernel::CGaussianARDKernel(int32_t size, float64_t width) 00028 : CLinearARDKernel(size), m_width(width) 00029 { 00030 init(); 00031 } 00032 00033 CGaussianARDKernel::CGaussianARDKernel(CDenseFeatures<float64_t>* l, 00034 CDenseFeatures<float64_t>* r, 00035 int32_t size, float64_t width) 00036 : CLinearARDKernel(size), m_width(width) 00037 { 00038 init(); 00039 } 00040 00041 bool CGaussianARDKernel::init(CFeatures* l, CFeatures* r) 00042 { 00043 return CLinearARDKernel::init(l,r); 00044 } 00045 00046 void CGaussianARDKernel::init() 00047 { 00048 m_width = 2.0; 00049 00050 SG_ADD(&m_width, "width", "Kernel Width", MS_AVAILABLE); 00051 } 00052 00053 CGaussianARDKernel::~CGaussianARDKernel() 00054 { 00055 } 00056 00057 float64_t CGaussianARDKernel::compute(int32_t idx_a, int32_t idx_b) 00058 { 00059 if (!lhs || !rhs) 00060 SG_ERROR("Features not set!\n"); 00061 00062 SGVector<float64_t> avec 00063 = ((CDenseFeatures<float64_t>*) lhs)->get_feature_vector(idx_a); 00064 SGVector<float64_t> bvec 00065 = ((CDenseFeatures<float64_t>*) rhs)->get_feature_vector(idx_b); 00066 00067 REQUIRE(avec.vlen==bvec.vlen, "Number of Right and Left Hand "\ 00068 "Features Must be the Same./n"); 00069 00070 float64_t result=0; 00071 00072 for (index_t i = 0; i < avec.vlen; i++) 00073 result += CMath::pow((avec[i]-bvec[i])*m_weights[i], 2); 00074 00075 return CMath::exp(-result/m_width); 00076 } 00077 00078 SGMatrix<float64_t> CGaussianARDKernel::get_parameter_gradient(TParameter* param, 00079 CSGObject* obj, index_t index) 00080 { 00081 if (!lhs || !rhs) 00082 SG_ERROR("Features not set!\n"); 00083 00084 if (!strcmp(param->m_name, "weights") && obj == this) 00085 { 00086 SGMatrix<float64_t> derivative = get_kernel_matrix(); 00087 00088 for (index_t j = 0; j < num_lhs; j++) 00089 { 00090 for (index_t k = 0; k < num_rhs; k++) 00091 { 00092 SGVector<float64_t> avec 00093 = ((CDenseFeatures<float64_t>*) lhs)->get_feature_vector(j); 00094 SGVector<float64_t> bvec 00095 = ((CDenseFeatures<float64_t>*) rhs)->get_feature_vector(k); 00096 00097 REQUIRE(avec.vlen==bvec.vlen, "Number of Right and Left Hand "\ 00098 "Features Must be the Same./n"); 00099 00100 float64_t element = compute(j,k); 00101 float64_t product = 00102 CMath::pow((avec[index]-bvec[index]), 2) 00103 *(m_weights[index]/m_width); 00104 00105 derivative(j,k) = -2*element*product; 00106 } 00107 } 00108 00109 return derivative; 00110 } 00111 00112 else if (!strcmp(param->m_name, "width") && obj == this) 00113 { 00114 SGMatrix<float64_t> derivative(num_lhs, num_rhs); 00115 00116 for (index_t j = 0; j < num_lhs; j++) 00117 { 00118 for (index_t k = 0; k < num_rhs; k++) 00119 { 00120 SGVector<float64_t> avec 00121 = ((CDenseFeatures<float64_t>*) lhs)->get_feature_vector(j); 00122 SGVector<float64_t> bvec 00123 = ((CDenseFeatures<float64_t>*) rhs)->get_feature_vector(k); 00124 00125 REQUIRE(avec.vlen==bvec.vlen, "Number of Right and Left Hand "\ 00126 "Features Must be the Same./n"); 00127 00128 float64_t result=0; 00129 00130 for (index_t i = 0; i < avec.vlen; i++) 00131 result += CMath::pow((avec[i]-bvec[i])*m_weights[i], 2); 00132 00133 derivative(j,k) = CMath::exp(-result/m_width)* 00134 result/(m_width*m_width); 00135 } 00136 } 00137 00138 return derivative; 00139 } 00140 00141 00142 else 00143 return SGMatrix<float64_t>(); 00144 }