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