SVRLight.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  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
00009  */
00010 
00011 #include <shogun/lib/config.h>
00012 
00013 #ifdef USE_SVMLIGHT
00014 
00015 #include <shogun/io/SGIO.h>
00016 #include <shogun/mathematics/lapack.h>
00017 #include <shogun/lib/Signal.h>
00018 #include <shogun/mathematics/Math.h>
00019 #include <shogun/regression/svr/SVRLight.h>
00020 #include <shogun/machine/KernelMachine.h>
00021 #include <shogun/kernel/CombinedKernel.h>
00022 
00023 #include <unistd.h>
00024 
00025 #ifdef USE_CPLEX
00026 extern "C" {
00027 #include <ilcplex/cplex.h>
00028 }
00029 #endif
00030 
00031 #include <shogun/base/Parallel.h>
00032 
00033 #ifdef HAVE_PTHREAD
00034 #include <pthread.h>
00035 #endif
00036 
00037 using namespace shogun;
00038 
00039 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00040 struct S_THREAD_PARAM
00041 {
00042     float64_t* lin;
00043     int32_t start, end;
00044     int32_t* active2dnum;
00045     int32_t* docs;
00046     CKernel* kernel;
00047     int32_t num_vectors;
00048 };
00049 #endif // DOXYGEN_SHOULD_SKIP_THIS
00050 
00051 CSVRLight::CSVRLight(float64_t C, float64_t eps, CKernel* k, CLabels* lab)
00052 : CSVMLight(C, k, lab)
00053 {
00054     set_tube_epsilon(eps);
00055 }
00056 
00057 CSVRLight::CSVRLight()
00058 : CSVMLight()
00059 {
00060 }
00061 
00062 bool CSVRLight::train_machine(CFeatures* data)
00063 {
00064     //certain setup params
00065     verbosity=1;
00066     init_margin=0.15;
00067     init_iter=500;
00068     precision_violations=0;
00069     opt_precision=DEF_PRECISION;
00070 
00071     strcpy (learn_parm->predfile, "");
00072     learn_parm->biased_hyperplane=1;
00073     learn_parm->sharedslack=0;
00074     learn_parm->remove_inconsistent=0;
00075     learn_parm->skip_final_opt_check=1;
00076     learn_parm->svm_maxqpsize=get_qpsize();
00077     learn_parm->svm_newvarsinqp=learn_parm->svm_maxqpsize-1;
00078     learn_parm->maxiter=100000;
00079     learn_parm->svm_iter_to_shrink=100;
00080     learn_parm->svm_c=get_C1();
00081     learn_parm->transduction_posratio=0.33;
00082     learn_parm->svm_costratio=get_C2()/get_C1();
00083     learn_parm->svm_costratio_unlab=1.0;
00084     learn_parm->svm_unlabbound=1E-5;
00085     learn_parm->epsilon_crit=epsilon; // GU: better decrease it ... ??
00086     learn_parm->epsilon_a=1E-15;
00087     learn_parm->compute_loo=0;
00088     learn_parm->rho=1.0;
00089     learn_parm->xa_depth=0;
00090 
00091     if (!kernel)
00092     {
00093         SG_ERROR( "SVR_light can not proceed without kernel!\n");
00094         return false ;
00095     }
00096 
00097     if (!labels)
00098     {
00099         SG_ERROR( "SVR_light can not proceed without labels!\n");
00100         return false;
00101     }
00102 
00103     if (data)
00104     {
00105         if (labels->get_num_labels() != data->get_num_vectors())
00106             SG_ERROR("Number of training vectors does not match number of labels\n");
00107         kernel->init(data, data);
00108     }
00109 
00110     if (kernel->has_property(KP_LINADD) && get_linadd_enabled())
00111         kernel->clear_normal();
00112 
00113     // output some info
00114     SG_DEBUG( "qpsize = %i\n", learn_parm->svm_maxqpsize) ;
00115     SG_DEBUG( "epsilon = %1.1e\n", learn_parm->epsilon_crit) ;
00116     SG_DEBUG( "kernel->has_property(KP_LINADD) = %i\n", kernel->has_property(KP_LINADD)) ;
00117     SG_DEBUG( "kernel->has_property(KP_KERNCOMBINATION) = %i\n", kernel->has_property(KP_KERNCOMBINATION)) ;
00118     SG_DEBUG( "get_linadd_enabled() = %i\n", get_linadd_enabled()) ;
00119     SG_DEBUG( "kernel->get_num_subkernels() = %i\n", kernel->get_num_subkernels()) ;
00120 
00121     use_kernel_cache = !((kernel->get_kernel_type() == K_CUSTOM) ||
00122                          (get_linadd_enabled() && kernel->has_property(KP_LINADD)));
00123 
00124     SG_DEBUG( "use_kernel_cache = %i\n", use_kernel_cache) ;
00125 
00126     // train the svm
00127     svr_learn();
00128 
00129     // brain damaged svm light work around
00130     create_new_model(model->sv_num-1);
00131     set_bias(-model->b);
00132     for (int32_t i=0; i<model->sv_num-1; i++)
00133     {
00134         set_alpha(i, model->alpha[i+1]);
00135         set_support_vector(i, model->supvec[i+1]);
00136     }
00137 
00138     if (kernel->has_property(KP_LINADD) && get_linadd_enabled())
00139         kernel->clear_normal() ;
00140 
00141     return true ;
00142 }
00143 
00144 void CSVRLight::svr_learn()
00145 {
00146     int32_t *inconsistent, i, j;
00147     int32_t upsupvecnum;
00148     float64_t maxdiff, *lin, *c, *a;
00149     int32_t iterations;
00150     float64_t *xi_fullset; /* buffer for storing xi on full sample in loo */
00151     float64_t *a_fullset;  /* buffer for storing alpha on full sample in loo */
00152     TIMING timing_profile;
00153     SHRINK_STATE shrink_state;
00154     int32_t* label;
00155     int32_t* docs;
00156 
00157     ASSERT(labels);
00158     int32_t totdoc=labels->get_num_labels();
00159     num_vectors=totdoc;
00160 
00161     // set up regression problem in standard form
00162     docs=SG_MALLOC(int32_t, 2*totdoc);
00163     label=SG_MALLOC(int32_t, 2*totdoc);
00164     c = SG_MALLOC(float64_t, 2*totdoc);
00165 
00166   for(i=0;i<totdoc;i++) {
00167       docs[i]=i;
00168       j=2*totdoc-1-i;
00169       label[i]=+1;
00170       c[i]=labels->get_label(i);
00171       docs[j]=j;
00172       label[j]=-1;
00173       c[j]=labels->get_label(i);
00174   }
00175   totdoc*=2;
00176 
00177   //prepare kernel cache for regression (i.e. cachelines are twice of current size)
00178   kernel->resize_kernel_cache( kernel->get_cache_size(), true);
00179 
00180   if (kernel->get_kernel_type() == K_COMBINED)
00181   {
00182       CCombinedKernel* k      = (CCombinedKernel*) kernel;
00183       CKernel* kn = k->get_first_kernel();
00184 
00185       while (kn)
00186       {
00187           kn->resize_kernel_cache( kernel->get_cache_size(), true);
00188           SG_UNREF(kn);
00189           kn = k->get_next_kernel();
00190       }
00191   }
00192 
00193   timing_profile.time_kernel=0;
00194   timing_profile.time_opti=0;
00195   timing_profile.time_shrink=0;
00196   timing_profile.time_update=0;
00197   timing_profile.time_model=0;
00198   timing_profile.time_check=0;
00199   timing_profile.time_select=0;
00200 
00201     SG_FREE(W);
00202     W=NULL;
00203 
00204     if (kernel->has_property(KP_KERNCOMBINATION) && callback)
00205     {
00206         W = SG_MALLOC(float64_t, totdoc*kernel->get_num_subkernels());
00207         for (i=0; i<totdoc*kernel->get_num_subkernels(); i++)
00208             W[i]=0;
00209     }
00210 
00211     /* make sure -n value is reasonable */
00212     if((learn_parm->svm_newvarsinqp < 2)
00213             || (learn_parm->svm_newvarsinqp > learn_parm->svm_maxqpsize)) {
00214         learn_parm->svm_newvarsinqp=learn_parm->svm_maxqpsize;
00215     }
00216 
00217     init_shrink_state(&shrink_state,totdoc,(int32_t)MAXSHRINK);
00218 
00219     inconsistent = SG_MALLOC(int32_t, totdoc);
00220     a = SG_MALLOC(float64_t, totdoc);
00221     a_fullset = SG_MALLOC(float64_t, totdoc);
00222     xi_fullset = SG_MALLOC(float64_t, totdoc);
00223     lin = SG_MALLOC(float64_t, totdoc);
00224     learn_parm->svm_cost = SG_MALLOC(float64_t, totdoc);
00225     if (m_linear_term.vlen>0)
00226         learn_parm->eps=get_linear_term_array();
00227     else
00228     {
00229         learn_parm->eps=SG_MALLOC(float64_t, totdoc);      /* equivalent regression epsilon for classification */
00230         CMath::fill_vector(learn_parm->eps, totdoc, tube_epsilon);
00231     }
00232 
00233     SG_FREE(model->supvec);
00234     SG_FREE(model->alpha);
00235     SG_FREE(model->index);
00236     model->supvec = SG_MALLOC(int32_t, totdoc+2);
00237     model->alpha = SG_MALLOC(float64_t, totdoc+2);
00238     model->index = SG_MALLOC(int32_t, totdoc+2);
00239 
00240     model->at_upper_bound=0;
00241     model->b=0;
00242     model->supvec[0]=0;  /* element 0 reserved and empty for now */
00243     model->alpha[0]=0;
00244     model->totdoc=totdoc;
00245 
00246     model->kernel=kernel;
00247 
00248     model->sv_num=1;
00249     model->loo_error=-1;
00250     model->loo_recall=-1;
00251     model->loo_precision=-1;
00252     model->xa_error=-1;
00253     model->xa_recall=-1;
00254     model->xa_precision=-1;
00255 
00256   for(i=0;i<totdoc;i++) {    /* various inits */
00257     inconsistent[i]=0;
00258     a[i]=0;
00259     lin[i]=0;
00260 
00261         if(label[i] > 0) {
00262             learn_parm->svm_cost[i]=learn_parm->svm_c*learn_parm->svm_costratio*
00263                 fabs((float64_t)label[i]);
00264         }
00265         else if(label[i] < 0) {
00266             learn_parm->svm_cost[i]=learn_parm->svm_c*fabs((float64_t)label[i]);
00267         }
00268         else
00269             ASSERT(false);
00270     }
00271 
00272     if(verbosity==1) {
00273         SG_DEBUG( "Optimizing...\n");
00274     }
00275 
00276     /* train the svm */
00277         SG_DEBUG( "num_train: %d\n", totdoc);
00278   iterations=optimize_to_convergence(docs,label,totdoc,
00279                      &shrink_state,inconsistent,a,lin,
00280                      c,&timing_profile,
00281                      &maxdiff,(int32_t)-1,
00282                      (int32_t)1);
00283 
00284 
00285     if(verbosity>=1) {
00286         SG_DONE();
00287         SG_INFO("(%ld iterations)\n",iterations);
00288         SG_INFO( "Optimization finished (maxdiff=%.8f).\n",maxdiff);
00289         SG_INFO( "obj = %.16f, rho = %.16f\n",get_objective(),model->b);
00290 
00291         upsupvecnum=0;
00292 
00293         SG_DEBUG( "num sv: %d\n", model->sv_num);
00294         for(i=1;i<model->sv_num;i++)
00295         {
00296             if(fabs(model->alpha[i]) >=
00297                     (learn_parm->svm_cost[model->supvec[i]]-
00298                      learn_parm->epsilon_a))
00299                 upsupvecnum++;
00300         }
00301         SG_INFO( "Number of SV: %ld (including %ld at upper bound)\n",
00302                 model->sv_num-1,upsupvecnum);
00303     }
00304 
00305   /* this makes sure the model we return does not contain pointers to the
00306      temporary documents */
00307   for(i=1;i<model->sv_num;i++) {
00308     j=model->supvec[i];
00309     if(j >= (totdoc/2)) {
00310       j=totdoc-j-1;
00311     }
00312     model->supvec[i]=j;
00313   }
00314 
00315   shrink_state_cleanup(&shrink_state);
00316     SG_FREE(label);
00317     SG_FREE(inconsistent);
00318     SG_FREE(c);
00319     SG_FREE(a);
00320     SG_FREE(a_fullset);
00321     SG_FREE(xi_fullset);
00322     SG_FREE(lin);
00323     SG_FREE(learn_parm->svm_cost);
00324     SG_FREE(docs);
00325 }
00326 
00327 float64_t CSVRLight::compute_objective_function(
00328     float64_t *a, float64_t *lin, float64_t *c, float64_t* eps, int32_t *label,
00329     int32_t totdoc)
00330 {
00331   /* calculate value of objective function */
00332   float64_t criterion=0;
00333 
00334   for(int32_t i=0;i<totdoc;i++)
00335       criterion+=(eps[i]-(float64_t)label[i]*c[i])*a[i]+0.5*a[i]*label[i]*lin[i];
00336 
00337   /* float64_t check=0;
00338   for(int32_t i=0;i<totdoc;i++)
00339   {
00340       check+=a[i]*eps-a[i]*label[i]*c[i];
00341       for(int32_t j=0;j<totdoc;j++)
00342           check+= 0.5*a[i]*label[i]*a[j]*label[j]*compute_kernel(i,j);
00343 
00344   }
00345 
00346   SG_INFO("REGRESSION OBJECTIVE %f vs. CHECK %f (diff %f)\n", criterion, check, criterion-check); */
00347 
00348   return(criterion);
00349 }
00350 
00351 void* CSVRLight::update_linear_component_linadd_helper(void *params_)
00352 {
00353     S_THREAD_PARAM * params = (S_THREAD_PARAM*) params_ ;
00354 
00355     int32_t jj=0, j=0 ;
00356 
00357     for(jj=params->start;(jj<params->end) && (j=params->active2dnum[jj])>=0;jj++)
00358         params->lin[j]+=params->kernel->compute_optimized(CSVRLight::regression_fix_index2(params->docs[j], params->num_vectors));
00359 
00360     return NULL ;
00361 }
00362 
00363 
00364 void CSVRLight::update_linear_component(
00365     int32_t* docs, int32_t* label, int32_t *active2dnum, float64_t *a,
00366     float64_t *a_old, int32_t *working2dnum, int32_t totdoc, float64_t *lin,
00367     float64_t *aicache, float64_t* c)
00368      /* keep track of the linear component */
00369      /* lin of the gradient etc. by updating */
00370      /* based on the change of the variables */
00371      /* in the current working set */
00372 {
00373     register int32_t i=0,ii=0,j=0,jj=0;
00374 
00375     if (kernel->has_property(KP_LINADD) && get_linadd_enabled())
00376     {
00377         if (callback)
00378         {
00379             update_linear_component_mkl_linadd(docs, label, active2dnum, a, a_old, working2dnum,
00380                                                totdoc,  lin, aicache, c) ;
00381         }
00382         else
00383         {
00384             kernel->clear_normal();
00385 
00386             int32_t num_working=0;
00387             for(ii=0;(i=working2dnum[ii])>=0;ii++) {
00388                 if(a[i] != a_old[i]) {
00389                     kernel->add_to_normal(regression_fix_index(docs[i]), (a[i]-a_old[i])*(float64_t)label[i]);
00390                     num_working++;
00391                 }
00392             }
00393 
00394             if (num_working>0)
00395             {
00396                 if (parallel->get_num_threads() < 2)
00397                 {
00398                     for(jj=0;(j=active2dnum[jj])>=0;jj++) {
00399                         lin[j]+=kernel->compute_optimized(regression_fix_index(docs[j]));
00400                     }
00401                 }
00402 #ifdef HAVE_PTHREAD
00403                 else
00404                 {
00405                     int32_t num_elem = 0 ;
00406                     for(jj=0;(j=active2dnum[jj])>=0;jj++) num_elem++ ;
00407 
00408                     pthread_t* threads = SG_MALLOC(pthread_t, parallel->get_num_threads()-1);
00409                     S_THREAD_PARAM* params = SG_MALLOC(S_THREAD_PARAM, parallel->get_num_threads()-1);
00410                     int32_t start = 0 ;
00411                     int32_t step = num_elem/parallel->get_num_threads() ;
00412                     int32_t end = step ;
00413 
00414                     for (int32_t t=0; t<parallel->get_num_threads()-1; t++)
00415                     {
00416                         params[t].kernel = kernel ;
00417                         params[t].lin = lin ;
00418                         params[t].docs = docs ;
00419                         params[t].active2dnum=active2dnum ;
00420                         params[t].start = start ;
00421                         params[t].end = end ;
00422                         params[t].num_vectors=num_vectors ;
00423 
00424                         start=end ;
00425                         end+=step ;
00426                         pthread_create(&threads[t], NULL, update_linear_component_linadd_helper, (void*)&params[t]) ;
00427                     }
00428 
00429                     for(jj=params[parallel->get_num_threads()-2].end;(j=active2dnum[jj])>=0;jj++) {
00430                         lin[j]+=kernel->compute_optimized(regression_fix_index(docs[j]));
00431                     }
00432                     void* ret;
00433                     for (int32_t t=0; t<parallel->get_num_threads()-1; t++)
00434                         pthread_join(threads[t], &ret) ;
00435 
00436                     SG_FREE(params);
00437                     SG_FREE(threads);
00438                 }
00439 #endif
00440             }
00441         }
00442     }
00443     else
00444     {
00445         if (callback)
00446         {
00447             update_linear_component_mkl(docs, label, active2dnum,
00448                     a, a_old, working2dnum, totdoc, lin, aicache, c) ;
00449         }
00450         else {
00451             for(jj=0;(i=working2dnum[jj])>=0;jj++) {
00452                 if(a[i] != a_old[i]) {
00453                     kernel->get_kernel_row(i,active2dnum,aicache);
00454                     for(ii=0;(j=active2dnum[ii])>=0;ii++)
00455                         lin[j]+=(a[i]-a_old[i])*aicache[j]*(float64_t)label[i];
00456                 }
00457             }
00458         }
00459     }
00460 }
00461 
00462 void CSVRLight::update_linear_component_mkl(
00463     int32_t* docs, int32_t* label, int32_t *active2dnum, float64_t *a,
00464     float64_t *a_old, int32_t *working2dnum, int32_t totdoc, float64_t *lin,
00465     float64_t *aicache, float64_t* c)
00466 {
00467     int32_t num         = totdoc;
00468     int32_t num_weights = -1;
00469     int32_t num_kernels = kernel->get_num_subkernels() ;
00470     const float64_t* old_beta  = kernel->get_subkernel_weights(num_weights);
00471 
00472     ASSERT(num_weights==num_kernels);
00473 
00474     if ((kernel->get_kernel_type()==K_COMBINED) &&
00475              (!((CCombinedKernel*)kernel)->get_append_subkernel_weights()))// for combined kernel
00476     {
00477         CCombinedKernel* k      = (CCombinedKernel*) kernel;
00478         CKernel* kn = k->get_first_kernel() ;
00479         int32_t n = 0, i, j ;
00480 
00481         while (kn!=NULL)
00482         {
00483             for(i=0;i<num;i++)
00484             {
00485                 if(a[i] != a_old[i])
00486                 {
00487                     kn->get_kernel_row(i,NULL,aicache, true);
00488                     for(j=0;j<num;j++)
00489                         W[j*num_kernels+n]+=(a[i]-a_old[i])*aicache[regression_fix_index(j)]*(float64_t)label[i];
00490                 }
00491             }
00492             SG_UNREF(kn);
00493             kn = k->get_next_kernel();
00494             n++ ;
00495         }
00496     }
00497     else // hope the kernel is fast ...
00498     {
00499         float64_t* w_backup = SG_MALLOC(float64_t, num_kernels);
00500         float64_t* w1 = SG_MALLOC(float64_t, num_kernels);
00501 
00502         // backup and set to zero
00503         for (int32_t i=0; i<num_kernels; i++)
00504         {
00505             w_backup[i] = old_beta[i] ;
00506             w1[i]=0.0 ;
00507         }
00508         for (int32_t n=0; n<num_kernels; n++)
00509         {
00510             w1[n]=1.0 ;
00511             kernel->set_subkernel_weights(w1, num_weights) ;
00512 
00513             for(int32_t i=0;i<num;i++)
00514             {
00515                 if(a[i] != a_old[i])
00516                 {
00517                     for(int32_t j=0;j<num;j++)
00518                         W[j*num_kernels+n]+=(a[i]-a_old[i])*compute_kernel(i,j)*(float64_t)label[i];
00519                 }
00520             }
00521             w1[n]=0.0 ;
00522         }
00523 
00524         // restore old weights
00525         kernel->set_subkernel_weights(w_backup,num_weights) ;
00526 
00527         SG_FREE(w_backup);
00528         SG_FREE(w1);
00529     }
00530 
00531     call_mkl_callback(a, label, lin, c, totdoc);
00532 }
00533 
00534 
00535 void CSVRLight::update_linear_component_mkl_linadd(
00536     int32_t* docs, int32_t* label, int32_t *active2dnum, float64_t *a,
00537     float64_t *a_old, int32_t *working2dnum, int32_t totdoc, float64_t *lin,
00538     float64_t *aicache, float64_t* c)
00539 {
00540     // kernel with LP_LINADD property is assumed to have
00541     // compute_by_subkernel functions
00542     int32_t num         = totdoc;
00543     int32_t num_weights = -1;
00544     int32_t num_kernels = kernel->get_num_subkernels() ;
00545     const float64_t* old_beta   = kernel->get_subkernel_weights(num_weights);
00546 
00547     ASSERT(num_weights==num_kernels);
00548 
00549     float64_t* w_backup=SG_MALLOC(float64_t, num_kernels);
00550     float64_t* w1=SG_MALLOC(float64_t, num_kernels);
00551 
00552     // backup and set to one
00553     for (int32_t i=0; i<num_kernels; i++)
00554     {
00555         w_backup[i] = old_beta[i] ;
00556         w1[i]=1.0 ;
00557     }
00558     // set the kernel weights
00559     kernel->set_subkernel_weights(w1, num_weights) ;
00560 
00561     // create normal update (with changed alphas only)
00562     kernel->clear_normal();
00563     for(int32_t ii=0, i=0;(i=working2dnum[ii])>=0;ii++) {
00564         if(a[i] != a_old[i]) {
00565             kernel->add_to_normal(regression_fix_index(docs[i]), (a[i]-a_old[i])*(float64_t)label[i]);
00566         }
00567     }
00568 
00569     // determine contributions of different kernels
00570     for (int32_t i=0; i<num; i++)
00571         kernel->compute_by_subkernel(i,&W[i*num_kernels]) ;
00572 
00573     // restore old weights
00574     kernel->set_subkernel_weights(w_backup,num_weights) ;
00575 
00576     SG_FREE(w_backup);
00577     SG_FREE(w1);
00578 
00579     call_mkl_callback(a, label, lin, c, totdoc);
00580 }
00581 
00582 void CSVRLight::call_mkl_callback(float64_t* a, int32_t* label, float64_t* lin, float64_t* c, int32_t totdoc)
00583 {
00584     int32_t num = totdoc;
00585     int32_t num_kernels = kernel->get_num_subkernels() ;
00586     int nk = (int) num_kernels; // calling external lib
00587     float64_t sumalpha = 0;
00588     float64_t* sumw=SG_MALLOC(float64_t, num_kernels);
00589 
00590     for (int32_t i=0; i<num; i++)
00591         sumalpha-=a[i]*(learn_parm->eps[i]-label[i]*c[i]);
00592 
00593 #ifdef HAVE_LAPACK
00594     double* alphay  = SG_MALLOC(double, num);
00595     for (int32_t i=0; i<num; i++)
00596         alphay[i]=a[i]*label[i];
00597 
00598     for (int32_t i=0; i<num_kernels; i++)
00599         sumw[i]=0;
00600 
00601     cblas_dgemv(CblasColMajor, CblasNoTrans, nk, (int) num, 0.5, (double*) W,
00602         nk, (double*) alphay, 1, 1.0, (double*) sumw, 1);
00603 
00604     SG_FREE(alphay);
00605 #else
00606     for (int32_t d=0; d<num_kernels; d++)
00607     {
00608         sumw[d]=0;
00609         for(int32_t i=0; i<num; i++)
00610             sumw[d] += 0.5*a[i]*label[i]*W[i*num_kernels+d];
00611     }
00612 #endif
00613 
00614     if (callback)
00615         mkl_converged=callback(mkl, sumw, sumalpha);
00616 
00617     const float64_t* new_beta   = kernel->get_subkernel_weights(num_kernels);
00618 
00619     // update lin
00620 #ifdef HAVE_LAPACK
00621     cblas_dgemv(CblasColMajor, CblasTrans, nk, (int) num, 1.0, (double*) W,
00622         nk, (double*) new_beta, 1, 0.0, (double*) lin, 1);
00623 #else
00624     for(int32_t i=0; i<num; i++)
00625         lin[i]=0 ;
00626     for (int32_t d=0; d<num_kernels; d++)
00627         if (new_beta[d]!=0)
00628             for(int32_t i=0; i<num; i++)
00629                 lin[i] += new_beta[d]*W[i*num_kernels+d] ;
00630 #endif
00631 
00632 
00633     SG_FREE(sumw);
00634 }
00635 
00636 
00637 void CSVRLight::reactivate_inactive_examples(
00638     int32_t* label, float64_t *a, SHRINK_STATE *shrink_state, float64_t *lin,
00639     float64_t *c, int32_t totdoc, int32_t iteration, int32_t *inconsistent,
00640     int32_t* docs, float64_t *aicache, float64_t *maxdiff)
00641      /* Make all variables active again which had been removed by
00642         shrinking. */
00643      /* Computes lin for those variables from scratch. */
00644 {
00645   register int32_t i=0,j,ii=0,jj,t,*changed2dnum,*inactive2dnum;
00646   int32_t *changed,*inactive;
00647   register float64_t *a_old,dist;
00648   float64_t ex_c,target;
00649 
00650   if (kernel->has_property(KP_LINADD) && get_linadd_enabled()) { /* special linear case */
00651       a_old=shrink_state->last_a;
00652 
00653       kernel->clear_normal();
00654       int32_t num_modified=0;
00655       for(i=0;i<totdoc;i++) {
00656           if(a[i] != a_old[i]) {
00657               kernel->add_to_normal(regression_fix_index(docs[i]), ((a[i]-a_old[i])*(float64_t)label[i]));
00658               a_old[i]=a[i];
00659               num_modified++;
00660           }
00661       }
00662 
00663       if (num_modified>0)
00664       {
00665           for(i=0;i<totdoc;i++) {
00666               if(!shrink_state->active[i]) {
00667                   lin[i]=shrink_state->last_lin[i]+kernel->compute_optimized(regression_fix_index(docs[i]));
00668               }
00669               shrink_state->last_lin[i]=lin[i];
00670           }
00671       }
00672   }
00673   else
00674   {
00675       changed=SG_MALLOC(int32_t, totdoc);
00676       changed2dnum=SG_MALLOC(int32_t, totdoc+11);
00677       inactive=SG_MALLOC(int32_t, totdoc);
00678       inactive2dnum=SG_MALLOC(int32_t, totdoc+11);
00679       for(t=shrink_state->deactnum-1;(t>=0) && shrink_state->a_history[t];t--) {
00680           if(verbosity>=2) {
00681               SG_INFO( "%ld..",t);
00682           }
00683           a_old=shrink_state->a_history[t];
00684           for(i=0;i<totdoc;i++) {
00685               inactive[i]=((!shrink_state->active[i])
00686                       && (shrink_state->inactive_since[i] == t));
00687               changed[i]= (a[i] != a_old[i]);
00688           }
00689           compute_index(inactive,totdoc,inactive2dnum);
00690           compute_index(changed,totdoc,changed2dnum);
00691 
00692           for(ii=0;(i=changed2dnum[ii])>=0;ii++) {
00693               CKernelMachine::kernel->get_kernel_row(i,inactive2dnum,aicache);
00694               for(jj=0;(j=inactive2dnum[jj])>=0;jj++)
00695                   lin[j]+=(a[i]-a_old[i])*aicache[j]*(float64_t)label[i];
00696           }
00697       }
00698       SG_FREE(changed);
00699       SG_FREE(changed2dnum);
00700       SG_FREE(inactive);
00701       SG_FREE(inactive2dnum);
00702   }
00703 
00704   (*maxdiff)=0;
00705   for(i=0;i<totdoc;i++) {
00706     shrink_state->inactive_since[i]=shrink_state->deactnum-1;
00707     if(!inconsistent[i]) {
00708       dist=(lin[i]-model->b)*(float64_t)label[i];
00709       target=-(learn_parm->eps[i]-(float64_t)label[i]*c[i]);
00710       ex_c=learn_parm->svm_cost[i]-learn_parm->epsilon_a;
00711       if((a[i]>learn_parm->epsilon_a) && (dist > target)) {
00712     if((dist-target)>(*maxdiff))  /* largest violation */
00713       (*maxdiff)=dist-target;
00714       }
00715       else if((a[i]<ex_c) && (dist < target)) {
00716     if((target-dist)>(*maxdiff))  /* largest violation */
00717       (*maxdiff)=target-dist;
00718       }
00719       if((a[i]>(0+learn_parm->epsilon_a))
00720      && (a[i]<ex_c)) {
00721     shrink_state->active[i]=1;                         /* not at bound */
00722       }
00723       else if((a[i]<=(0+learn_parm->epsilon_a)) && (dist < (target+learn_parm->epsilon_shrink))) {
00724     shrink_state->active[i]=1;
00725       }
00726       else if((a[i]>=ex_c)
00727           && (dist > (target-learn_parm->epsilon_shrink))) {
00728     shrink_state->active[i]=1;
00729       }
00730       else if(learn_parm->sharedslack) { /* make all active when sharedslack */
00731     shrink_state->active[i]=1;
00732       }
00733     }
00734   }
00735   if (use_kernel_cache) { /* update history for non-linear */
00736       for(i=0;i<totdoc;i++) {
00737           (shrink_state->a_history[shrink_state->deactnum-1])[i]=a[i];
00738       }
00739       for(t=shrink_state->deactnum-2;(t>=0) && shrink_state->a_history[t];t--) {
00740           SG_FREE(shrink_state->a_history[t]);
00741           shrink_state->a_history[t]=0;
00742       }
00743   }
00744 }
00745 #endif //USE_SVMLIGHT
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation