contrib/brl/bbas/bsta/algo/bsta_gaussian_updater.h
Go to the documentation of this file.
00001 // This is brl/bbas/bsta/algo/bsta_gaussian_updater.h
00002 #ifndef bsta_gaussian_updater_h_
00003 #define bsta_gaussian_updater_h_
00004 //:
00005 // \file
00006 // \brief Iterative updating of Gaussians
00007 // \author Matt Leotta (mleotta@lems.brown.edu)
00008 // \date February 22, 2006
00009 //
00010 // \verbatim
00011 //  Modifications
00012 //   Jun 18, 2008 - Matt Leotta -- Adjusted such that min_var is a hard minimum
00013 //                                 instead of a minimum in the limit
00014 // \endverbatim
00015 
00016 #include <bsta/bsta_gaussian_sphere.h>
00017 #include <bsta/bsta_gaussian_indep.h>
00018 #include <bsta/bsta_gaussian_full.h>
00019 #include <bsta/bsta_mixture.h>
00020 #include <bsta/bsta_attributes.h>
00021 #include <vcl_algorithm.h>
00022 
00023 
00024 //: Update the statistics given a 1D Gaussian distribution and a learning rate
00025 // \note if rho = 1/(num observations) then this just an online cumulative average
00026 template <class T>
00027 void bsta_update_gaussian(bsta_gaussian_sphere<T,1>& gaussian, T rho,
00028                           const T& sample )
00029 {
00030   // the complement of rho (i.e. rho+rho_comp=1.0)
00031   T rho_comp = 1.0f - rho;
00032   // compute the updated mean
00033   const T& old_mean = gaussian.mean();
00034 
00035   T diff = sample - old_mean;
00036   T new_var = rho_comp * gaussian.var();
00037   new_var += (rho * rho_comp) * diff*diff;
00038 
00039   gaussian.set_var(new_var);
00040   gaussian.set_mean((old_mean) +  (rho * diff));
00041 }
00042 
00043 
00044 //: Update the statistics given a Gaussian distribution and a learning rate
00045 // \note if rho = 1/(num observations) then this just an online cumulative average
00046 template <class T, unsigned n>
00047 void bsta_update_gaussian(bsta_gaussian_sphere<T,n>& gaussian, T rho,
00048                           const vnl_vector_fixed<T,n>& sample )
00049 {
00050   // the complement of rho (i.e. rho+rho_comp=1.0)
00051   T rho_comp = 1.0f - rho;
00052   // compute the updated mean
00053   const vnl_vector_fixed<T,n>& old_mean = gaussian.mean();
00054 
00055   vnl_vector_fixed<T,n> diff(sample - old_mean);
00056   T new_var = rho_comp * gaussian.var();
00057   new_var += (rho * rho_comp) * dot_product(diff,diff);
00058 
00059   gaussian.set_var(new_var);
00060   gaussian.set_mean((old_mean) +  (rho * diff));
00061 }
00062 
00063 
00064 //: Update the statistics given a Gaussian distribution and a learning rate
00065 // \note if rho = 1/(num observations) then this just an online cumulative average
00066 template <class T, unsigned n>
00067 void bsta_update_gaussian(bsta_gaussian_indep<T,n>& gaussian, T rho,
00068                           const vnl_vector_fixed<T,n>& sample )
00069 {
00070   // the complement of rho (i.e. rho+rho_comp=1.0)
00071   T rho_comp = 1.0f - rho;
00072   // compute the updated mean
00073   const vnl_vector_fixed<T,n>& old_mean = gaussian.mean();
00074 
00075   vnl_vector_fixed<T,n> diff(sample - old_mean);
00076 
00077   vnl_vector_fixed<T,n> new_covar(rho_comp * gaussian.diag_covar());
00078   new_covar += (rho * rho_comp) * element_product(diff,diff);
00079 
00080   gaussian.set_covar(new_covar);
00081   gaussian.set_mean((old_mean) +  (rho * diff));
00082 }
00083 
00084 
00085 //: Update the statistics given a Gaussian distribution and a learning rate
00086 // \note if rho = 1/(num observations) then this just an online cumulative average
00087 template <class T, unsigned n>
00088 void bsta_update_gaussian(bsta_gaussian_full<T,n>& gaussian, T rho,
00089                           const vnl_vector_fixed<T,n>& sample )
00090 {
00091   // the complement of rho (i.e. rho+rho_comp=1.0)
00092   T rho_comp = 1.0f - rho;
00093   // compute the updated mean
00094   const vnl_vector_fixed<T,n>& old_mean = gaussian.mean();
00095 
00096   vnl_vector_fixed<T,n> diff(sample - old_mean);
00097 
00098   vnl_matrix_fixed<T,n,n> new_covar(rho_comp * gaussian.covar());
00099   new_covar += (rho * rho_comp) * outer_product(diff,diff);
00100 
00101   gaussian.set_covar(new_covar);
00102   gaussian.set_mean((old_mean) +  (rho * diff));
00103 }
00104 
00105 
00106 //-----------------------------------------------------------------------------
00107 // The following versions allow for a lower limit on variances.
00108 // If the same sample is observed repeatedly, the variances will
00109 // converge to the minimum value parameter rather than zero.
00110 
00111 
00112 template <class T>
00113 inline T element_max(const T& a, const T& b)
00114 {
00115   return vcl_max(a,b);
00116 }
00117 
00118 
00119 //: element-wise minimum of vector.
00120 template <class T, unsigned n>
00121 vnl_vector_fixed<T,n> element_max(const vnl_vector_fixed<T,n>& a_vector,
00122                                   const T& b)
00123 {
00124   vnl_vector_fixed<T,n> min_vector;
00125   T* r = min_vector.data_block();
00126   const T* a = a_vector.data_block();
00127   for (unsigned i=0; i<n; ++i, ++r, ++a)
00128     *r = vcl_max(*a,b);
00129   return min_vector;
00130 }
00131 
00132 
00133 //: element-wise minimum of vector.
00134 template <class T, unsigned n>
00135 vnl_vector_fixed<T,n> element_max(const vnl_vector_fixed<T,n>& a_vector,
00136                                   const vnl_vector_fixed<T,n>& b_vector)
00137 {
00138   vnl_vector_fixed<T,n> min_vector;
00139   T* r = min_vector.data_block();
00140   const T* a = a_vector.data_block();
00141   const T* b = b_vector.data_block();
00142   for (unsigned i=0; i<n; ++i, ++r, ++a, ++b)
00143     *r = vcl_max(*a,*b);
00144   return min_vector;
00145 }
00146 
00147 
00148 //: element-wise minimum on the matrix diagonal.
00149 template <class T, unsigned n>
00150 vnl_matrix_fixed<T,n,n> element_max(const vnl_matrix_fixed<T,n,n>& a_matrix,
00151                                     const T& b)
00152 {
00153   vnl_matrix_fixed<T,n,n> min_matrix(a_matrix);
00154   T* r = min_matrix.data_block();
00155   const T* a = a_matrix.data_block();
00156   const unsigned step = n+1;
00157   for (unsigned i=0; i<n; ++i, r+=step, a+=step)
00158     *r = vcl_max(*a,b);
00159   return min_matrix;
00160 }
00161 
00162 
00163 //: element-wise minimum of matrix.
00164 template <class T, unsigned n>
00165 vnl_matrix_fixed<T,n,n> element_max(const vnl_matrix_fixed<T,n,n>& a_matrix,
00166                                     const vnl_matrix_fixed<T,n,n>& b_matrix)
00167 {
00168   vnl_matrix_fixed<T,n,n> min_matrix;
00169   T* r = min_matrix.data_block();
00170   const T* a = a_matrix.data_block();
00171   const T* b = b_matrix.data_block();
00172   const unsigned num_elements = n*n;
00173   for (unsigned i=0; i<num_elements; ++i, ++r, ++a, ++b)
00174     *r = vcl_max(*a,*b);
00175   return min_matrix;
00176 }
00177 
00178 
00179 //: Update the statistics given a Gaussian distribution and a learning rate
00180 // \param min_covar forces the covariance to stay above this limit
00181 // \note if rho = 1/(num observations) then this just an online cumulative average
00182 template <class gauss_>
00183 inline void bsta_update_gaussian(gauss_& gaussian,
00184                                  typename gauss_::math_type rho,
00185                                  const typename gauss_::vector_type& sample,
00186                                  const typename gauss_::covar_type& min_covar)
00187 {
00188   bsta_update_gaussian(gaussian, rho, sample);
00189   gaussian.set_covar(element_max(gaussian.covar(),min_covar));
00190 }
00191 
00192 
00193 //: Update the statistics given a Gaussian distribution and a learning rate
00194 // \param min_var forces all the variances to stay above this limit
00195 // \note if rho = 1/(num observations) then this just an online cumulative average
00196 template <class T, unsigned n>
00197 inline void bsta_update_gaussian(bsta_gaussian_indep<T,n>& gaussian, T rho,
00198                                  const vnl_vector_fixed<T,n>& sample,
00199                                  T min_var)
00200 {
00201   bsta_update_gaussian(gaussian, rho, sample);
00202   gaussian.set_covar(element_max(gaussian.covar(),min_var));
00203 }
00204 
00205 
00206 //: Update the statistics given a Gaussian distribution and a learning rate
00207 // \param min_var forces the diagonal covariance to stay above this limit
00208 // \note if rho = 1/(num observations) then this just an online cumulative average
00209 template <class T, unsigned n>
00210 inline void bsta_update_gaussian(bsta_gaussian_full<T,n>& gaussian, T rho,
00211                                  const vnl_vector_fixed<T,n>& sample,
00212                                  T min_var)
00213 {
00214   bsta_update_gaussian(gaussian, rho, sample);
00215   gaussian.set_covar(element_max(gaussian.covar(),min_var));
00216 }
00217 
00218 
00219 //-----------------------------------------------------------------------------
00220 
00221 
00222 //: An updater for statistically updating Gaussian distributions
00223 template <class gauss_>
00224 class bsta_gaussian_updater
00225 {
00226     typedef bsta_num_obs<gauss_> obs_gauss_;
00227     typedef typename gauss_::math_type T;
00228     typedef vnl_vector_fixed<T,gauss_::dimension> vector_;
00229   public:
00230 
00231     //: for compatibility with vpdl/vpdt
00232     typedef typename gauss_::field_type field_type;
00233     typedef gauss_ distribution_type;
00234 
00235 
00236     //: The main function
00237     // make the appropriate type casts and call a helper function
00238     void operator() ( obs_gauss_& d, const vector_& sample ) const
00239     {
00240       d.num_observations += T(1);
00241       bsta_update_gaussian(d, T(1)/d.num_observations, sample);
00242     }
00243 };
00244 
00245 
00246 //: An updater for updating Gaussian distributions with a moving window
00247 // When the number of samples exceeds the window size the most recent
00248 // samples contribute more toward the distribution.
00249 template <class gauss_>
00250 class bsta_gaussian_window_updater
00251 {
00252     typedef bsta_num_obs<gauss_> obs_gauss_;
00253     typedef typename gauss_::math_type T;
00254     typedef vnl_vector_fixed<T,gauss_::dimension> vector_;
00255   public:
00256 
00257     //: for compatibility with vpdl/vpdt
00258     typedef typename gauss_::field_type field_type;
00259     typedef gauss_ distribution_type;
00260 
00261 
00262     //: Constructor
00263     bsta_gaussian_window_updater(unsigned int ws) : window_size(ws) {}
00264 
00265     //: The main function
00266     // make the appropriate type casts and call a helper function
00267     void operator() ( obs_gauss_& d, const vector_& sample) const
00268     {
00269       if (d.num_observations < window_size)
00270         d.num_observations += T(1);
00271       bsta_update_gaussian(d, T(1)/d.num_observations, sample);
00272     }
00273 
00274     unsigned int window_size;
00275 };
00276 
00277 
00278 #endif // bsta_gaussian_updater_h_