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

SHOGUN Machine Learning Toolbox - Documentation