CombinedKernel.cpp

Go to the documentation of this file.
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*) &params);
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*)&params[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*) &params[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*) &params);
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*)&params[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(&params[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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation