fisher.c
Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2013 David Novotny and Andrea Vedaldi.
00008 All rights reserved.
00009 
00010 This file is part of the VLFeat library and is made available under
00011 the terms of the BSD license (see the COPYING file).
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   /* sparsify posterior assignments with the FAST option */
00399   if (flags & VL_FISHER_FLAG_FAST) {
00400     for(i_d = 0; i_d < (signed)numData; i_d++) {
00401       /* find largest posterior assignment for datum i_d */
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       /* make all posterior assignments zero but the best one */
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     If the GMM component is degenerate and has a null prior, then it
00431     must have null posterior as well. Hence it is safe to skip it.  In
00432     practice, we skip over it even if the prior is very small; if by
00433     any chance a feature is assigned to such a mode, then its weight
00434     would be very high due to the division by priors[i_cl] below.
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 /* not VL_FISHER_INSTANTIATING */
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 /* not VL_FISHER_INSTANTIATING */
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 /* not VL_FISHER_INSTANTIATING */
00581 #endif
00582 
00583 #undef SFX
00584 #undef TYPE
00585 #undef FLT
00586 #undef VL_FISHER_INSTANTIATING


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51