00001
00002
00003
00004
00005
00006
00007
00008
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
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
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
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
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
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
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 }