SHOGUN
v3.2.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 * Copyright (C) 2012 Jacob Walker 00008 * 00009 * Code adapted from CCombinedKernel 00010 */ 00011 00012 #include <shogun/kernel/ProductKernel.h> 00013 #include <shogun/kernel/CustomKernel.h> 00014 00015 using namespace shogun; 00016 00017 CProductKernel::CProductKernel(int32_t size) : CKernel(size) 00018 { 00019 init(); 00020 00021 SG_INFO("Product kernel created (%p)\n", this) 00022 } 00023 00024 CProductKernel::~CProductKernel() 00025 { 00026 cleanup(); 00027 SG_UNREF(kernel_array); 00028 00029 SG_INFO("Product kernel deleted (%p).\n", this) 00030 } 00031 00032 //Adapted from CCombinedKernel 00033 bool CProductKernel::init(CFeatures* l, CFeatures* r) 00034 { 00035 CKernel::init(l,r); 00036 ASSERT(l->get_feature_class()==C_COMBINED) 00037 ASSERT(r->get_feature_class()==C_COMBINED) 00038 ASSERT(l->get_feature_type()==F_UNKNOWN) 00039 ASSERT(r->get_feature_type()==F_UNKNOWN) 00040 00041 CFeatures* lf=NULL; 00042 CFeatures* rf=NULL; 00043 CKernel* k=NULL; 00044 00045 bool result=true; 00046 00047 index_t f_idx=0; 00048 for (index_t k_idx=0; k_idx<get_num_subkernels() && result; k_idx++) 00049 { 00050 k=get_kernel(k_idx); 00051 if (!k) 00052 SG_ERROR("Kernel at position %d is NULL\n", k_idx); 00053 00054 // skip over features - the custom kernel does not need any 00055 if (k->get_kernel_type() != K_CUSTOM) 00056 { 00057 lf=((CCombinedFeatures*) l)->get_feature_obj(f_idx); 00058 rf=((CCombinedFeatures*) r)->get_feature_obj(f_idx); 00059 f_idx++; 00060 if (!lf || !rf) 00061 { 00062 SG_UNREF(lf); 00063 SG_UNREF(rf); 00064 SG_UNREF(k); 00065 SG_ERROR("ProductKernel: Number of features/kernels does not match - bailing out\n") 00066 } 00067 00068 SG_DEBUG("Initializing 0x%p - \"%s\"\n", this, k->get_name()) 00069 result=k->init(lf,rf); 00070 00071 SG_UNREF(lf); 00072 SG_UNREF(rf); 00073 00074 if (!result) 00075 break; 00076 } 00077 else 00078 { 00079 SG_DEBUG("Initializing 0x%p - \"%s\" (skipping init, this is a CUSTOM kernel)\n", this, k->get_name()) 00080 if (!k->has_features()) 00081 SG_ERROR("No kernel matrix was assigned to this Custom kernel\n") 00082 if (k->get_num_vec_lhs() != num_lhs) 00083 SG_ERROR("Number of lhs-feature vectors (%d) not match with number of rows (%d) of custom kernel\n", num_lhs, k->get_num_vec_lhs()) 00084 if (k->get_num_vec_rhs() != num_rhs) 00085 SG_ERROR("Number of rhs-feature vectors (%d) not match with number of cols (%d) of custom kernel\n", num_rhs, k->get_num_vec_rhs()) 00086 } 00087 00088 SG_UNREF(k); 00089 } 00090 00091 if (!result) 00092 { 00093 SG_INFO("ProductKernel: Initialising the following kernel failed\n") 00094 if (k) 00095 { 00096 k->list_kernel(); 00097 SG_UNREF(k); 00098 } 00099 else 00100 SG_INFO("<NULL>\n") 00101 return false; 00102 } 00103 00104 if ( (f_idx!=((CCombinedFeatures*) l)->get_num_feature_obj()) || 00105 (f_idx!=((CCombinedFeatures*) r)->get_num_feature_obj()) ) 00106 SG_ERROR("ProductKernel: Number of features/kernels does not match - bailing out\n") 00107 00108 initialized=true; 00109 return true; 00110 } 00111 00112 //Adapted from CCombinedKernel 00113 void CProductKernel::remove_lhs() 00114 { 00115 for (index_t k_idx=0; k_idx<get_num_subkernels(); k_idx++) 00116 { 00117 CKernel* k=get_kernel(k_idx); 00118 if (k->get_kernel_type() != K_CUSTOM) 00119 k->remove_lhs(); 00120 00121 SG_UNREF(k); 00122 } 00123 CKernel::remove_lhs(); 00124 00125 num_lhs=0; 00126 } 00127 00128 //Adapted from CCombinedKernel 00129 void CProductKernel::remove_rhs() 00130 { 00131 for (index_t k_idx=0; k_idx<get_num_subkernels(); k_idx++) 00132 { 00133 CKernel* k=get_kernel(k_idx); 00134 if (k->get_kernel_type() != K_CUSTOM) 00135 k->remove_rhs(); 00136 SG_UNREF(k); 00137 } 00138 CKernel::remove_rhs(); 00139 00140 num_rhs=0; 00141 } 00142 00143 //Adapted from CCombinedKernel 00144 void CProductKernel::remove_lhs_and_rhs() 00145 { 00146 for (index_t k_idx=0; k_idx<get_num_subkernels(); k_idx++) 00147 { 00148 CKernel* k=get_kernel(k_idx); 00149 if (k->get_kernel_type() != K_CUSTOM) 00150 k->remove_lhs_and_rhs(); 00151 SG_UNREF(k); 00152 } 00153 00154 CKernel::remove_lhs_and_rhs(); 00155 00156 num_lhs=0; 00157 num_rhs=0; 00158 } 00159 00160 //Adapted from CCombinedKernel 00161 void CProductKernel::cleanup() 00162 { 00163 for (index_t k_idx=0; k_idx<get_num_subkernels(); k_idx++) 00164 { 00165 CKernel* k=get_kernel(k_idx); 00166 k->cleanup(); 00167 SG_UNREF(k); 00168 } 00169 00170 CKernel::cleanup(); 00171 00172 num_lhs=0; 00173 num_rhs=0; 00174 } 00175 00176 //Adapted from CCombinedKernel 00177 void CProductKernel::list_kernels() 00178 { 00179 SG_INFO("BEGIN PRODUCT KERNEL LIST - ") 00180 this->list_kernel(); 00181 00182 for (index_t k_idx=0; k_idx<get_num_subkernels(); k_idx++) 00183 { 00184 CKernel* k=get_kernel(k_idx); 00185 k->list_kernel(); 00186 SG_UNREF(k); 00187 } 00188 SG_INFO("END PRODUCT KERNEL LIST - ") 00189 } 00190 00191 //Adapted from CCombinedKernel 00192 float64_t CProductKernel::compute(int32_t x, int32_t y) 00193 { 00194 float64_t result=1; 00195 for (index_t k_idx=0; k_idx<get_num_subkernels(); k_idx++) 00196 { 00197 CKernel* k=get_kernel(k_idx); 00198 result *= k->get_combined_kernel_weight() * k->kernel(x,y); 00199 SG_UNREF(k); 00200 } 00201 00202 return result; 00203 } 00204 00205 //Adapted from CCombinedKernel 00206 bool CProductKernel::precompute_subkernels() 00207 { 00208 if (get_num_subkernels()==0) 00209 return false; 00210 00211 CDynamicObjectArray* new_kernel_array=new CDynamicObjectArray(); 00212 00213 for (index_t k_idx=0; k_idx<get_num_subkernels(); k_idx++) 00214 { 00215 CKernel* k=get_kernel(k_idx); 00216 new_kernel_array->append_element(new CCustomKernel(k)); 00217 SG_UNREF(k); 00218 } 00219 00220 SG_UNREF(kernel_array); 00221 kernel_array=new_kernel_array; 00222 SG_REF(kernel_array); 00223 00224 return true; 00225 } 00226 00227 void CProductKernel::init() 00228 { 00229 initialized=false; 00230 00231 properties=KP_NONE; 00232 kernel_array=new CDynamicObjectArray(); 00233 SG_REF(kernel_array); 00234 00235 SG_ADD((CSGObject**) &kernel_array, "kernel_array", "Array of kernels", 00236 MS_AVAILABLE); 00237 SG_ADD(&initialized, "initialized", "Whether kernel is ready to be used", 00238 MS_NOT_AVAILABLE); 00239 } 00240 00241 SGMatrix<float64_t> CProductKernel::get_parameter_gradient( 00242 const TParameter* param, index_t index) 00243 { 00244 CKernel* k=get_kernel(0); 00245 SGMatrix<float64_t> temp_kernel=k->get_kernel_matrix(); 00246 SG_UNREF(k); 00247 00248 bool found_derivative=false; 00249 00250 for (index_t g=0; g<temp_kernel.num_rows; g++) 00251 { 00252 for (int h=0; h<temp_kernel.num_cols; h++) 00253 temp_kernel(g,h)=1.0; 00254 } 00255 00256 for (index_t k_idx=0; k_idx<get_num_subkernels(); k_idx++) 00257 { 00258 k=get_kernel(k_idx); 00259 SGMatrix<float64_t> cur_matrix=k->get_kernel_matrix(); 00260 SGMatrix<float64_t> derivative= 00261 k->get_parameter_gradient(param, index); 00262 00263 if (derivative.num_cols*derivative.num_rows > 0) 00264 { 00265 found_derivative=true; 00266 for (index_t g=0; g<derivative.num_rows; g++) 00267 { 00268 for (index_t h=0; h<derivative.num_cols; h++) 00269 temp_kernel(g,h)*=derivative(g,h); 00270 } 00271 } 00272 else 00273 { 00274 for (index_t g=0; g<cur_matrix.num_rows; g++) 00275 { 00276 for (index_t h=0; h<cur_matrix.num_cols; h++) 00277 temp_kernel(g,h)*=cur_matrix(g,h); 00278 } 00279 } 00280 00281 SG_UNREF(k); 00282 } 00283 00284 if (found_derivative) 00285 return temp_kernel; 00286 else 00287 return SGMatrix<float64_t>(); 00288 }