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