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