00001
00002
00003
00004
00005
00006
00007
00008
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
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
00133 DP_len=(cardinality+1)*(num_feat+1);
00134 DP = SG_MALLOC(float64_t, DP_len);
00135
00136
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
00145 SG_FREE(DP);
00146 DP=NULL;
00147 DP_len=0;
00148
00149
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
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 }