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-2009 Soeren Sonnenburg 00008 * Written (W) 1999-2008 Gunnar Raetsch 00009 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00010 */ 00011 00012 #include <shogun/lib/common.h> 00013 #include <shogun/io/SGIO.h> 00014 #include <shogun/lib/Signal.h> 00015 #include <shogun/base/Parallel.h> 00016 00017 #include <shogun/kernel/Kernel.h> 00018 #include <shogun/kernel/CombinedKernel.h> 00019 #include <shogun/kernel/CustomKernel.h> 00020 #include <shogun/features/CombinedFeatures.h> 00021 #include <string.h> 00022 00023 #ifndef WIN32 00024 #include <pthread.h> 00025 #endif 00026 00027 using namespace shogun; 00028 00029 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00030 struct S_THREAD_PARAM 00031 { 00032 CKernel* kernel; 00033 float64_t* result; 00034 int32_t* vec_idx; 00035 int32_t start; 00036 int32_t end; 00038 float64_t* weights; 00039 int32_t* IDX; 00040 int32_t num_suppvec; 00041 }; 00042 #endif // DOXYGEN_SHOULD_SKIP_THIS 00043 00044 CCombinedKernel::CCombinedKernel(int32_t size, bool asw) 00045 : CKernel(size), append_subkernel_weights(asw) 00046 { 00047 init(); 00048 00049 if (append_subkernel_weights) 00050 SG_INFO( "(subkernel weights are appended)\n") ; 00051 00052 SG_INFO("Combined kernel created (%p)\n", this) ; 00053 } 00054 00055 CCombinedKernel::~CCombinedKernel() 00056 { 00057 SG_FREE(subkernel_weights_buffer); 00058 subkernel_weights_buffer=NULL; 00059 00060 cleanup(); 00061 SG_UNREF(kernel_list); 00062 00063 SG_INFO("Combined kernel deleted (%p).\n", this); 00064 } 00065 00066 bool CCombinedKernel::init(CFeatures* l, CFeatures* r) 00067 { 00068 CKernel::init(l,r); 00069 ASSERT(l->get_feature_class()==C_COMBINED); 00070 ASSERT(r->get_feature_class()==C_COMBINED); 00071 ASSERT(l->get_feature_type()==F_UNKNOWN); 00072 ASSERT(r->get_feature_type()==F_UNKNOWN); 00073 00074 CFeatures* lf=NULL; 00075 CFeatures* rf=NULL; 00076 CKernel* k=NULL; 00077 00078 bool result=true; 00079 00080 CListElement* lfc = NULL; 00081 CListElement* rfc = NULL; 00082 lf=((CCombinedFeatures*) l)->get_first_feature_obj(lfc); 00083 rf=((CCombinedFeatures*) r)->get_first_feature_obj(rfc); 00084 CListElement* current = NULL; 00085 k=get_first_kernel(current); 00086 00087 while ( result && k ) 00088 { 00089 // skip over features - the custom kernel does not need any 00090 if (k->get_kernel_type() != K_CUSTOM) 00091 { 00092 if (!lf || !rf) 00093 { 00094 SG_UNREF(lf); 00095 SG_UNREF(rf); 00096 SG_UNREF(k); 00097 SG_ERROR( "CombinedKernel: Number of features/kernels does not match - bailing out\n"); 00098 } 00099 00100 SG_DEBUG( "Initializing 0x%p - \"%s\"\n", this, k->get_name()); 00101 result=k->init(lf,rf); 00102 SG_UNREF(lf); 00103 SG_UNREF(rf); 00104 00105 lf=((CCombinedFeatures*) l)->get_next_feature_obj(lfc) ; 00106 rf=((CCombinedFeatures*) r)->get_next_feature_obj(rfc) ; 00107 } 00108 else 00109 { 00110 SG_DEBUG( "Initializing 0x%p - \"%s\" (skipping init, this is a CUSTOM kernel)\n", this, k->get_name()); 00111 if (!k->has_features()) 00112 SG_ERROR("No kernel matrix was assigned to this Custom kernel\n"); 00113 if (k->get_num_vec_lhs() != num_lhs) 00114 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()); 00115 if (k->get_num_vec_rhs() != num_rhs) 00116 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()); 00117 } 00118 00119 SG_UNREF(k); 00120 k=get_next_kernel(current) ; 00121 } 00122 00123 if (!result) 00124 { 00125 SG_INFO( "CombinedKernel: Initialising the following kernel failed\n"); 00126 if (k) 00127 k->list_kernel(); 00128 else 00129 SG_INFO( "<NULL>\n"); 00130 return false; 00131 } 00132 00133 if ((lf!=NULL) || (rf!=NULL) || (k!=NULL)) 00134 { 00135 SG_UNREF(lf); 00136 SG_UNREF(rf); 00137 SG_UNREF(k); 00138 SG_ERROR( "CombinedKernel: Number of features/kernels does not match - bailing out\n"); 00139 } 00140 00141 init_normalizer(); 00142 initialized=true; 00143 return true; 00144 } 00145 00146 void CCombinedKernel::remove_lhs() 00147 { 00148 delete_optimization(); 00149 00150 CListElement* current = NULL ; 00151 CKernel* k=get_first_kernel(current); 00152 00153 while (k) 00154 { 00155 if (k->get_kernel_type() != K_CUSTOM) 00156 k->remove_lhs(); 00157 00158 SG_UNREF(k); 00159 k=get_next_kernel(current); 00160 } 00161 CKernel::remove_lhs(); 00162 00163 num_lhs=0; 00164 } 00165 00166 void CCombinedKernel::remove_rhs() 00167 { 00168 CListElement* current = NULL ; 00169 CKernel* k=get_first_kernel(current); 00170 00171 while (k) 00172 { 00173 if (k->get_kernel_type() != K_CUSTOM) 00174 k->remove_rhs(); 00175 SG_UNREF(k); 00176 k=get_next_kernel(current); 00177 } 00178 CKernel::remove_rhs(); 00179 00180 num_rhs=0; 00181 } 00182 00183 void CCombinedKernel::remove_lhs_and_rhs() 00184 { 00185 delete_optimization(); 00186 00187 CListElement* current = NULL ; 00188 CKernel* k=get_first_kernel(current); 00189 00190 while (k) 00191 { 00192 if (k->get_kernel_type() != K_CUSTOM) 00193 k->remove_lhs_and_rhs(); 00194 SG_UNREF(k); 00195 k=get_next_kernel(current); 00196 } 00197 00198 CKernel::remove_lhs_and_rhs(); 00199 00200 num_lhs=0; 00201 num_rhs=0; 00202 } 00203 00204 void CCombinedKernel::cleanup() 00205 { 00206 CListElement* current = NULL ; 00207 CKernel* k=get_first_kernel(current); 00208 00209 while (k) 00210 { 00211 k->cleanup(); 00212 SG_UNREF(k); 00213 k=get_next_kernel(current); 00214 } 00215 00216 delete_optimization(); 00217 00218 CKernel::cleanup(); 00219 00220 num_lhs=0; 00221 num_rhs=0; 00222 } 00223 00224 void CCombinedKernel::list_kernels() 00225 { 00226 CKernel* k; 00227 00228 SG_INFO( "BEGIN COMBINED KERNEL LIST - "); 00229 this->list_kernel(); 00230 00231 CListElement* current = NULL ; 00232 k=get_first_kernel(current); 00233 while (k) 00234 { 00235 k->list_kernel(); 00236 SG_UNREF(k); 00237 k=get_next_kernel(current); 00238 } 00239 SG_INFO( "END COMBINED KERNEL LIST - "); 00240 } 00241 00242 float64_t CCombinedKernel::compute(int32_t x, int32_t y) 00243 { 00244 float64_t result=0; 00245 CListElement* current = NULL ; 00246 CKernel* k=get_first_kernel(current); 00247 while (k) 00248 { 00249 if (k->get_combined_kernel_weight()!=0) 00250 result += k->get_combined_kernel_weight() * k->kernel(x,y); 00251 SG_UNREF(k); 00252 k=get_next_kernel(current); 00253 } 00254 00255 return result; 00256 } 00257 00258 bool CCombinedKernel::init_optimization( 00259 int32_t count, int32_t *IDX, float64_t *weights) 00260 { 00261 SG_DEBUG( "initializing CCombinedKernel optimization\n"); 00262 00263 delete_optimization(); 00264 00265 CListElement* current=NULL; 00266 CKernel *k=get_first_kernel(current); 00267 bool have_non_optimizable=false; 00268 00269 while(k) 00270 { 00271 bool ret=true; 00272 00273 if (k && k->has_property(KP_LINADD)) 00274 ret=k->init_optimization(count, IDX, weights); 00275 else 00276 { 00277 SG_WARNING("non-optimizable kernel 0x%X in kernel-list\n", k); 00278 have_non_optimizable=true; 00279 } 00280 00281 if (!ret) 00282 { 00283 have_non_optimizable=true; 00284 SG_WARNING("init_optimization of kernel 0x%X failed\n", k); 00285 } 00286 00287 SG_UNREF(k); 00288 k=get_next_kernel(current); 00289 } 00290 00291 if (have_non_optimizable) 00292 { 00293 SG_WARNING( "some kernels in the kernel-list are not optimized\n"); 00294 00295 sv_idx=SG_MALLOC(int32_t, count); 00296 sv_weight=SG_MALLOC(float64_t, count); 00297 sv_count=count; 00298 for (int32_t i=0; i<count; i++) 00299 { 00300 sv_idx[i]=IDX[i]; 00301 sv_weight[i]=weights[i]; 00302 } 00303 } 00304 set_is_initialized(true); 00305 00306 return true; 00307 } 00308 00309 bool CCombinedKernel::delete_optimization() 00310 { 00311 CListElement* current = NULL ; 00312 CKernel* k = get_first_kernel(current); 00313 00314 while(k) 00315 { 00316 if (k->has_property(KP_LINADD)) 00317 k->delete_optimization(); 00318 00319 SG_UNREF(k); 00320 k = get_next_kernel(current); 00321 } 00322 00323 SG_FREE(sv_idx); 00324 sv_idx = NULL; 00325 00326 SG_FREE(sv_weight); 00327 sv_weight = NULL; 00328 00329 sv_count = 0; 00330 set_is_initialized(false); 00331 00332 return true; 00333 } 00334 00335 void CCombinedKernel::compute_batch( 00336 int32_t num_vec, int32_t* vec_idx, float64_t* result, int32_t num_suppvec, 00337 int32_t* IDX, float64_t* weights, float64_t factor) 00338 { 00339 ASSERT(num_vec<=get_num_vec_rhs()) 00340 ASSERT(num_vec>0); 00341 ASSERT(vec_idx); 00342 ASSERT(result); 00343 00344 //we have to do the optimization business ourselves but lets 00345 //make sure we start cleanly 00346 delete_optimization(); 00347 00348 CListElement* current = NULL ; 00349 CKernel * k = get_first_kernel(current) ; 00350 00351 while(k) 00352 { 00353 if (k && k->has_property(KP_BATCHEVALUATION)) 00354 { 00355 if (k->get_combined_kernel_weight()!=0) 00356 k->compute_batch(num_vec, vec_idx, result, num_suppvec, IDX, weights, k->get_combined_kernel_weight()); 00357 } 00358 else 00359 emulate_compute_batch(k, num_vec, vec_idx, result, num_suppvec, IDX, weights); 00360 00361 SG_UNREF(k); 00362 k = get_next_kernel(current); 00363 } 00364 00365 //clean up 00366 delete_optimization(); 00367 } 00368 00369 void* CCombinedKernel::compute_optimized_kernel_helper(void* p) 00370 { 00371 S_THREAD_PARAM* params= (S_THREAD_PARAM*) p; 00372 int32_t* vec_idx=params->vec_idx; 00373 CKernel* k=params->kernel; 00374 float64_t* result=params->result; 00375 00376 for (int32_t i=params->start; i<params->end; i++) 00377 result[i] += k->get_combined_kernel_weight()*k->compute_optimized(vec_idx[i]); 00378 00379 return NULL; 00380 } 00381 00382 void* CCombinedKernel::compute_kernel_helper(void* p) 00383 { 00384 S_THREAD_PARAM* params= (S_THREAD_PARAM*) p; 00385 int32_t* vec_idx=params->vec_idx; 00386 CKernel* k=params->kernel; 00387 float64_t* result=params->result; 00388 float64_t* weights=params->weights; 00389 int32_t* IDX=params->IDX; 00390 int32_t num_suppvec=params->num_suppvec; 00391 00392 for (int32_t i=params->start; i<params->end; i++) 00393 { 00394 float64_t sub_result=0; 00395 for (int32_t j=0; j<num_suppvec; j++) 00396 sub_result += weights[j] * k->kernel(IDX[j], vec_idx[i]); 00397 00398 result[i] += k->get_combined_kernel_weight()*sub_result; 00399 } 00400 00401 return NULL; 00402 } 00403 00404 void CCombinedKernel::emulate_compute_batch( 00405 CKernel* k, int32_t num_vec, int32_t* vec_idx, float64_t* result, 00406 int32_t num_suppvec, int32_t* IDX, float64_t* weights) 00407 { 00408 ASSERT(k); 00409 ASSERT(result); 00410 00411 if (k->has_property(KP_LINADD)) 00412 { 00413 if (k->get_combined_kernel_weight()!=0) 00414 { 00415 k->init_optimization(num_suppvec, IDX, weights); 00416 00417 int32_t num_threads=parallel->get_num_threads(); 00418 ASSERT(num_threads>0); 00419 00420 if (num_threads < 2) 00421 { 00422 S_THREAD_PARAM params; 00423 params.kernel=k; 00424 params.result=result; 00425 params.start=0; 00426 params.end=num_vec; 00427 params.vec_idx = vec_idx; 00428 compute_optimized_kernel_helper((void*) ¶ms); 00429 } 00430 #ifdef HAVE_PTHREAD 00431 else 00432 { 00433 pthread_t* threads = SG_MALLOC(pthread_t, num_threads-1); 00434 S_THREAD_PARAM* params = SG_MALLOC(S_THREAD_PARAM, num_threads); 00435 int32_t step= num_vec/num_threads; 00436 00437 int32_t t; 00438 00439 for (t=0; t<num_threads-1; t++) 00440 { 00441 params[t].kernel = k; 00442 params[t].result = result; 00443 params[t].start = t*step; 00444 params[t].end = (t+1)*step; 00445 params[t].vec_idx = vec_idx; 00446 pthread_create(&threads[t], NULL, CCombinedKernel::compute_optimized_kernel_helper, (void*)¶ms[t]); 00447 } 00448 00449 params[t].kernel = k; 00450 params[t].result = result; 00451 params[t].start = t*step; 00452 params[t].end = num_vec; 00453 params[t].vec_idx = vec_idx; 00454 compute_optimized_kernel_helper((void*) ¶ms[t]); 00455 00456 for (t=0; t<num_threads-1; t++) 00457 pthread_join(threads[t], NULL); 00458 00459 SG_FREE(params); 00460 SG_FREE(threads); 00461 } 00462 #endif /* HAVE_PTHREAD */ 00463 00464 k->delete_optimization(); 00465 } 00466 } 00467 else 00468 { 00469 ASSERT(IDX!=NULL || num_suppvec==0); 00470 ASSERT(weights!=NULL || num_suppvec==0); 00471 00472 if (k->get_combined_kernel_weight()!=0) 00473 { // compute the usual way for any non-optimized kernel 00474 int32_t num_threads=parallel->get_num_threads(); 00475 ASSERT(num_threads>0); 00476 00477 if (num_threads < 2) 00478 { 00479 S_THREAD_PARAM params; 00480 params.kernel=k; 00481 params.result=result; 00482 params.start=0; 00483 params.end=num_vec; 00484 params.vec_idx = vec_idx; 00485 params.IDX = IDX; 00486 params.weights = weights; 00487 params.num_suppvec = num_suppvec; 00488 compute_kernel_helper((void*) ¶ms); 00489 } 00490 #ifdef HAVE_PTHREAD 00491 else 00492 { 00493 pthread_t* threads = SG_MALLOC(pthread_t, num_threads-1); 00494 S_THREAD_PARAM* params = SG_MALLOC(S_THREAD_PARAM, num_threads); 00495 int32_t step= num_vec/num_threads; 00496 00497 int32_t t; 00498 00499 for (t=0; t<num_threads-1; t++) 00500 { 00501 params[t].kernel = k; 00502 params[t].result = result; 00503 params[t].start = t*step; 00504 params[t].end = (t+1)*step; 00505 params[t].vec_idx = vec_idx; 00506 params[t].IDX = IDX; 00507 params[t].weights = weights; 00508 params[t].num_suppvec = num_suppvec; 00509 pthread_create(&threads[t], NULL, CCombinedKernel::compute_kernel_helper, (void*)¶ms[t]); 00510 } 00511 00512 params[t].kernel = k; 00513 params[t].result = result; 00514 params[t].start = t*step; 00515 params[t].end = num_vec; 00516 params[t].vec_idx = vec_idx; 00517 params[t].IDX = IDX; 00518 params[t].weights = weights; 00519 params[t].num_suppvec = num_suppvec; 00520 compute_kernel_helper(¶ms[t]); 00521 00522 for (t=0; t<num_threads-1; t++) 00523 pthread_join(threads[t], NULL); 00524 00525 SG_FREE(params); 00526 SG_FREE(threads); 00527 } 00528 #endif /* HAVE_PTHREAD */ 00529 } 00530 } 00531 } 00532 00533 float64_t CCombinedKernel::compute_optimized(int32_t idx) 00534 { 00535 if (!get_is_initialized()) 00536 { 00537 SG_ERROR("CCombinedKernel optimization not initialized\n"); 00538 return 0; 00539 } 00540 00541 float64_t result=0; 00542 00543 CListElement* current=NULL; 00544 CKernel *k=get_first_kernel(current); 00545 while (k) 00546 { 00547 if (k->has_property(KP_LINADD) && 00548 k->get_is_initialized()) 00549 { 00550 if (k->get_combined_kernel_weight()!=0) 00551 { 00552 result += 00553 k->get_combined_kernel_weight()*k->compute_optimized(idx); 00554 } 00555 } 00556 else 00557 { 00558 ASSERT(sv_idx!=NULL || sv_count==0); 00559 ASSERT(sv_weight!=NULL || sv_count==0); 00560 00561 if (k->get_combined_kernel_weight()!=0) 00562 { // compute the usual way for any non-optimized kernel 00563 float64_t sub_result=0; 00564 for (int32_t j=0; j<sv_count; j++) 00565 sub_result += sv_weight[j] * k->kernel(sv_idx[j], idx); 00566 00567 result += k->get_combined_kernel_weight()*sub_result; 00568 } 00569 } 00570 00571 SG_UNREF(k); 00572 k=get_next_kernel(current); 00573 } 00574 00575 return result; 00576 } 00577 00578 void CCombinedKernel::add_to_normal(int32_t idx, float64_t weight) 00579 { 00580 CListElement* current = NULL ; 00581 CKernel* k = get_first_kernel(current); 00582 00583 while(k) 00584 { 00585 k->add_to_normal(idx, weight); 00586 SG_UNREF(k); 00587 k = get_next_kernel(current); 00588 } 00589 set_is_initialized(true) ; 00590 } 00591 00592 void CCombinedKernel::clear_normal() 00593 { 00594 CListElement* current = NULL ; 00595 CKernel* k = get_first_kernel(current); 00596 00597 while(k) 00598 { 00599 k->clear_normal() ; 00600 SG_UNREF(k); 00601 k = get_next_kernel(current); 00602 } 00603 set_is_initialized(true) ; 00604 } 00605 00606 void CCombinedKernel::compute_by_subkernel( 00607 int32_t idx, float64_t * subkernel_contrib) 00608 { 00609 if (append_subkernel_weights) 00610 { 00611 int32_t i=0 ; 00612 CListElement* current = NULL ; 00613 CKernel* k = get_first_kernel(current); 00614 while(k) 00615 { 00616 int32_t num = -1 ; 00617 k->get_subkernel_weights(num); 00618 if (num>1) 00619 k->compute_by_subkernel(idx, &subkernel_contrib[i]) ; 00620 else 00621 subkernel_contrib[i] += k->get_combined_kernel_weight() * k->compute_optimized(idx) ; 00622 00623 SG_UNREF(k); 00624 k = get_next_kernel(current); 00625 i += num ; 00626 } 00627 } 00628 else 00629 { 00630 int32_t i=0 ; 00631 CListElement* current = NULL ; 00632 CKernel* k = get_first_kernel(current); 00633 while(k) 00634 { 00635 if (k->get_combined_kernel_weight()!=0) 00636 subkernel_contrib[i] += k->get_combined_kernel_weight() * k->compute_optimized(idx) ; 00637 00638 SG_UNREF(k); 00639 k = get_next_kernel(current); 00640 i++ ; 00641 } 00642 } 00643 } 00644 00645 const float64_t* CCombinedKernel::get_subkernel_weights(int32_t& num_weights) 00646 { 00647 SG_DEBUG("entering CCombinedKernel::get_subkernel_weights()\n"); 00648 00649 num_weights = get_num_subkernels() ; 00650 SG_FREE(subkernel_weights_buffer); 00651 subkernel_weights_buffer = SG_MALLOC(float64_t, num_weights); 00652 00653 if (append_subkernel_weights) 00654 { 00655 SG_DEBUG("appending kernel weights\n"); 00656 00657 int32_t i=0 ; 00658 CListElement* current = NULL ; 00659 CKernel* k = get_first_kernel(current); 00660 while(k) 00661 { 00662 int32_t num = -1 ; 00663 const float64_t *w = k->get_subkernel_weights(num); 00664 ASSERT(num==k->get_num_subkernels()); 00665 for (int32_t j=0; j<num; j++) 00666 subkernel_weights_buffer[i+j]=w[j] ; 00667 00668 SG_UNREF(k); 00669 k = get_next_kernel(current); 00670 i += num ; 00671 } 00672 } 00673 else 00674 { 00675 SG_DEBUG("not appending kernel weights\n"); 00676 int32_t i=0 ; 00677 CListElement* current = NULL ; 00678 CKernel* k = get_first_kernel(current); 00679 while(k) 00680 { 00681 subkernel_weights_buffer[i] = k->get_combined_kernel_weight(); 00682 00683 SG_UNREF(k); 00684 k = get_next_kernel(current); 00685 i++ ; 00686 } 00687 } 00688 00689 SG_DEBUG("leaving CCombinedKernel::get_subkernel_weights()\n"); 00690 return subkernel_weights_buffer ; 00691 } 00692 00693 SGVector<float64_t> CCombinedKernel::get_subkernel_weights() 00694 { 00695 int32_t num=0; 00696 const float64_t* w=get_subkernel_weights(num); 00697 00698 float64_t* weights = SG_MALLOC(float64_t, num); 00699 for (int32_t i=0; i<num; i++) 00700 weights[i] = w[i]; 00701 00702 return SGVector<float64_t>(weights, num); 00703 } 00704 00705 void CCombinedKernel::set_subkernel_weights(SGVector<float64_t> weights) 00706 { 00707 if (append_subkernel_weights) 00708 { 00709 int32_t i=0 ; 00710 CListElement* current = NULL ; 00711 CKernel* k = get_first_kernel(current); 00712 while(k) 00713 { 00714 int32_t num = k->get_num_subkernels() ; 00715 ASSERT(i<weights.vlen); 00716 k->set_subkernel_weights(SGVector<float64_t>(&weights.vector[i],num, false)); 00717 00718 SG_UNREF(k); 00719 k = get_next_kernel(current); 00720 i += num ; 00721 } 00722 } 00723 else 00724 { 00725 int32_t i=0 ; 00726 CListElement* current = NULL ; 00727 CKernel* k = get_first_kernel(current); 00728 while(k) 00729 { 00730 ASSERT(i<weights.vlen); 00731 k->set_combined_kernel_weight(weights.vector[i]); 00732 00733 SG_UNREF(k); 00734 k = get_next_kernel(current); 00735 i++ ; 00736 } 00737 } 00738 } 00739 00740 void CCombinedKernel::set_optimization_type(EOptimizationType t) 00741 { 00742 CKernel* k = get_first_kernel(); 00743 00744 while(k) 00745 { 00746 k->set_optimization_type(t); 00747 00748 SG_UNREF(k); 00749 k = get_next_kernel(); 00750 } 00751 00752 CKernel::set_optimization_type(t); 00753 } 00754 00755 bool CCombinedKernel::precompute_subkernels() 00756 { 00757 CKernel* k = get_first_kernel(); 00758 00759 if (!k) 00760 return false; 00761 00762 CList* new_kernel_list = new CList(true); 00763 00764 while(k) 00765 { 00766 new_kernel_list->append_element(new CCustomKernel(k)); 00767 00768 SG_UNREF(k); 00769 k = get_next_kernel(); 00770 } 00771 00772 SG_UNREF(kernel_list); 00773 kernel_list=new_kernel_list; 00774 SG_REF(kernel_list); 00775 00776 return true; 00777 } 00778 00779 void CCombinedKernel::init() 00780 { 00781 sv_count=0; 00782 sv_idx=NULL; 00783 sv_weight=NULL; 00784 subkernel_weights_buffer=NULL; 00785 initialized=false; 00786 00787 properties |= KP_LINADD | KP_KERNCOMBINATION | KP_BATCHEVALUATION; 00788 kernel_list=new CList(true); 00789 SG_REF(kernel_list); 00790 00791 SG_ADD((CSGObject**) &kernel_list, "kernel_list", "List of kernels.", 00792 MS_AVAILABLE); 00793 m_parameters->add_vector(&sv_idx, &sv_count, "sv_idx", 00794 "Support vector index."); 00795 m_parameters->add_vector(&sv_weight, &sv_count, "sv_weight", 00796 "Support vector weights."); 00797 SG_ADD(&append_subkernel_weights, "append_subkernel_weights", 00798 "If subkernel weights are appended.", MS_AVAILABLE); 00799 SG_ADD(&initialized, "initialized", "Whether kernel is ready to be used.", 00800 MS_NOT_AVAILABLE); 00801 } 00802 00803 SGMatrix<float64_t> CCombinedKernel::get_parameter_gradient(TParameter* param, 00804 CSGObject* obj, index_t index) 00805 { 00806 SGMatrix<float64_t> result(0,0); 00807 00808 if (strcmp(param->m_name, "combined_kernel_weight") == 0) 00809 { 00810 CListElement* current = NULL ; 00811 CKernel* k = get_first_kernel(current); 00812 00813 if (append_subkernel_weights) 00814 { 00815 while(k) 00816 { 00817 result = k->get_parameter_gradient(param, obj, index); 00818 00819 SG_UNREF(k); 00820 00821 if (result.num_cols*result.num_rows > 0) 00822 return result; 00823 00824 k = get_next_kernel(current); 00825 } 00826 } 00827 00828 else 00829 { 00830 while(k) 00831 { 00832 if(obj == k) 00833 { 00834 result = k->get_kernel_matrix(); 00835 SG_UNREF(k); 00836 return result; 00837 } 00838 00839 SG_UNREF(k); 00840 00841 k = get_next_kernel(current); 00842 } 00843 } 00844 } 00845 00846 else 00847 { 00848 CListElement* current = NULL ; 00849 CKernel* k = get_first_kernel(current); 00850 float64_t coeff; 00851 while(k) 00852 { 00853 SGMatrix<float64_t> derivative = 00854 k->get_parameter_gradient(param, obj, index); 00855 00856 coeff = 1.0; 00857 00858 if (!append_subkernel_weights) 00859 coeff = k->get_combined_kernel_weight(); 00860 00861 00862 for (index_t g = 0; g < derivative.num_rows; g++) 00863 { 00864 for (index_t h = 0; h < derivative.num_cols; h++) 00865 derivative(g,h) *= coeff; 00866 } 00867 00868 if (derivative.num_cols*derivative.num_rows > 0) 00869 { 00870 if (result.num_cols == 0 && result.num_rows == 0) 00871 result = derivative; 00872 00873 else 00874 { 00875 for (index_t g = 0; g < derivative.num_rows; g++) 00876 { 00877 for (index_t h = 0; h < derivative.num_cols; h++) 00878 result(g,h) += derivative(g,h); 00879 } 00880 } 00881 } 00882 00883 SG_UNREF(k); 00884 k = get_next_kernel(current); 00885 } 00886 } 00887 00888 return result; 00889 }