00001
00002 #ifndef bsta_fit_gaussian_h_
00003 #define bsta_fit_gaussian_h_
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <bsta/bsta_gaussian.h>
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_iostream.h>
00022
00023
00024 template <class T>
00025 void bsta_fit_gaussian(vcl_vector<T> const& samples, vcl_vector<T> const& sample_weights, bsta_gaussian_sphere<T,1>& gaussian)
00026 {
00027
00028 if (samples.size() != sample_weights.size()) {
00029 vcl_cerr << "bsta_fit_gaussian : error - samples.size == " << samples.size()
00030 << ", sample_weights.size == " << sample_weights.size() << vcl_endl;
00031 return;
00032 }
00033
00034 const unsigned int nobs = (unsigned int)samples.size();
00035 T weight_sum = 0;
00036
00037
00038 T mean = 0;
00039 for (unsigned int i=0; i<nobs; ++i) {
00040 mean += samples[i]*sample_weights[i];
00041 weight_sum += sample_weights[i];
00042 }
00043 if (weight_sum > 0) {
00044 mean /= weight_sum;
00045 }
00046 else {
00047
00048 return;
00049 }
00050
00051
00052 T var = 0;
00053 T weight_norm_sqrd_sum = 0;
00054
00055 for (unsigned int i=0; i<nobs; ++i) {
00056 const T diff = samples[i] - mean;
00057 const T weight_norm = sample_weights[i] / weight_sum;
00058 var += diff*diff*weight_norm;
00059 weight_norm_sqrd_sum += weight_norm*weight_norm;
00060 }
00061 if( (T)(1-weight_norm_sqrd_sum) > (T) 0 )
00062 var /= ((T)1 - weight_norm_sqrd_sum);
00063 else
00064 var = (T) 0;
00065
00066 gaussian.set_mean(mean);
00067 if(var > 0)
00068 gaussian.set_covar(var);
00069 }
00070
00071
00072 template <class T, unsigned n>
00073 void bsta_fit_gaussian(vcl_vector<vnl_vector_fixed<T,n> > const& samples, vcl_vector<T> const& sample_weights,
00074 bsta_gaussian_sphere<T,n>& gaussian )
00075 {
00076
00077 if (samples.size() != sample_weights.size()) {
00078 vcl_cerr << "bsta_fit_gaussian : error - samples.size == " << samples.size()
00079 << ", sample_weights.size == " << sample_weights.size() << vcl_endl;
00080 return;
00081 }
00082
00083 const unsigned int nobs = samples.size();
00084 T weight_sum = 0;
00085
00086
00087 vnl_vector_fixed<T,n> mean((T)0);
00088 for (unsigned int i=0; i<nobs; ++i) {
00089 mean += samples[i]*sample_weights[i];
00090 weight_sum += sample_weights[i];
00091 }
00092 if (weight_sum > 0) {
00093 mean /= weight_sum;
00094 }
00095 else {
00096
00097 return;
00098 }
00099
00100
00101 T var = 0;
00102 T weight_norm_sqrd_sum = 0;
00103
00104 for (unsigned int i=0; i<nobs; ++i) {
00105 const vnl_vector_fixed<T,n> diff = samples[i] - mean;
00106 const T weight_norm = sample_weights[i] / weight_sum;
00107 var += dot_product(diff,diff)*weight_norm/n;
00108 weight_norm_sqrd_sum += weight_norm*weight_norm;
00109 }
00110 var /= ((T)1 - weight_norm_sqrd_sum);
00111
00112 gaussian.set_mean(mean);
00113 gaussian.set_covar(var);
00114 }
00115
00116
00117
00118 template <class T, unsigned n>
00119 void bsta_fit_gaussian(vcl_vector<vnl_vector_fixed<T,n> > const& samples, vcl_vector<T> const& sample_weights,
00120 bsta_gaussian_indep<T,n>& gaussian)
00121 {
00122 const unsigned int nobs = samples.size();
00123
00124 if (nobs != sample_weights.size()) {
00125 vcl_cerr << "bsta_fit_gaussian : error - samples.size == " << samples.size()
00126 << ", sample_weights.size == " << sample_weights.size() << vcl_endl;
00127 return;
00128 }
00129
00130
00131 T weight_sum = 0;
00132 vnl_vector_fixed<T,n> mean((T)0);
00133 for (unsigned int i=0; i<nobs; ++i) {
00134 mean += samples[i]*sample_weights[i];
00135 weight_sum += sample_weights[i];
00136 }
00137 if (weight_sum > 0) {
00138 mean /= weight_sum;
00139 }
00140 else {
00141
00142 return;
00143 }
00144
00145
00146 vnl_vector_fixed<T,n> diag_covar((T)0);
00147 T weight_norm_sqrd_sum = 0;
00148
00149 for (unsigned int i=0; i<nobs; ++i) {
00150 const vnl_vector_fixed<T,n> diff = samples[i] - mean;
00151 const T weight_norm = sample_weights[i] / weight_sum;
00152 diag_covar += element_product(diff,diff)*weight_norm;
00153 weight_norm_sqrd_sum += weight_norm*weight_norm;
00154 }
00155 diag_covar /= ((T)1 - weight_norm_sqrd_sum);
00156
00157 gaussian.set_mean(mean);
00158 gaussian.set_covar(diag_covar);
00159 }
00160
00161
00162
00163 template <class T, unsigned n>
00164 void bsta_fit_gaussian(vcl_vector<vnl_vector_fixed<T,n> > const& samples, vcl_vector<T> const& sample_weights,
00165 bsta_gaussian_full<T,n>& gaussian)
00166 {
00167 const unsigned int nobs = samples.size();
00168
00169 if (nobs != sample_weights.size()) {
00170 vcl_cerr << "bsta_fit_gaussian : error - samples.size == " << samples.size()
00171 << ", sample_weights.size == " << sample_weights.size() << vcl_endl;
00172 return;
00173 }
00174
00175
00176 T weight_sum = 0;
00177 vnl_vector_fixed<T,n> mean((T)0);
00178 for (unsigned int i=0; i<nobs; ++i) {
00179 mean += samples[i]*sample_weights[i];
00180 weight_sum += sample_weights[i];
00181 }
00182 if (weight_sum > 0) {
00183 mean /= weight_sum;
00184 }
00185 else {
00186
00187 return;
00188 }
00189
00190
00191 vnl_matrix_fixed<T,n,n> covar((T)0);
00192 T weight_norm_sqrd_sum = 0;
00193
00194 for (unsigned int i=0; i<nobs; ++i) {
00195 const vnl_vector_fixed<T,n> diff = samples[i] - mean;
00196 const T weight_norm = sample_weights[i] / weight_sum;
00197 covar += outer_product(diff,diff)*weight_norm;
00198 weight_norm_sqrd_sum += weight_norm*weight_norm;
00199 }
00200 covar /= ((T)1 - weight_norm_sqrd_sum);
00201
00202 gaussian.set_mean(mean);
00203 gaussian.set_covar(covar);
00204 }
00205
00206
00207 template<class T>
00208 T clip_covar(T var, T min_var)
00209 { return vcl_max(var,min_var); }
00210
00211
00212 template<class T, unsigned n>
00213 vnl_vector_fixed<T,n> clip_covar(vnl_vector_fixed<T,n> covar, vnl_vector_fixed<T,n> min_covar)
00214 {
00215 vnl_vector_fixed<T,n> maxval;
00216 for (unsigned int i=0; i<n; ++i) {
00217 maxval[i] = vcl_max(covar[i],min_covar[i]);
00218 }
00219 return maxval;
00220 }
00221
00222
00223 template<class T, unsigned n>
00224 vnl_matrix_fixed<T,n,n> clip_covar(vnl_matrix_fixed<T,n,n> covar, vnl_matrix_fixed<T,n,n> min_covar)
00225 {
00226 vnl_matrix_fixed<T,n,n> maxval;
00227 for (unsigned int i=0; i<n; ++i) {
00228 for (unsigned int j=0; j<n; ++j) {
00229 maxval(i,j) = vcl_max(covar(i,j),min_covar(i,j));
00230 }
00231 }
00232 return maxval;
00233 }
00234
00235
00236
00237
00238 template <class gauss_type>
00239 void bsta_fit_gaussian(vcl_vector<typename gauss_type::vector_type> const& samples,
00240 vcl_vector<typename gauss_type::math_type> const& sample_probs,
00241 vcl_vector<typename gauss_type::math_type> const& prob_densities_other,
00242 gauss_type& gaussian, typename gauss_type::covar_type min_covar)
00243 {
00244
00245 const unsigned int nobs = (unsigned int)samples.size();
00246 if (nobs != sample_probs.size()) {
00247 vcl_cerr << "bsta_fit_gaussian : error - samples.size == " << samples.size()
00248 << ", sample_probs.size == " << sample_probs.size() << vcl_endl;
00249 return;
00250 }
00251 if (nobs != prob_densities_other.size()) {
00252 vcl_cerr << "bsta_fit_gaussian : error - samples.size == " << samples.size()
00253 << ", prob_densities_other.size == " << prob_densities_other.size() << vcl_endl;
00254 return;
00255 }
00256 if (nobs == 0) {
00257
00258 return;
00259 }
00260
00261
00262 typedef typename gauss_type::math_type T;
00263
00264 vcl_vector<T> sample_weights = sample_probs;
00265 bsta_fit_gaussian(samples, sample_weights, gaussian);
00266
00267 const unsigned int max_its = 100;
00268 const T max_converged_weight_change = 1e-4f;
00269 for (unsigned int i=0; i<max_its; ++i)
00270 {
00271 T max_weight_change = 0;
00272 T sample_weight_sum = 0;
00273
00274 for (unsigned int n=0; n<nobs; ++n) {
00275
00276
00277
00278 const T P1 = sample_probs[n] * gaussian.prob_density(samples[n]);
00279 const T P2 = prob_densities_other[n];
00280 const T normalizing_factor = P1 + P2;
00281 T new_sample_weight = 0;
00282 if (normalizing_factor > 1e-6) {
00283 new_sample_weight = P1 / normalizing_factor;
00284 }
00285
00286 T weight_delta = vcl_fabs(sample_weights[n] - new_sample_weight);
00287 if (weight_delta > max_weight_change) {
00288 max_weight_change = weight_delta;
00289 }
00290 sample_weights[n] = new_sample_weight;
00291 sample_weight_sum += new_sample_weight;
00292 }
00293
00294 if (max_weight_change < max_converged_weight_change) {
00295 break;
00296 }
00297
00298 bsta_fit_gaussian(samples, sample_weights, gaussian);
00299
00300 gaussian.set_covar(clip_covar(gaussian.covar(),min_covar));
00301 }
00302 }
00303
00304 #endif // bsta_fit_gaussian_h_