Mercurial > hg > audiodb
comparison query.cpp @ 768:b9dbe4611dde
Adding Kullback-Leibler divergence as alternate distance function
author | mas01mc |
---|---|
date | Sat, 15 Oct 2011 17:28:07 +0000 |
parents | ddf08008d45b |
children |
comparison
equal
deleted
inserted
replaced
767:6d0d41604aba | 768:b9dbe4611dde |
---|---|
53 goto error; | 53 goto error; |
54 } | 54 } |
55 break; | 55 break; |
56 case ADB_DISTANCE_EUCLIDEAN_NORMED: | 56 case ADB_DISTANCE_EUCLIDEAN_NORMED: |
57 case ADB_DISTANCE_EUCLIDEAN: | 57 case ADB_DISTANCE_EUCLIDEAN: |
58 case ADB_DISTANCE_KULLBACK_LEIBLER_DIVERGENCE: | |
58 switch(qspec->params.accumulation) { | 59 switch(qspec->params.accumulation) { |
59 case ADB_ACCUMULATION_DB: | 60 case ADB_ACCUMULATION_DB: |
60 qstate.accumulator = new DBAccumulator<adb_result_dist_lt>(qspec->params.npoints); | 61 qstate.accumulator = new DBAccumulator<adb_result_dist_lt>(qspec->params.npoints); |
61 break; | 62 break; |
62 case ADB_ACCUMULATION_PER_TRACK: | 63 case ADB_ACCUMULATION_PER_TRACK: |
106 | 107 |
107 /* FIXME: we should check the return values from allocation */ | 108 /* FIXME: we should check the return values from allocation */ |
108 static void audiodb_initialize_arrays(adb_t *adb, const adb_query_spec_t *spec, int track, unsigned int numVectors, double *query, double *data_buffer, double **D, double **DD) { | 109 static void audiodb_initialize_arrays(adb_t *adb, const adb_query_spec_t *spec, int track, unsigned int numVectors, double *query, double *data_buffer, double **D, double **DD) { |
109 unsigned int j, k, l, w; | 110 unsigned int j, k, l, w; |
110 double *dp, *qp, *sp; | 111 double *dp, *qp, *sp; |
112 double a,b, tmp1; | |
113 #ifdef SYMMETRIC_KL | |
114 double tmp2; | |
115 #endif | |
111 | 116 |
112 const unsigned wL = spec->qid.sequence_length; | 117 const unsigned wL = spec->qid.sequence_length; |
113 | 118 |
114 for(j = 0; j < numVectors; j++) { | 119 for(j = 0; j < numVectors; j++) { |
115 // Sum products matrix | 120 // Sum products matrix |
125 sp = data_buffer + k * adb->header->dim; | 130 sp = data_buffer + k * adb->header->dim; |
126 DD[j][k] = 0.0; // Initialize matched filter array | 131 DD[j][k] = 0.0; // Initialize matched filter array |
127 dp = &D[j][k]; // point to correlation cell j,k | 132 dp = &D[j][k]; // point to correlation cell j,k |
128 *dp = 0.0; // initialize correlation cell | 133 *dp = 0.0; // initialize correlation cell |
129 l = adb->header->dim; // size of vectors | 134 l = adb->header->dim; // size of vectors |
130 while(l--) | 135 if (spec->params.distance!=ADB_DISTANCE_KULLBACK_LEIBLER_DIVERGENCE){ |
131 *dp += *qp++ * *sp++; | 136 while(l--) |
137 *dp += *qp++ * *sp++; | |
138 } | |
139 else{ // KL | |
140 while(l--){ | |
141 a = *qp++; | |
142 b = *sp++; | |
143 tmp1 = a * log( a / b ); | |
144 if(isnan(tmp1)) | |
145 tmp1=0.0; | |
146 #ifdef SYMMETRIC_KL | |
147 tmp2 = b * log( b / a ); | |
148 if(isnan(tmp2)) | |
149 tmp2=0.0; | |
150 *dp += ( tmp1 + tmp2 ) / 2.0; | |
151 #else | |
152 *dp += tmp1; | |
153 #endif | |
154 } | |
155 } | |
132 } | 156 } |
133 | 157 |
134 double* spd; | 158 double* spd; |
135 if(!(spec->refine.flags & ADB_REFINE_HOP_SIZE)) { | 159 if(!(spec->refine.flags & ADB_REFINE_HOP_SIZE)) { |
136 for(w = 0; w < wL; w++) { | 160 for(w = 0; w < wL; w++) { |
459 uint32_t sPos = pp.spos; // index into l2norm table | 483 uint32_t sPos = pp.spos; // index into l2norm table |
460 // Test power thresholds before computing distance | 484 // Test power thresholds before computing distance |
461 if( ( (!power_refine) || audiodb_powers_acceptable(&spec->refine, qpointers->power[qPos], dbpointers.power[sPos])) && | 485 if( ( (!power_refine) || audiodb_powers_acceptable(&spec->refine, qpointers->power[qPos], dbpointers.power[sPos])) && |
462 ( qPos<qpointers->nvectors-sequence_length+1 && sPos<(*adb->track_lengths)[pp.trackID]-sequence_length+1 ) ){ | 486 ( qPos<qpointers->nvectors-sequence_length+1 && sPos<(*adb->track_lengths)[pp.trackID]-sequence_length+1 ) ){ |
463 // Compute distance | 487 // Compute distance |
464 dist = audiodb_dot_product(query + qPos*adb->header->dim, dbdata + sPos*adb->header->dim, adb->header->dim*sequence_length); | 488 dist = 1.0e9; |
489 if (spec->params.distance==ADB_DISTANCE_EUCLIDEAN_NORMED || spec->params.distance==ADB_DISTANCE_EUCLIDEAN) | |
490 dist = audiodb_dot_product(query + qPos*adb->header->dim, dbdata + sPos*adb->header->dim, adb->header->dim*sequence_length); | |
491 else if(spec->params.distance==ADB_DISTANCE_KULLBACK_LEIBLER_DIVERGENCE) | |
492 dist = audiodb_kullback_leibler(query + qPos*adb->header->dim, dbdata + sPos*adb->header->dim, adb->header->dim*sequence_length); | |
465 double qn = qpointers->l2norm[qPos]; | 493 double qn = qpointers->l2norm[qPos]; |
466 double sn = dbpointers.l2norm[sPos]; | 494 double sn = dbpointers.l2norm[sPos]; |
467 switch(spec->params.distance) { | 495 switch(spec->params.distance) { |
468 case ADB_DISTANCE_EUCLIDEAN_NORMED: | 496 case ADB_DISTANCE_EUCLIDEAN_NORMED: |
469 dist = 2 - (2/(qn*sn))*dist; | 497 dist = 2 - (2/(qn*sn))*dist; |