00001
00006
00007
00008
00009
00010
00011
00012
00013
00353 #include "fisher.h"
00354 #include "gmm.h"
00355 #include "mathop.h"
00356
00357 #include <stdio.h>
00358 #include <stdlib.h>
00359 #include <string.h>
00360
00361 #ifdef VL_FISHER_INSTANTIATING
00362
00363 static vl_size
00364 VL_XCAT(_vl_fisher_encode_, SFX)
00365 (TYPE * enc,
00366 TYPE const * means, vl_size dimension, vl_size numClusters,
00367 TYPE const * covariances,
00368 TYPE const * priors,
00369 TYPE const * data, vl_size numData,
00370 int flags)
00371 {
00372 vl_size dim;
00373 vl_index i_cl, i_d;
00374 vl_size numTerms = 0 ;
00375 TYPE * posteriors ;
00376 TYPE * sqrtInvSigma;
00377
00378 assert(numClusters >= 1) ;
00379 assert(dimension >= 1) ;
00380
00381 posteriors = vl_malloc(sizeof(TYPE) * numClusters * numData);
00382 sqrtInvSigma = vl_malloc(sizeof(TYPE) * dimension * numClusters);
00383
00384 memset(enc, 0, sizeof(TYPE) * 2 * dimension * numClusters) ;
00385
00386 for (i_cl = 0 ; i_cl < (signed)numClusters ; ++i_cl) {
00387 for(dim = 0; dim < dimension; dim++) {
00388 sqrtInvSigma[i_cl*dimension + dim] = sqrt(1.0 / covariances[i_cl*dimension + dim]);
00389 }
00390 }
00391
00392 VL_XCAT(vl_get_gmm_data_posteriors_, SFX)(posteriors, numClusters, numData,
00393 priors,
00394 means, dimension,
00395 covariances,
00396 data) ;
00397
00398
00399 if (flags & VL_FISHER_FLAG_FAST) {
00400 for(i_d = 0; i_d < (signed)numData; i_d++) {
00401
00402 vl_index best = 0 ;
00403 TYPE bestValue = posteriors[i_d * numClusters] ;
00404 for (i_cl = 1 ; i_cl < (signed)numClusters; ++ i_cl) {
00405 TYPE p = posteriors[i_cl + i_d * numClusters] ;
00406 if (p > bestValue) {
00407 bestValue = p ;
00408 best = i_cl ;
00409 }
00410 }
00411
00412 for (i_cl = 0 ; i_cl < (signed)numClusters; ++ i_cl) {
00413 posteriors[i_cl + i_d * numClusters] =
00414 (TYPE)(i_cl == best) ;
00415 }
00416 }
00417 }
00418
00419 #if defined(_OPENMP)
00420 #pragma omp parallel for default(shared) private(i_cl, i_d, dim) num_threads(vl_get_max_threads()) reduction(+:numTerms)
00421 #endif
00422 for(i_cl = 0; i_cl < (signed)numClusters; ++ i_cl) {
00423 TYPE uprefix;
00424 TYPE vprefix;
00425
00426 TYPE * uk = enc + i_cl*dimension ;
00427 TYPE * vk = enc + i_cl*dimension + numClusters * dimension ;
00428
00429
00430
00431
00432
00433
00434
00435
00436 if (priors[i_cl] < 1e-6) { continue ; }
00437
00438 for(i_d = 0; i_d < (signed)numData; i_d++) {
00439 TYPE p = posteriors[i_cl + i_d * numClusters] ;
00440 if (p < 1e-6) continue ;
00441 numTerms += 1;
00442 for(dim = 0; dim < dimension; dim++) {
00443 TYPE diff = data[i_d*dimension + dim] - means[i_cl*dimension + dim] ;
00444 diff *= sqrtInvSigma[i_cl*dimension + dim] ;
00445 *(uk + dim) += p * diff ;
00446 *(vk + dim) += p * (diff * diff - 1);
00447 }
00448 }
00449
00450 if (numData > 0) {
00451 uprefix = 1/(numData*sqrt(priors[i_cl]));
00452 vprefix = 1/(numData*sqrt(2*priors[i_cl]));
00453 for(dim = 0; dim < dimension; dim++) {
00454 *(uk + dim) = *(uk + dim) * uprefix;
00455 *(vk + dim) = *(vk + dim) * vprefix;
00456 }
00457 }
00458 }
00459
00460 vl_free(posteriors);
00461 vl_free(sqrtInvSigma) ;
00462
00463 if (flags & VL_FISHER_FLAG_SQUARE_ROOT) {
00464 for(dim = 0; dim < 2 * dimension * numClusters ; dim++) {
00465 TYPE z = enc [dim] ;
00466 if (z >= 0) {
00467 enc[dim] = VL_XCAT(vl_sqrt_, SFX)(z) ;
00468 } else {
00469 enc[dim] = - VL_XCAT(vl_sqrt_, SFX)(- z) ;
00470 }
00471 }
00472 }
00473
00474 if (flags & VL_FISHER_FLAG_NORMALIZED) {
00475 TYPE n = 0 ;
00476 for(dim = 0 ; dim < 2 * dimension * numClusters ; dim++) {
00477 TYPE z = enc [dim] ;
00478 n += z * z ;
00479 }
00480 n = VL_XCAT(vl_sqrt_, SFX)(n) ;
00481 n = VL_MAX(n, 1e-12) ;
00482 for(dim = 0 ; dim < 2 * dimension * numClusters ; dim++) {
00483 enc[dim] /= n ;
00484 }
00485 }
00486
00487 return numTerms ;
00488 }
00489
00490 #else
00491
00492
00493 #ifndef __DOXYGEN__
00494 #define FLT VL_TYPE_FLOAT
00495 #define TYPE float
00496 #define SFX f
00497 #define VL_FISHER_INSTANTIATING
00498 #include "fisher.c"
00499
00500 #define FLT VL_TYPE_DOUBLE
00501 #define TYPE double
00502 #define SFX d
00503 #define VL_FISHER_INSTANTIATING
00504 #include "fisher.c"
00505 #endif
00506
00507
00508 #endif
00509
00510
00511 #ifndef VL_FISHER_INSTANTIATING
00512
00548 VL_EXPORT vl_size
00549 vl_fisher_encode
00550 (void * enc, vl_type dataType,
00551 void const * means, vl_size dimension, vl_size numClusters,
00552 void const * covariances,
00553 void const * priors,
00554 void const * data, vl_size numData,
00555 int flags
00556 )
00557 {
00558 switch(dataType) {
00559 case VL_TYPE_FLOAT:
00560 return _vl_fisher_encode_f
00561 ((float *) enc,
00562 (float const *) means, dimension, numClusters,
00563 (float const *) covariances,
00564 (float const *) priors,
00565 (float const *) data, numData,
00566 flags);
00567 case VL_TYPE_DOUBLE:
00568 return _vl_fisher_encode_d
00569 ((double *) enc,
00570 (double const *) means, dimension, numClusters,
00571 (double const *) covariances,
00572 (double const *) priors,
00573 (double const *) data, numData,
00574 flags);
00575 break;
00576 default:
00577 abort();
00578 }
00579 }
00580
00581 #endif
00582
00583 #undef SFX
00584 #undef TYPE
00585 #undef FLT
00586 #undef VL_FISHER_INSTANTIATING