KernelMachine.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "classifier/KernelMachine.h"
00014 #include "lib/Signal.h"
00015
00016 #ifdef HAVE_BOOST_SERIALIZATION
00017 #include <boost/serialization/export.hpp>
00018 BOOST_CLASS_EXPORT_GUID(shogun::CKernelMachine, "CKernelMachine");
00019
00020 #endif //HAVE_BOOST_SERIALIZATION
00021
00022 using namespace shogun;
00023
00024 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00025 struct S_THREAD_PARAM
00026 {
00027 CKernelMachine* kernel_machine;
00028 CLabels* result;
00029 int32_t start;
00030 int32_t end;
00031 bool verbose;
00032 };
00033 #endif // DOXYGEN_SHOULD_SKIP_THIS
00034
00035 CKernelMachine::CKernelMachine()
00036 : CClassifier(), kernel(NULL), use_batch_computation(true), use_linadd(true), use_bias(true)
00037 {
00038 m_bias=0.0;
00039 m_alpha=NULL;
00040 m_svs=NULL;
00041 num_svs=0;
00042 }
00043
00044 CKernelMachine::~CKernelMachine()
00045 {
00046 SG_UNREF(kernel);
00047
00048 delete[] m_alpha;
00049 delete[] m_svs;
00050 }
00051
00052 bool CKernelMachine::init_kernel_optimization()
00053 {
00054 int32_t num_sv=get_num_support_vectors();
00055
00056 if (kernel && kernel->has_property(KP_LINADD) && num_sv>0)
00057 {
00058 int32_t * sv_idx = new int32_t[num_sv] ;
00059 float64_t* sv_weight = new float64_t[num_sv] ;
00060
00061 for(int32_t i=0; i<num_sv; i++)
00062 {
00063 sv_idx[i] = get_support_vector(i) ;
00064 sv_weight[i] = get_alpha(i) ;
00065 }
00066
00067 bool ret = kernel->init_optimization(num_sv, sv_idx, sv_weight) ;
00068
00069 delete[] sv_idx ;
00070 delete[] sv_weight ;
00071
00072 if (!ret)
00073 SG_ERROR( "initialization of kernel optimization failed\n");
00074
00075 return ret;
00076 }
00077 else
00078 SG_ERROR( "initialization of kernel optimization failed\n");
00079
00080 return false;
00081 }
00082
00083 CLabels* CKernelMachine::classify()
00084 {
00085 CLabels* lab=NULL;
00086
00087 if (!kernel)
00088 SG_ERROR( "Kernelmachine can not proceed without kernel!\n");
00089
00090 if ( kernel && kernel->get_num_vec_rhs()>0 )
00091 {
00092 int32_t num_vectors=kernel->get_num_vec_rhs();
00093
00094 lab=new CLabels(num_vectors);
00095 SG_DEBUG( "computing output on %d test examples\n", num_vectors);
00096
00097 CSignal::clear_cancel();
00098
00099 if (io->get_show_progress())
00100 io->enable_progress();
00101 else
00102 io->disable_progress();
00103
00104 if (kernel->has_property(KP_BATCHEVALUATION) &&
00105 get_batch_computation_enabled())
00106 {
00107 float64_t* output=new float64_t[num_vectors];
00108 memset(output, 0, sizeof(float64_t)*num_vectors);
00109
00110 if (get_num_support_vectors()>0)
00111 {
00112 int32_t* sv_idx=new int32_t[get_num_support_vectors()];
00113 float64_t* sv_weight=new float64_t[get_num_support_vectors()];
00114 int32_t* idx=new int32_t[num_vectors];
00115
00116
00117 for (int32_t i=0; i<num_vectors; i++)
00118 idx[i]=i;
00119
00120 for (int32_t i=0; i<get_num_support_vectors(); i++)
00121 {
00122 sv_idx[i] = get_support_vector(i) ;
00123 sv_weight[i] = get_alpha(i) ;
00124 }
00125
00126 kernel->compute_batch(num_vectors, idx,
00127 output, get_num_support_vectors(), sv_idx, sv_weight);
00128 delete[] sv_idx ;
00129 delete[] sv_weight ;
00130 delete[] idx;
00131 }
00132
00133 for (int32_t i=0; i<num_vectors; i++)
00134 lab->set_label(i, get_bias()+output[i]);
00135
00136 delete[] output;
00137 }
00138 else
00139 {
00140 int32_t num_threads=parallel->get_num_threads();
00141 ASSERT(num_threads>0);
00142
00143 if (num_threads < 2)
00144 {
00145 S_THREAD_PARAM params;
00146 params.kernel_machine=this;
00147 params.result=lab;
00148 params.start=0;
00149 params.end=num_vectors;
00150 params.verbose=true;
00151 classify_example_helper((void*) ¶ms);
00152 }
00153 #ifndef WIN32
00154 else
00155 {
00156 pthread_t* threads = new pthread_t[num_threads-1];
00157 S_THREAD_PARAM* params = new S_THREAD_PARAM[num_threads];
00158 int32_t step= num_vectors/num_threads;
00159
00160 int32_t t;
00161
00162 for (t=0; t<num_threads-1; t++)
00163 {
00164 params[t].kernel_machine = this;
00165 params[t].result = lab;
00166 params[t].start = t*step;
00167 params[t].end = (t+1)*step;
00168 params[t].verbose = false;
00169 pthread_create(&threads[t], NULL,
00170 CKernelMachine::classify_example_helper, (void*)¶ms[t]);
00171 }
00172
00173 params[t].kernel_machine = this;
00174 params[t].result = lab;
00175 params[t].start = t*step;
00176 params[t].end = num_vectors;
00177 params[t].verbose = true;
00178 classify_example_helper((void*) ¶ms[t]);
00179
00180 for (t=0; t<num_threads-1; t++)
00181 pthread_join(threads[t], NULL);
00182
00183 delete[] params;
00184 delete[] threads;
00185 }
00186 #endif
00187 }
00188
00189 #ifndef WIN32
00190 if ( CSignal::cancel_computations() )
00191 SG_INFO( "prematurely stopped. \n");
00192 else
00193 #endif
00194 SG_DONE();
00195 }
00196 else
00197 return NULL;
00198
00199 return lab;
00200 }
00201
00202 float64_t CKernelMachine::classify_example(int32_t num)
00203 {
00204 ASSERT(kernel);
00205
00206 if (kernel->has_property(KP_LINADD) && (kernel->get_is_initialized()))
00207 {
00208 float64_t dist = kernel->compute_optimized(num);
00209 return (dist+get_bias());
00210 }
00211 else
00212 {
00213 float64_t dist=0;
00214 for(int32_t i=0; i<get_num_support_vectors(); i++)
00215 dist+=kernel->kernel(get_support_vector(i), num)*get_alpha(i);
00216
00217 return (dist+get_bias());
00218 }
00219 }
00220
00221
00222 CLabels* CKernelMachine::classify(CFeatures* data)
00223 {
00224 if (!kernel)
00225 SG_ERROR("No kernel assigned!\n");
00226
00227 CFeatures* lhs=kernel->get_lhs();
00228 if (!lhs || !lhs->get_num_vectors())
00229 {
00230 SG_UNREF(lhs);
00231 SG_ERROR("No vectors on left hand side\n");
00232 }
00233 kernel->init(lhs, data);
00234 SG_UNREF(lhs);
00235
00236 return classify();
00237 }
00238
00239 void* CKernelMachine::classify_example_helper(void* p)
00240 {
00241 S_THREAD_PARAM* params= (S_THREAD_PARAM*) p;
00242 CLabels* result=params->result;
00243 CKernelMachine* kernel_machine=params->kernel_machine;
00244
00245 #ifdef WIN32
00246 for (int32_t vec=params->start; vec<params->end; vec++)
00247 #else
00248 for (int32_t vec=params->start; vec<params->end &&
00249 !CSignal::cancel_computations(); vec++)
00250 #endif
00251 {
00252 if (params->verbose)
00253 {
00254 int32_t num_vectors=params->end - params->start;
00255 int32_t v=vec-params->start;
00256 if ( (v% (num_vectors/100+1))== 0)
00257 SG_SPROGRESS(v, 0.0, num_vectors-1);
00258 }
00259
00260 result->set_label(vec, kernel_machine->classify_example(vec));
00261 }
00262
00263 return NULL;
00264 }