PyramidChi2.cpp

Go to the documentation of this file.
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 Alexander Binder
00008  * Copyright (C) 1999-2008 Fraunhofer Institute FIRST and Max-Planck-Society
00009  */
00010 
00011 #include "PyramidChi2.h"
00012 #include "lib/common.h"
00013 #include "kernel/GaussianKernel.h"
00014 #include "features/Features.h"
00015 #include "features/RealFeatures.h"
00016 #include "lib/io.h"
00017 
00018 CPyramidChi2::CPyramidChi2(
00019     int32_t size, float64_t width2, int32_t* pyramidlevels2,int32_t
00020     numlevels2, int32_t  numbinsinhistogram2, float64_t* weights2,
00021     int32_t numweights2)
00022 : CSimpleKernel<float64_t>(size), width(width2), pyramidlevels(NULL),
00023     numlevels(numlevels2), weights(NULL), numweights(numweights2)
00024 {
00025     pyramidlevels=new int32_t[numlevels];
00026     for(int32_t i=0; i<numlevels; ++i)
00027         pyramidlevels[i]=pyramidlevels2[i];
00028     
00029     numbinsinhistogram=numbinsinhistogram2;
00030     
00031     weights=new float64_t[numweights];
00032     for(int32_t i=0; i<numweights; ++i)
00033         weights[i]=weights2[i];
00034     
00035     if (!sanitycheck_weak())
00036         SG_ERROR("CPyramidChi2::CPyramidChi2(... first constructor): false==sanitycheck_weak() occurred! Someone messed up the initializing of the kernel.\0");
00037 }
00038 
00039 void CPyramidChi2::cleanup()
00040 {
00041     //weights.clear();
00042     //pyramidlevels.clear();
00043     numlevels=-1;
00044     numweights=-1;
00045     numbinsinhistogram=-1;
00046     //sanitycheckbit=false;
00047 
00048     delete[] pyramidlevels;
00049     pyramidlevels=NULL;
00050     delete[] weights;
00051     weights=NULL;
00052 
00053     CKernel::cleanup();
00054 }
00055 
00056 bool CPyramidChi2::init(CFeatures* l, CFeatures* r)
00057 {
00058     CSimpleKernel<float64_t>::init(l, r);
00059     return init_normalizer();
00060 }
00061 
00062 CPyramidChi2::CPyramidChi2(
00063     CRealFeatures* l, CRealFeatures* r, int32_t size, float64_t width2,
00064     int32_t* pyramidlevels2,int32_t numlevels2, int32_t  numbinsinhistogram2,
00065     float64_t* weights2,int32_t numweights2)
00066 : CSimpleKernel<float64_t>(size), width(width2), pyramidlevels(NULL),
00067     numlevels(numlevels2), weights(NULL), numweights(numweights2)
00068 {
00069     pyramidlevels=new int32_t[numlevels];
00070     for(int32_t i=0; i<numlevels;++i )
00071         pyramidlevels[i]=pyramidlevels2[i];
00072     
00073     numbinsinhistogram=numbinsinhistogram2;
00074     
00075     weights=new float64_t[numweights];
00076     for(int32_t i=0; i<numweights;++i )
00077         weights[i]=weights2[i];
00078     
00079     if(!sanitycheck_weak())
00080         SG_ERROR("CPyramidChi2::CPyramidChi2(... second constructor): false==sanitycheck_weak() occurred! Someone messed up with initializing the kernel.\0");
00081 
00082     init(l, r);
00083 }
00084 
00085 CPyramidChi2::~CPyramidChi2()
00086 {
00087     cleanup();
00088 }
00089 
00090 bool CPyramidChi2::load_init(FILE* src)
00091 {
00092     return (false);
00093 }
00094 
00095 bool CPyramidChi2::save_init(FILE* dest)
00096 {
00097     return (false);
00098 }
00099 
00100 
00101 bool CPyramidChi2::sanitycheck_weak()
00102 {
00103     if (numbinsinhistogram<=0)
00104     {
00105         SG_ERROR("bool CPyramidChi2::sanitycheck_weak(): member value inconsistencer: numbinsinhistogram<=0");
00106         return (false);
00107     }
00108     
00109     if ((pyramidlevels!=NULL) && (numlevels<=0))
00110     {
00111         SG_ERROR("void CPyramidChi2::sanitycheck_weak(): inconsistency found: (pyramidlevels!=NULL) && (numlevels <=0)");
00112         
00113         return(false);
00114     }
00115     
00116     if ((pyramidlevels==NULL) && (numlevels>0))
00117     {
00118         SG_ERROR("void CPyramidChi2::sanitycheck_weak(): inconsistency found: (pyramidlevels==NULL) && (numlevels>0)");
00119         
00120         return(false);
00121     }
00122     
00123     if((weights!=NULL) &&(numweights<=0))
00124     {
00125         SG_ERROR("void CPyramidChi2::sanitycheck_weak(): inconsistency found: (weights!=NULL) && (numweights <=0)");
00126         
00127         return(false);
00128     }
00129     
00130     if ((weights==NULL) && (numweights>0))
00131     {
00132         SG_ERROR("void CPyramidChi2::sanitycheck_weak(): inconsistency found: (weights==NULL) && (numweights >0)");
00133         
00134         return(false);
00135     }
00136     
00137 
00138     int32_t sum=0;
00139     for (int32_t levelind=0; levelind < numlevels; ++levelind)
00140     {
00141         sum+=CMath::pow(4, pyramidlevels[levelind]);
00142     }
00143     
00144     if (sum!=numweights )
00145     {
00146         SG_ERROR("bool CPyramidChi2::sanitycheck_weak(): member value error: sum!=numweights ");
00147         return (false);
00148     }
00149 
00150     return (true);
00151 
00152 }
00153 
00154 
00155 float64_t CPyramidChi2::compute(int32_t idx_a, int32_t idx_b)
00156 {
00157     // implied structure
00158     // for each level l in pyramidlevels we have at level l we have 4^l histograms with numbinsinhistogram bins
00159     //the features are a vector being a concatenation of histograms starting with all histograms at the largest level in pyramidlevels
00160     // then followed by all histograms at the next largest level in pyramidlevels, then the next largest and so on
00161 
00162 
00163     // the dimensionality is (LATEX) \sum_{ l \ in pyramidlevels } 4^l * numbinsinhistogram
00164 
00165     int32_t alen, blen;
00166     bool afree, bfree;
00167 
00168     float64_t* avec=
00169             ((CRealFeatures*) lhs)->get_feature_vector(idx_a,
00170                     alen, afree);
00171     float64_t* bvec=
00172             ((CRealFeatures*) rhs)->get_feature_vector(idx_b,
00173                     blen, bfree);
00174     ASSERT(alen==blen);
00175 
00176     int32_t dims=0;
00177     for (int32_t levelind=0; levelind<numlevels; ++levelind)
00178     {
00179         dims+=CMath::pow(4, pyramidlevels[levelind])*numbinsinhistogram;
00180     }
00181     ASSERT(dims==alen);
00182 
00183     //the actual computation - a weighted sum over chi2
00184     float64_t result=0;
00185     int32_t cursum=0;
00186     
00187     for (int32_t lvlind=0; lvlind< numlevels; ++lvlind)
00188     {
00189         for (int32_t histoind=0; histoind<CMath::pow(4, pyramidlevels[lvlind]); ++histoind)
00190         {
00191             float64_t curweight=weights[cursum+histoind];
00192             
00193             for (int32_t i=0; i< numbinsinhistogram; ++i)
00194             {
00195                 int32_t index= (cursum+histoind)*numbinsinhistogram+i;
00196                 if(avec[index] + bvec[index]>0)
00197                 {   
00198                     result+= curweight*(avec[index] - bvec[index])*(avec[index]
00199                         - bvec[index])/(avec[index] + bvec[index]);
00200                 }
00201             }
00202         }
00203         cursum+=CMath::pow(4, pyramidlevels[lvlind]);
00204     }
00205     result=exp(-result/(float64_t)width);
00206     
00207     
00208     ((CRealFeatures*) lhs)->free_feature_vector(avec, idx_a, afree);
00209     ((CRealFeatures*) rhs)->free_feature_vector(bvec, idx_b, bfree);
00210 
00211     return (result);
00212 }
00213 
00214 
00215 void CPyramidChi2::setstandardweights()
00216 {
00217     int32_t sum=0;
00218     int32_t maxlvl=0;
00219     for (int32_t levelind=0; levelind < numlevels; ++levelind)
00220     {
00221         sum+=CMath::pow(4, pyramidlevels[levelind]);
00222         maxlvl=CMath::max(maxlvl,pyramidlevels[levelind]);
00223     }
00224 
00225     if (weights==NULL)
00226     {
00227         numweights=sum;
00228         weights=new float64_t[numweights];
00229     }
00230 
00231     else if (numweights!=sum)
00232     {
00233         // a possible source of error or leak!
00234         if (numweights>0)
00235         {
00236             delete[]  weights;
00237         }
00238         else
00239         {
00240             SG_ERROR("void CPyramidChi2::setstandardweights(): inconsistency found: (weights!=NULL) && (numweights <=0), continuing, but memory leak possible");
00241         }
00242 
00243         numweights=sum;
00244         weights=new float64_t[numweights];
00245     }
00246     //weights.resize(sum);
00247     
00248     int32_t cursum=0;
00249     for (int32_t levelind=0; levelind < numlevels; ++levelind)
00250     {
00251         if (pyramidlevels[levelind]==0)
00252         {
00253             for (int32_t histoind=0; histoind<CMath::pow(4, pyramidlevels[levelind]); ++histoind)
00254             {
00255                 weights[cursum+histoind]=CMath::pow((float64_t)2.0,
00256                         -(float64_t)maxlvl);
00257             }
00258         }
00259         else
00260         {
00261             for (int32_t histoind=0; histoind<CMath::pow(4, pyramidlevels[levelind]); ++histoind)
00262             {
00263                 weights[cursum+histoind]=CMath::pow((float64_t)2.0,
00264                         (float64_t)(pyramidlevels[levelind]-1-maxlvl));
00265             }
00266         }
00267         cursum+=CMath::pow(4, pyramidlevels[levelind]);
00268     }
00269 }

SHOGUN Machine Learning Toolbox - Documentation