SHOGUN
v1.1.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) 2008-2009 Alexander Binder 00008 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00009 */ 00010 00011 #include <shogun/kernel/PyramidChi2.h> 00012 #include <shogun/lib/common.h> 00013 #include <shogun/kernel/GaussianKernel.h> 00014 #include <shogun/features/Features.h> 00015 #include <shogun/features/SimpleFeatures.h> 00016 #include <shogun/io/SGIO.h> 00017 #include <shogun/mathematics/Math.h> 00018 00019 using namespace shogun; 00020 00021 CPyramidChi2::CPyramidChi2() 00022 : weights(NULL) 00023 { 00024 // this will produce an erro in kernel computation! 00025 num_cells=0; 00026 width_computation_type=0; 00027 width=1; 00028 num_randfeats_forwidthcomputation=-1; 00029 } 00030 00031 CPyramidChi2::CPyramidChi2( 00032 int32_t size, int32_t num_cells2, 00033 float64_t* weights_foreach_cell2, 00034 int32_t width_computation_type2, 00035 float64_t width2) 00036 : CDotKernel(size), num_cells(num_cells2),weights(NULL), 00037 width_computation_type(width_computation_type2), width(width2), 00038 num_randfeats_forwidthcomputation(-1) 00039 { 00040 if(num_cells<=0) 00041 SG_ERROR("CPyramidChi2 Constructor fatal error: parameter num_cells2 NOT positive"); 00042 weights=SG_MALLOC(float64_t, num_cells); 00043 if(weights_foreach_cell2) 00044 { 00045 for (int32_t i=0; i<num_cells; ++i) 00046 weights[i]=weights_foreach_cell2[i]; 00047 } 00048 else 00049 { for (int32_t i=0; i<num_cells; ++i) 00050 weights[i]=1; 00051 } 00052 00053 if (width_computation_type>0 ) 00054 { 00055 num_randfeats_forwidthcomputation=(int32_t)CMath::round(width); 00056 width=-1; 00057 } 00058 00059 00060 } 00061 00062 void CPyramidChi2::cleanup() 00063 { 00064 // this will produce an erro in kernel computation! 00065 num_cells=0; 00066 width_computation_type=0; 00067 width=1; 00068 00069 num_randfeats_forwidthcomputation=-1; 00070 00071 SG_FREE(weights); 00072 weights=NULL; 00073 00074 CKernel::cleanup(); 00075 } 00076 00077 bool CPyramidChi2::init(CFeatures* l, CFeatures* r) 00078 { 00079 CDotKernel::init(l, r); 00080 return init_normalizer(); 00081 } 00082 00083 CPyramidChi2::CPyramidChi2( 00084 CSimpleFeatures<float64_t>* l, CSimpleFeatures<float64_t>* r, 00085 int32_t size, int32_t num_cells2, 00086 float64_t* weights_foreach_cell2, 00087 int32_t width_computation_type2, 00088 float64_t width2) 00089 : CDotKernel(size), num_cells(num_cells2), weights(NULL), 00090 width_computation_type(width_computation_type2), width(width2), 00091 num_randfeats_forwidthcomputation(-1) 00092 { 00093 if(num_cells<=0) 00094 SG_ERROR("CPyramidChi2 Constructor fatal error: parameter num_cells2 NOT positive"); 00095 weights=SG_MALLOC(float64_t, num_cells); 00096 if(weights_foreach_cell2) 00097 { 00098 for (int32_t i=0; i<num_cells; ++i) 00099 weights[i]=weights_foreach_cell2[i]; 00100 } 00101 else 00102 { for (int32_t i=0; i<num_cells; ++i) 00103 weights[i]=1; 00104 } 00105 00106 if (width_computation_type>0 ) 00107 { 00108 num_randfeats_forwidthcomputation=(int32_t)CMath::round(width); 00109 width=-1; 00110 } 00111 00112 init(l, r); 00113 } 00114 00115 CPyramidChi2::~CPyramidChi2() 00116 { 00117 cleanup(); 00118 } 00119 00120 00121 00122 float64_t CPyramidChi2::compute(int32_t idx_a, int32_t idx_b) 00123 { 00124 00125 if(num_cells<=0) 00126 SG_ERROR("CPyramidChi2::compute(...) fatal error: parameter num_cells NOT positive"); 00127 00128 int32_t alen, blen; 00129 bool afree, bfree; 00130 00131 float64_t* avec=((CSimpleFeatures<float64_t>*) lhs)->get_feature_vector(idx_a, 00132 alen, afree); 00133 float64_t* bvec=((CSimpleFeatures<float64_t>*) rhs)->get_feature_vector(idx_b, 00134 blen, bfree); 00135 if(alen!=blen) 00136 SG_ERROR("CPyramidChi2::compute(...) fatal error: lhs feature dim != rhs feature dim"); 00137 00138 int32_t dims=alen/num_cells; 00139 00140 00141 if(width<=0) 00142 { 00143 if(width_computation_type >0) 00144 { 00145 00146 //compute width 00147 int32_t numind; 00148 00149 if (num_randfeats_forwidthcomputation >1) 00150 { 00151 numind=CMath::min( ((CSimpleFeatures<float64_t>*) lhs)->get_num_vectors() , num_randfeats_forwidthcomputation); 00152 } 00153 else 00154 { 00155 numind= ((CSimpleFeatures<float64_t>*) lhs)->get_num_vectors(); 00156 } 00157 float64_t* featindices = SG_MALLOC(float64_t, numind); 00158 00159 if (num_randfeats_forwidthcomputation >0) 00160 { 00161 for(int32_t i=0; i< numind;++i) 00162 featindices[i]=CMath::random(0, ((CSimpleFeatures<float64_t>*) lhs)->get_num_vectors()-1); 00163 } 00164 else 00165 { 00166 for(int32_t i=0; i< numind;++i) 00167 featindices[i]=i; 00168 } 00169 00170 00171 width=0; 00172 00173 //get avec, get bvec only from lhs, do not free 00174 for (int32_t li=0; li < numind;++li) 00175 { 00176 avec=((CSimpleFeatures<float64_t>*) lhs)->get_feature_vector(featindices[li], 00177 alen, afree); 00178 for (int32_t ri=0; ri <=li;++ri) 00179 { 00180 // lhs is right here!!! 00181 bvec=((CSimpleFeatures<float64_t>*) lhs)->get_feature_vector(featindices[ri], 00182 blen, bfree); 00183 00184 float64_t result=0; 00185 for (int32_t histoind=0; histoind<num_cells; ++histoind) 00186 { 00187 float64_t curweight=weights[histoind]; 00188 00189 for (int32_t i=0; i< dims; ++i) 00190 { 00191 int32_t index= histoind*dims+i; 00192 if(avec[index] + bvec[index]>0) 00193 { 00194 result+= curweight*(avec[index] - bvec[index])*(avec[index] 00195 - bvec[index])/(avec[index] + bvec[index]); 00196 } 00197 } 00198 } 00199 width+=result*2.0/((double)numind)/(numind+1.0); 00200 } 00201 00202 } 00203 SG_FREE(featindices); 00204 } 00205 else 00206 { 00207 SG_ERROR("CPyramidChi2::compute(...) fatal error: width<=0"); 00208 } 00209 } 00210 00211 00212 //the actual kernel computation 00213 avec=((CSimpleFeatures<float64_t>*) lhs)->get_feature_vector(idx_a, 00214 alen, afree); 00215 bvec=((CSimpleFeatures<float64_t>*) rhs)->get_feature_vector(idx_b, 00216 blen, bfree); 00217 00218 float64_t result=0; 00219 for (int32_t histoind=0; histoind<num_cells; ++histoind) 00220 { 00221 float64_t curweight=weights[histoind]; 00222 00223 for (int32_t i=0; i< dims; ++i) 00224 { 00225 int32_t index= histoind*dims+i; 00226 if(avec[index] + bvec[index]>0) 00227 { 00228 result+= curweight*(avec[index] - bvec[index])*(avec[index] 00229 - bvec[index])/(avec[index] + bvec[index]); 00230 } 00231 } 00232 } 00233 result= CMath::exp(-result/width); 00234 00235 00236 ((CSimpleFeatures<float64_t>*) lhs)->free_feature_vector(avec, idx_a, afree); 00237 ((CSimpleFeatures<float64_t>*) rhs)->free_feature_vector(bvec, idx_b, bfree); 00238 00239 return (result); 00240 } 00241 00242 void CPyramidChi2::setparams_pychi2(int32_t num_cells2, 00243 float64_t* weights_foreach_cell2, 00244 int32_t width_computation_type2, 00245 float64_t width2) 00246 { 00247 num_cells=num_cells2; 00248 width_computation_type=width_computation_type2; 00249 width=width2; 00250 num_randfeats_forwidthcomputation=-1; 00251 00252 if(num_cells<=0) 00253 SG_ERROR("CPyramidChi2::setparams_pychi2(...) fatal error: parameter num_cells2 NOT positive"); 00254 if(weights) 00255 SG_FREE(weights); 00256 weights=SG_MALLOC(float64_t, num_cells); 00257 if(weights_foreach_cell2) 00258 { 00259 for (int32_t i=0; i<num_cells; ++i) 00260 weights[i]=weights_foreach_cell2[i]; 00261 } 00262 else 00263 { for (int32_t i=0; i<num_cells; ++i) 00264 weights[i]=1; 00265 } 00266 00267 if (width_computation_type>0 ) 00268 { 00269 num_randfeats_forwidthcomputation=(int32_t)CMath::round(width); 00270 width=-1; 00271 } 00272 }