00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
00345
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
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
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 {
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
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 {
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 }