ANOVAKernel.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) 2011 Andrew Tereskin
00008  * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
00009  */
00010 
00011 #include <math.h>
00012 #include <shogun/kernel/ANOVAKernel.h>
00013 #include <shogun/mathematics/Math.h>
00014 
00015 using namespace shogun;
00016 
00017 CANOVAKernel::CANOVAKernel(): CDotKernel(0), cardinality(1.0)
00018 {
00019     init();
00020     register_params();
00021 }
00022 
00023 CANOVAKernel::CANOVAKernel(int32_t cache, int32_t d)
00024 : CDotKernel(cache), cardinality(d)
00025 {
00026     init();
00027     register_params();
00028 }
00029 
00030 CANOVAKernel::CANOVAKernel(
00031     CSimpleFeatures<float64_t>* l, CSimpleFeatures<float64_t>* r, int32_t d, int32_t cache)
00032   : CDotKernel(cache), cardinality(d)
00033 {
00034     init();
00035     register_params();
00036     init(l, r);
00037 }
00038 
00039 CANOVAKernel::~CANOVAKernel()
00040 {
00041     cleanup();
00042 }
00043 
00044 bool CANOVAKernel::init(CFeatures* l, CFeatures* r)
00045 {
00046     cleanup();
00047 
00048     bool result = CDotKernel::init(l,r);
00049 
00050     allocate_arrays();
00051     init_normalizer();
00052     return result;
00053 }
00054 
00055 float64_t CANOVAKernel::compute(int32_t idx_a, int32_t idx_b)
00056 {
00057     int32_t alen, blen;
00058     bool afree, bfree;
00059 
00060     float64_t* avec=
00061         ((CSimpleFeatures<float64_t>*) lhs)->get_feature_vector(idx_a, alen, afree);
00062     float64_t* bvec=
00063         ((CSimpleFeatures<float64_t>*) rhs)->get_feature_vector(idx_b, blen, bfree);
00064     ASSERT(alen==blen);
00065 
00066     float64_t result1 = compute_recursive1(avec, bvec, alen);
00067     //float64_t result2 = compute_recursive2(avec, bvec, alen);
00068         
00069     ((CSimpleFeatures<float64_t>*) lhs)->free_feature_vector(avec, idx_a, afree);
00070     ((CSimpleFeatures<float64_t>*) rhs)->free_feature_vector(bvec, idx_b, bfree);
00071         
00072     return result1;
00073 }
00074 
00075 float64_t CANOVAKernel::compute_rec1(int32_t idx_a, int32_t idx_b)
00076 {
00077     int32_t alen, blen;
00078     bool afree, bfree;
00079 
00080     float64_t* avec=
00081         ((CSimpleFeatures<float64_t>*) lhs)->get_feature_vector(idx_a, alen, afree);
00082     float64_t* bvec=
00083         ((CSimpleFeatures<float64_t>*) rhs)->get_feature_vector(idx_b, blen, bfree);
00084     ASSERT(alen==blen);
00085 
00086     float64_t result = compute_recursive1(avec, bvec, alen);
00087         
00088     ((CSimpleFeatures<float64_t>*) lhs)->free_feature_vector(avec, idx_a, afree);
00089     ((CSimpleFeatures<float64_t>*) rhs)->free_feature_vector(bvec, idx_b, bfree);
00090         
00091     return result;
00092 }
00093 
00094 float64_t CANOVAKernel::compute_rec2(int32_t idx_a, int32_t idx_b)
00095 {
00096     int32_t alen, blen;
00097     bool afree, bfree;
00098 
00099     float64_t* avec=
00100         ((CSimpleFeatures<float64_t>*) lhs)->get_feature_vector(idx_a, alen, afree);
00101     float64_t* bvec=
00102         ((CSimpleFeatures<float64_t>*) rhs)->get_feature_vector(idx_b, blen, bfree);
00103     ASSERT(alen==blen);
00104 
00105     float64_t result = compute_recursive2(avec, bvec, alen);
00106         
00107     ((CSimpleFeatures<float64_t>*) lhs)->free_feature_vector(avec, idx_a, afree);
00108     ((CSimpleFeatures<float64_t>*) rhs)->free_feature_vector(bvec, idx_b, bfree);
00109         
00110     return result;
00111 }
00112 
00113 void CANOVAKernel::init()
00114 {
00116     DP=NULL;
00117     
00119     KD=NULL;
00120     KS=NULL;
00121     vec_pow=NULL;
00122 }
00123 
00124 void CANOVAKernel::allocate_arrays()
00125 {
00126     cleanup();
00127 
00128     ASSERT(lhs && rhs);
00129     int32_t num_feat = ((CSimpleFeatures<float64_t>*) lhs)->get_num_features();
00130     ASSERT(num_feat == ((CSimpleFeatures<float64_t>*) rhs)->get_num_features());
00131     
00132     //compute_recursive1
00133     DP_len=(cardinality+1)*(num_feat+1);
00134     DP = SG_MALLOC(float64_t, DP_len);
00135     
00136     //compute_recursive2
00137     KD = SG_MALLOC(float64_t, cardinality+1);
00138     KS = SG_MALLOC(float64_t, cardinality+1);
00139     vec_pow = SG_MALLOC(float64_t, num_feat);
00140 }
00141 
00142 void CANOVAKernel::cleanup()
00143 {
00144     //compute_recursive1
00145     SG_FREE(DP);
00146     DP=NULL;
00147     DP_len=0;
00148 
00149     //compute_recursive2
00150     SG_FREE(KD);
00151     KD=NULL;
00152     SG_FREE(KS);
00153     KS=NULL;
00154     SG_FREE(vec_pow);
00155     vec_pow=NULL;
00156 }
00157 
00158 void CANOVAKernel::load_serializable_post() throw (ShogunException)
00159 {
00160     CKernel::load_serializable_post();
00161     allocate_arrays();
00162 }
00163 
00164 void CANOVAKernel::register_params()
00165 {
00166     m_parameters->add(&cardinality, "cardinality", "Kernel cardinality.");
00167 }
00168 
00169 
00170 float64_t CANOVAKernel::compute_recursive1(float64_t* avec, float64_t* bvec, int32_t len)
00171 {
00172     ASSERT(DP);
00173     int32_t d=cardinality;
00174     int32_t offs=cardinality+1;
00175 
00176     ASSERT(DP_len==(len+1)*offs);
00177 
00178     for (int32_t j=0; j < len+1; j++)
00179         DP[j] = 1.0;
00180 
00181     for (int32_t k=1; k < d+1; k++)
00182     {
00183         // TRAP d>len case
00184         if (k-1>=len)
00185             return 0.0;
00186 
00187         DP[k*offs+k-1] = 0;
00188         for (int32_t j=k; j < len+1; j++)
00189             DP[k*offs+j]=DP[k*offs+j-1]+avec[j-1]*bvec[j-1]*DP[(k-1)*offs+j-1];
00190     }
00191 
00192     float64_t result=DP[d*offs+len];
00193 
00194     return result;
00195 }
00196 
00197 float64_t CANOVAKernel::compute_recursive2(float64_t* avec, float64_t* bvec, int32_t len)
00198 {
00199     ASSERT(vec_pow);
00200     ASSERT(KS);
00201     ASSERT(KD);
00202 
00203     int32_t d=cardinality;
00204     for (int32_t i=0; i < len; i++)
00205         vec_pow[i] = 1;
00206 
00207     for (int32_t k=1; k < d+1; k++)
00208     {
00209         KS[k] = 0;
00210         for (int32_t i=0; i < len; i++)
00211         {
00212             vec_pow[i] *= avec[i]*bvec[i];
00213             KS[k] += vec_pow[i];
00214         }
00215     }
00216 
00217     KD[0] = 1;
00218     for (int32_t k=1; k < d+1; k++)
00219     {
00220         float64_t sum = 0;
00221         for (int32_t s=1; s < k+1; s++)
00222         {
00223             float64_t sign = 1.0;
00224             if (s % 2 == 0)
00225                 sign = -1.0;
00226 
00227             sum += sign*KD[k-s]*KS[s];
00228         }
00229 
00230         KD[k] = sum / k;
00231     }
00232     float64_t result=KD[d];
00233 
00234     return result;
00235 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation