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