contrib/brl/bbas/bsta/algo/bsta_beta_updater.txx
Go to the documentation of this file.
00001 #ifndef bsta_beta_updater_txx_
00002 #define bsta_beta_updater_txx_
00003 //:
00004 // \file
00005 #include "bsta_beta_updater.h"
00006 #include <vcl_limits.h>
00007 
00008 
00009 //: The update function
00010 template <class mix_dist_>
00011 void
00012 bsta_mix_beta_updater<mix_dist_>::update( mix_dist_& mix, const vector_& sample, T alpha ) const
00013 {
00014   unsigned num_components = mix.num_components();
00015 
00016   // prune components by probability distribution threshold
00017   static vcl_vector<T> probs;
00018   probs.resize(num_components,T(0));
00019   static vcl_vector<unsigned int> matched;
00020   matched.clear();
00021 
00022   for (unsigned int i=0; i<num_components; ++i) {
00023     obs_dist_& d = mix.distribution(i);
00024     T p = d.prob_density(sample);
00025     T dist_p=d.distance(sample);
00026     if (dist_p > -p_thresh_){
00027       matched.push_back(i);
00028       probs[i] = p; // ???? SHOULD BE p ?? initially these are distances, not probabilities
00029     }
00030   }
00031 
00032   // if matches are not good add a new component
00033   if (matched.empty()) {
00034     insert(mix,sample,alpha);
00035     mix.normalize_weights();
00036   }
00037   else
00038   {
00039     // update the weights
00040     for (unsigned int i=0; i<num_components; ++i) {
00041       T weight = (T(1)-alpha) * mix.weight(i);
00042       mix.set_weight(i,weight);
00043     }
00044     // special case of 1 match - don't need to compute probabilites
00045     if (matched.size() == 1) {
00046       unsigned int m_idx = matched.front();
00047       mix.set_weight(m_idx,mix.weight(m_idx)+alpha);
00048       obs_dist_& b = mix.distribution(m_idx);
00049       b.num_observations += T(1);
00050       T rho =(T(1)-alpha)/b.num_observations + alpha;
00051       bsta_update_beta(b, rho, sample);
00052     }
00053     else {
00054       // compute probabilites for each match
00055       typedef typename vcl_vector<unsigned int>::iterator m_itr;
00056       T sum_probs = T(0);
00057       for (m_itr itr = matched.begin(); itr != matched.end(); ++itr) {
00058         const unsigned int i = *itr;
00059                                    // obs_dist_& b = mix.distribution(i);
00060         probs[i] *= mix.weight(i); //?????? b.dist_prob_density(probs[i]) * mix.weight(i);
00061         sum_probs += probs[i];
00062       }
00063       // update each match
00064       for (m_itr itr = matched.begin(); itr != matched.end(); ++itr) {
00065         const unsigned int i = *itr;
00066         if (sum_probs != 0) {
00067           probs[i] /= sum_probs;
00068         }
00069         mix.set_weight(i,mix.weight(i)+alpha*probs[i]);
00070         obs_dist_& b = mix.distribution(i);
00071         b.num_observations += probs[i];
00072         T rho = probs[i] * ((1-alpha)/b.num_observations + alpha);
00073         bsta_update_beta(b, rho, sample);
00074       }
00075     }
00076   }
00077 
00078   mix.sort(bsta_beta_fitness<dist_>::order);
00079 
00080   // try to clean up gaussian components with weights that have converged to zero
00081   if (mix.weight(mix.num_components()-1) < vcl_numeric_limits<T>::epsilon()) {
00082     mix.remove_last();
00083     T sum = 0;
00084     for (unsigned int i=0; i<mix.num_components(); ++i) {
00085       sum += mix.weight(i);
00086     }
00087     vcl_cout << "removed, total weight = " << sum << vcl_endl;
00088     mix.normalize_weights();
00089   }
00090 }
00091 
00092 #define BSTA_MIX_BETA_UPDATER_INSTANTIATE(T) \
00093 template class bsta_mix_beta_updater<T >
00094 
00095 #endif