core/vpdl/vpdt/vpdt_update_gaussian.h
Go to the documentation of this file.
00001 // This is core/vpdl/vpdt/vpdt_update_gaussian.h
00002 #ifndef vpdt_update_gaussian_h_
00003 #define vpdt_update_gaussian_h_
00004 //:
00005 // \file
00006 // \author Matt Leotta (mleotta@lems.brown.edu)
00007 // \date March 7, 2009
00008 // \brief Iterative updating of Gaussians
00009 
00010 
00011 #include <vpdl/vpdt/vpdt_field_traits.h>
00012 #include <vpdl/vpdt/vpdt_gaussian.h>
00013 
00014 
00015 //==============================================================================
00016 // A helper class used to update the various covariance types
00017 
00018 //: Specialized classes to update covariance of different types
00019 // \note the \c Disambiguate template parameter is a dummy used to
00020 //  prevent ambiguous instantiations
00021 template<class F, class Covar, class Disambiguate= void>
00022 struct vpdt_update_covariance {};
00023 
00024 //: Specialized classes to update covariance of different types
00025 template<class F>
00026 struct vpdt_update_covariance<F, typename vpdt_eigen_sym_matrix_gen<F>::type,
00027                               typename vpdt_field_traits<F>::type_is_vector>
00028 {
00029   //: the data type used for covariance
00030   typedef typename vpdt_eigen_sym_matrix_gen<F>::type Covar;
00031   //: the data type used for scalars
00032   typedef typename vpdt_field_traits<F>::scalar_type T;
00033   //: the data type used for vectors
00034   typedef typename vpdt_field_traits<F>::vector_type vector;
00035 
00036   //: update the covariance matrix with a weighted vector difference
00037   static inline void increment(Covar& c, const T& s, const vector& d)
00038   {
00039     // FIXME this could be more efficient if we could iteratively update the eigen decomposition
00040     typename vpdt_field_traits<F>::matrix_type m;
00041     c.form_matrix(m);
00042     m += s * outer_product(d,d);
00043     c.set_matrix(m);
00044   }
00045 
00046   //: enforce a minimum covariance value in all dimensions
00047   static inline void enforce_min(Covar& c, const T& min_var)
00048   {
00049     vector ev = c.eigenvalues();
00050     const unsigned int dim = vpdt_size(ev);
00051     for (unsigned int i=0; i<dim; ++i){
00052       T& evi = vpdt_index(ev,i);
00053       if (evi < min_var)
00054         evi = min_var;
00055     }
00056     c.set_eigenvalues(ev);
00057   }
00058 };
00059 
00060 
00061 //: Specialized classes to update covariance of different types
00062 template<class F>
00063 struct vpdt_update_covariance<F, typename vpdt_field_traits<F>::vector_type,
00064                               typename vpdt_field_traits<F>::type_is_vector>
00065 {
00066   //: the data type used for scalars
00067   typedef typename vpdt_field_traits<F>::scalar_type T;
00068   //: the data type used for vectors
00069   typedef typename vpdt_field_traits<F>::vector_type vector;
00070 
00071   //: update the covariance matrix with a weighted vector difference
00072   static inline void increment(vector& c, const T& s, const vector& d)
00073   {
00074     c += s * element_product(d,d);
00075   }
00076 
00077   //: enforce a minimum covariance value in all dimensions
00078   static inline void enforce_min(vector& c, const T& min_var)
00079   {
00080     const unsigned int dim = vpdt_size(c);
00081     for (unsigned int i=0; i<dim; ++i){
00082       T& ci = vpdt_index(c,i);
00083       if (ci < min_var)
00084         ci = min_var;
00085     }
00086   }
00087 };
00088 
00089 
00090 //: Specialized classes to update covariance of different types
00091 template<class F>
00092 struct vpdt_update_covariance<F, typename vpdt_field_traits<F>::scalar_type,
00093                               typename vpdt_field_traits<F>::type_is_vector>
00094 {
00095   //: the data type used for scalars
00096   typedef typename vpdt_field_traits<F>::scalar_type T;
00097   //: the data type used for vectors
00098   typedef typename vpdt_field_traits<F>::vector_type vector;
00099 
00100   //: update the covariance matrix with a weighted vector difference
00101   static inline void increment(T& c, const T& s, const vector& d)
00102   {
00103     c += s * dot_product(d,d);
00104   }
00105 
00106   //: enforce a minimum covariance value in all dimensions
00107   static inline void enforce_min(T& c, const T& min_var)
00108   {
00109     if (c<min_var)
00110       c = min_var;
00111   }
00112 };
00113 
00114 
00115 //: Specialized classes to update covariance of different types
00116 template<class F>
00117 struct vpdt_update_covariance<F, typename vpdt_field_traits<F>::scalar_type,
00118                               typename vpdt_field_traits<F>::type_is_scalar>
00119 {
00120   //: the data type used for scalars
00121   typedef typename vpdt_field_traits<F>::scalar_type T;
00122 
00123   //: update the covariance matrix with a weighted vector difference
00124   static inline void increment(T& c, const T& s, const T& d)
00125   {
00126     c += s*d*d;
00127   }
00128 
00129   //: enforce a minimum covariance value in all dimensions
00130   static inline void enforce_min(T& c, const T& min_var)
00131   {
00132     if (c<min_var)
00133       c = min_var;
00134   }
00135 };
00136 
00137 
00138 //==============================================================================
00139 // The Gaussian update functions
00140 
00141 
00142 //: Update the statistics given a 1D Gaussian distribution and a learning rate
00143 // \note if rho = 1/(num observations) then this just an online cumulative average
00144 template <class F, class Covar>
00145 void vpdt_update_gaussian(vpdt_gaussian<F,Covar>& gaussian,
00146                           typename vpdt_field_traits<F>::scalar_type rho,
00147                           const F& sample )
00148 {
00149   typedef typename vpdt_field_traits<F>::scalar_type T;
00150   typedef typename vpdt_field_traits<F>::vector_type vector;
00151 
00152   // the complement of rho (i.e. rho+rho_comp=1.0)
00153   T rho_comp = T(1) - rho;
00154   // the difference vector between the sample and the mean
00155   vector diff = sample - gaussian.mean;
00156 
00157   // update the covariance
00158   vpdt_update_covariance<F,Covar>::increment(gaussian.covar, rho, diff);
00159   gaussian.covar *= rho_comp;
00160 
00161   // update the mean
00162   gaussian.mean += (rho * diff);
00163 }
00164 
00165 
00166 //: Update the statistics given a Gaussian distribution and a learning rate
00167 // \param min_var forces the variance to stay above this limit
00168 // \note If the same sample is observed repeatedly, the variances will
00169 // converge to the minimum value parameter rather than zero.
00170 template <class F, class Covar>
00171 void vpdt_update_gaussian(vpdt_gaussian<F,Covar>& gaussian,
00172                           typename vpdt_field_traits<F>::scalar_type rho,
00173                           const F& sample,
00174                           typename vpdt_field_traits<F>::scalar_type min_var)
00175 {
00176   vpdt_update_gaussian(gaussian, rho, sample);
00177   vpdt_update_covariance<F,Covar>::enforce_min(gaussian.covar, min_var);
00178 }
00179 
00180 
00181 #endif // vpdt_update_gaussian_h_