00001 /*!@file Surprise/SurpriseModel.C a local (single-point) model of surprise */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Surprise/SurpriseModel.C $ 00035 // $Id: SurpriseModel.C 12962 2010-03-06 02:13:53Z irock $ 00036 // 00037 00038 #include "Surprise/SurpriseModel.H" 00039 00040 #include "Util/Assert.H" 00041 #include "Util/log.H" 00042 00043 // ###################################################################### 00044 // ###################################################################### 00045 // SurpriseModel implementation 00046 // ###################################################################### 00047 // ###################################################################### 00048 00049 SurpriseModel::SurpriseModel(const double updatefac, const double sampleval, 00050 const double samplevar) : 00051 itsUpdateFac(updatefac), itsInitialVal(sampleval), itsInitialVar(samplevar) 00052 { } 00053 00054 // ###################################################################### 00055 SurpriseModel::~SurpriseModel() 00056 { } 00057 00058 // ###################################################################### 00059 inline void SurpriseModel::init(const double updfac, 00060 const double sampleval, 00061 const double samplevar) 00062 { itsInitialVal = sampleval; itsInitialVar = samplevar; itsUpdateFac = updfac;} 00063 00064 // ###################################################################### 00065 inline void SurpriseModel::resetUpdFac(const double updfac) 00066 { itsUpdateFac = updfac; } 00067 00068 // ###################################################################### 00069 inline double SurpriseModel::surprise(const SurpriseModel& other) 00070 { LFATAL("Unimplemented! use derived classes instead"); return 0.0; } 00071 00072 // ###################################################################### 00073 inline void SurpriseModel::preComputeHyperParams(const SurpriseModel& sample) 00074 { LFATAL("Unimplemented! use derived classes instead"); } 00075 00076 // ###################################################################### 00077 inline void SurpriseModel::combineFrom(const Image<SurpriseModel>& models, 00078 const Image<float>& weights) 00079 { LFATAL("Unimplemented! use derived classes instead"); } 00080 00081 // ###################################################################### 00082 inline void SurpriseModel::combineFrom(const Image<SurpriseModel>& models, 00083 const Image<float>& weights, 00084 const Point2D<int>& pos, 00085 const int width, 00086 const int height, 00087 const int offset) 00088 { LFATAL("Unimplemented! use derived classes instead"); } 00089 00090 // ###################################################################### 00091 inline void SurpriseModel::setBias(const double slfac, 00092 const double ssfac, 00093 const SU_KL_BIAS klbias) 00094 { LFATAL("Unimplemented! use derived classes instead"); } 00095 00096 // ###################################################################### 00097 #define COMBINE_FROM(models,weights) \ 00098 ASSERT(models.isSameSize(weights)); \ 00099 COMBINE_INIT \ 00100 Image<COMBINE_TYPE>::const_iterator m = models.begin(), \ 00101 stop = models.end(); \ 00102 Image<float>::const_iterator w = weights.begin(); \ 00103 double wsum = 0.0; \ 00104 while(m != stop) \ 00105 { \ 00106 const double weight = double(*w++); \ 00107 COMBINE_UPDATE \ 00108 wsum += weight; \ 00109 ++m; \ 00110 } \ 00111 COMBINE_FINISH 00112 00113 // ###################################################################### 00114 // Notes: 00115 // (A) weight has been zero'd for low value so that if(weight) will 00116 // skip what would have been a below threshold weight 00117 // (B) offset gives us the formula: 00118 // w += width - pos.i + (2 * width + 1) * (height - pos.j) 00119 /* 00120 #define COMBINE_FROM_WMIN(models,weights,pos,width,height,offset) \ 00121 COMBINE_INIT \ 00122 Image<COMBINE_TYPE>::const_iterator m = models.begin(); \ 00123 Image<float>::const_iterator w = weights.begin(); \ 00124 w += offset - pos.i; \ 00125 double wsum = 0.0F; \ 00126 for (int j = 0; j < height; j ++) \ 00127 { \ 00128 for (int i = 0; i < width; i ++) \ 00129 { \ 00130 const double weight = *w++; \ 00131 if (weight) \ 00132 { \ 00133 COMBINE_UPDATE \ 00134 wsum += weight; \ 00135 } \ 00136 ++m; \ 00137 } \ 00138 w += width + 1; \ 00139 } \ 00140 COMBINE_FINISH 00141 */ 00142 #define COMBINE_FROM_WMIN(models,weights,pos,width,height,offset) \ 00143 COMBINE_INIT \ 00144 Image<COMBINE_TYPE>::const_iterator m = models.begin(); \ 00145 Image<float>::const_iterator w = weights.begin(); \ 00146 w += offset - pos.i; \ 00147 double wsum = 0.0F; \ 00148 for (int j = 0; j < height; j ++) \ 00149 { \ 00150 for (int i = 0; i < width; i ++) \ 00151 { \ 00152 const double weight = *w++; \ 00153 COMBINE_UPDATE \ 00154 wsum += weight; \ 00155 ++m; \ 00156 } \ 00157 w += width + 1; \ 00158 } \ 00159 COMBINE_FINISH 00160 00161 // ###################################################################### 00162 // ###################################################################### 00163 // SurpriseModelSG implementation 00164 // ###################################################################### 00165 // ###################################################################### 00166 00167 SurpriseModelSG::SurpriseModelSG(const double updatefac, 00168 const double sampleval, 00169 const double samplevar) : 00170 SurpriseModel(updatefac, sampleval, samplevar), 00171 itsN(1), 00172 itsMean(sampleval), 00173 itsVar(samplevar) 00174 { } 00175 00176 // ###################################################################### 00177 SurpriseModelSG::~SurpriseModelSG() 00178 { } 00179 00180 // ###################################################################### 00181 inline void SurpriseModelSG::reset() 00182 { load(itsInitialVal, itsInitialVar); } 00183 00184 // ###################################################################### 00185 inline void SurpriseModelSG::init(const double updfac, 00186 const double sampleval, 00187 const double samplevar) 00188 { 00189 SurpriseModel::init(updfac, sampleval, samplevar); 00190 reset(); 00191 } 00192 00193 // ###################################################################### 00194 inline void SurpriseModelSG::load(const double sampleval, 00195 const double samplevar) 00196 { itsMean = sampleval; itsVar = samplevar; } 00197 00198 // ###################################################################### 00199 inline double SurpriseModelSG::surprise(const SurpriseModelSG& sample) 00200 { 00201 const double mean1 = itsMean, var1 = itsVar / itsUpdateFac; 00202 const double mean2 = sample.itsMean, var2 = sample.itsVar; 00203 00204 const double ivar1 = var1 < 1.0e-10 ? 1.0e10 : 1.0 / var1; 00205 const double ivar2 = var2 < 1.0e-10 ? itsN * 1.0e10 : itsN / var2; 00206 00207 // let's find out the mean and variance of our model once we update 00208 // it with the incoming sample (i.e., let's compute the posterior). 00209 // We use the unknown mean / known variance case: 00210 const double newMean = (mean1 * ivar1 + mean2 * ivar2) / (ivar1 + ivar2); 00211 const double newVar = 1.0 / (ivar1 + ivar2); 00212 00213 // surprise is KL(new || old): 00214 // KL(Gq || Gp) = 1/2 [Sq^2/Sp^2 - 1 - log(Sq^2/Sp^2) + (Mq-Mp)^2/Sp^2] 00215 // here, new = Gq = G(newMean, newVar) and old = Gp = G(mean1, var1) 00216 const double x = newVar / var1, mm = newMean - mean1; 00217 const double s = 0.5 * (x - 1.0 - log(x) + mm * mm /var1); 00218 00219 // the posterior becomes our new prior: 00220 itsMean = newMean; itsVar = newVar; 00221 00222 // return the surprise, in units of wows: 00223 return s / M_LN2; 00224 } 00225 00226 // ###################################################################### 00227 inline void SurpriseModelSG::preComputeHyperParams(const SurpriseModelSG& sample) 00228 { LFATAL("Unimplemented in this model!"); } 00229 00230 // ###################################################################### 00231 00232 #define COMBINE_INIT itsMean = 0.0; itsVar = 0.0; 00233 #define COMBINE_TYPE SurpriseModelSG 00234 #define COMBINE_UPDATE \ 00235 const double mmean = m->itsMean; \ 00236 itsMean += weight * mmean; \ 00237 itsVar += weight * (m->itsVar + mmean * mmean); 00238 #define COMBINE_FINISH \ 00239 itsMean /= wsum; itsVar /= wsum; \ 00240 itsVar -= itsMean * itsMean; 00241 00242 // ###################################################################### 00243 inline void SurpriseModelSG::combineFrom(const Image<SurpriseModelSG>& models, 00244 const Image<float>& weights) 00245 { 00246 // combined mean is just the weighted sum of all the means; the 00247 // formula for combined variance is barely more complicated: 00248 COMBINE_FROM(models,weights) 00249 } 00250 00251 // ###################################################################### 00252 inline void SurpriseModelSG::combineFrom(const Image<SurpriseModelSG>& models, 00253 const Image<float>& weights, 00254 const Point2D<int>& pos, 00255 const int width, 00256 const int height, 00257 const int offset) 00258 { 00259 // combined mean is just the weighted sum of all the means; the 00260 // formula for combined variance is barely more complicated: 00261 COMBINE_FROM_WMIN(models,weights,pos,width,height,offset) 00262 } 00263 00264 // ###################################################################### 00265 00266 #undef COMBINE_INIT 00267 #undef COMBINE_TYPE 00268 #undef COMBINE_UPDATE 00269 #undef COMBINE_FINISH 00270 00271 // ###################################################################### 00272 inline double SurpriseModelSG::getMean() const 00273 { return itsMean; } 00274 00275 // ###################################################################### 00276 inline double SurpriseModelSG::getVar() const 00277 { return itsVar; } 00278 00279 // ###################################################################### 00280 inline double SurpriseModelSG::getUpdateFac() const 00281 { return itsUpdateFac; } 00282 00283 // ###################################################################### 00284 // ###################################################################### 00285 // SurpriseModelSP implementation 00286 // ###################################################################### 00287 // ###################################################################### 00288 00289 SurpriseModelSP::SurpriseModelSP(const double updatefac, 00290 const double sampleval, 00291 const double samplevar) : 00292 SurpriseModel(updatefac, sampleval, samplevar), 00293 itsN(1), 00294 itsAlpha(itsN * sampleval / (1.0 - updatefac)), 00295 itsBeta(itsN / (1.0 - updatefac)) 00296 { } 00297 00298 // ###################################################################### 00299 SurpriseModelSP::~SurpriseModelSP() 00300 { } 00301 00302 // ###################################################################### 00303 inline void SurpriseModelSP::reset() 00304 { load(itsInitialVal, itsInitialVar); } 00305 00306 // ###################################################################### 00307 inline void SurpriseModelSP::init(const double updfac, 00308 const double sampleval, 00309 const double samplevar) 00310 { 00311 SurpriseModel::init(updfac, sampleval, samplevar); 00312 load(sampleval, samplevar); 00313 } 00314 00315 // ###################################################################### 00316 inline void SurpriseModelSP::load(const double sampleval, 00317 const double samplevar) 00318 { 00319 itsAlpha = itsN * sampleval / (1.0 - itsUpdateFac); 00320 itsBeta = itsN / (1.0 - itsUpdateFac); 00321 } 00322 00323 // ###################################################################### 00324 inline double SurpriseModelSP::surprise(const SurpriseModelSP& sample) 00325 { 00326 // first, decay alpha and beta: 00327 itsAlpha *= itsUpdateFac; itsBeta *= itsUpdateFac; 00328 00329 // a zero response can trip us up since phi(x) >= 0.0 00330 // Added by Nate to avoid certain crashes 00331 if (itsAlpha <= 0.0) itsAlpha = 0.0000001; 00332 00333 // let's find out the alpha and beta of our model once we update 00334 // it with the incoming sample (i.e., let's compute the posterior): 00335 const double newAlpha = itsAlpha + itsN * sample.itsAlpha / sample.itsBeta; 00336 const double newBeta = itsBeta + itsN; 00337 00338 // surprise is KL(new || old): 00339 const double s = KLgamma<double>(newAlpha,newBeta,itsAlpha,itsBeta,true); 00340 00341 // the posterior becomes our new prior: 00342 itsAlpha = newAlpha; itsBeta = newBeta; 00343 00344 return s; 00345 } 00346 00347 // ###################################################################### 00348 inline void SurpriseModelSP::preComputeHyperParams(const SurpriseModelSP& sample) 00349 { LFATAL("Unimplemented in this model!"); } 00350 00351 // ###################################################################### 00352 #define COMBINE_INIT itsAlpha = 0.0; itsBeta = 0.0; 00353 #define COMBINE_TYPE SurpriseModelSP 00354 // Note alpha has been preset in its value so what we have here is 00355 // functionally: itsAlpha += weight * m->itsAlpha/m->itsBeta 00356 // See preSetAlpha() which does this short cut step 00357 #define COMBINE_UPDATE \ 00358 itsAlpha += weight * m->itsAlpha; \ 00359 itsBeta += weight * m->itsBeta; 00360 #define COMBINE_FINISH \ 00361 wsum = 1/wsum; \ 00362 itsBeta *= wsum; \ 00363 itsAlpha *= itsBeta * wsum; 00364 00365 // ###################################################################### 00366 inline void SurpriseModelSP::combineFrom(const Image<SurpriseModelSP>& models, 00367 const Image<float>& weights) 00368 { 00369 // combined alpha is the weighted sum of means, and combined beta is 00370 // the sum of weights (both possibly scaled by a factor): 00371 00372 COMBINE_FROM(models,weights) 00373 } 00374 00375 // ###################################################################### 00376 inline void SurpriseModelSP::combineFrom(const Image<SurpriseModelSP>& models, 00377 const Image<float>& weights, 00378 const Point2D<int>& pos, 00379 const int width, 00380 const int height, 00381 const int offset) 00382 { 00383 // combined mean is just the weighted sum of all the means; the 00384 // formula for combined variance is barely more complicated: 00385 00386 COMBINE_FROM_WMIN(models,weights,pos,width,height,offset) 00387 } 00388 00389 // ###################################################################### 00390 00391 #undef COMBINE_INIT 00392 #undef COMBINE_TYPE 00393 #undef COMBINE_UPDATE 00394 #undef COMBINE_FINISH 00395 00396 // ###################################################################### 00397 inline double SurpriseModelSP::getMean() const 00398 { return itsAlpha / itsBeta; } 00399 00400 // ###################################################################### 00401 inline double SurpriseModelSP::getVar() const 00402 { return itsAlpha / (itsBeta * itsBeta); } 00403 00404 // ###################################################################### 00405 inline double SurpriseModelSP::getUpdateFac() const 00406 { return itsUpdateFac; } 00407 00408 // ###################################################################### 00409 inline double SurpriseModelSP::getAlpha() const 00410 { return itsAlpha; } 00411 00412 // ###################################################################### 00413 inline double SurpriseModelSP::getBeta() const 00414 { return itsBeta; } 00415 00416 // ###################################################################### 00417 void SurpriseModelSP::preSetAlpha() 00418 { 00419 itsAlpha = itsAlpha/itsBeta; 00420 } 00421 00422 // ###################################################################### 00423 // ###################################################################### 00424 // SurpriseModelSP1 implementation 00425 // ###################################################################### 00426 // ###################################################################### 00427 00428 SurpriseModelSP1::SurpriseModelSP1(const double updatefac, 00429 const double sampleval, 00430 const double samplevar) : 00431 SurpriseModel(updatefac, sampleval, samplevar), 00432 itsN(1), 00433 itsAlpha(itsN * sampleval / (1.0 - updatefac)), 00434 itsBeta(itsN / (1.0 - updatefac)) 00435 { } 00436 00437 // ###################################################################### 00438 SurpriseModelSP1::~SurpriseModelSP1() 00439 { } 00440 00441 // ###################################################################### 00442 inline void SurpriseModelSP1::reset() 00443 { load(itsInitialVal, itsInitialVar); } 00444 00445 // ###################################################################### 00446 inline void SurpriseModelSP1::init(const double updfac, 00447 const double sampleval, 00448 const double samplevar) 00449 { 00450 SurpriseModel::init(updfac, sampleval, samplevar); 00451 load(sampleval, samplevar); 00452 } 00453 00454 // ###################################################################### 00455 inline void SurpriseModelSP1::load(const double sampleval, 00456 const double samplevar) 00457 { 00458 itsAlpha = itsN * sampleval / (1.0 - itsUpdateFac); 00459 itsBeta = itsN / (1.0 - itsUpdateFac); 00460 } 00461 00462 // ###################################################################### 00463 inline double SurpriseModelSP1::surprise(const SurpriseModelSP1& sample) 00464 { 00465 // a zero response can trip us up since phi(x) >= 0.0 00466 // Added by Nate to avoid certain crashes 00467 if (itsAlpha <= 0.0) itsAlpha = 0.0000001; 00468 00469 // let's find out the alpha and beta of our model once we update 00470 // it with the incoming sample (i.e., let's compute the posterior): 00471 const double newAlpha = itsAlpha * itsUpdateFac + 00472 itsN * sample.itsAlpha / sample.itsBeta; 00473 const double newBeta = itsBeta * itsUpdateFac + 00474 itsN; 00475 00476 // surprise is KL(new || old): 00477 const double s = KLgamma<double>(newAlpha,newBeta,itsAlpha,itsBeta,true); 00478 00479 // the posterior becomes our new prior: 00480 itsAlpha = newAlpha; itsBeta = newBeta; 00481 00482 return s; 00483 } 00484 00485 // ###################################################################### 00486 inline void SurpriseModelSP1::preComputeHyperParams(const SurpriseModelSP1& sample) 00487 { LFATAL("Unimplemented in this model!"); } 00488 00489 // ###################################################################### 00490 #define COMBINE_INIT itsAlpha = 0.0; itsBeta = 0.0; 00491 #define COMBINE_TYPE SurpriseModelSP1 00492 // Note alpha has been preset in its value so what we have here is 00493 // functionally: itsAlpha += weight * m->itsAlpha/m->itsBeta 00494 // See preSetAlpha() which does this short cut step 00495 #define COMBINE_UPDATE \ 00496 itsAlpha += weight * m->itsAlpha; \ 00497 itsBeta += weight * m->itsBeta; 00498 #define COMBINE_FINISH \ 00499 wsum = 1/wsum; \ 00500 itsBeta *= wsum; \ 00501 itsAlpha *= itsBeta * wsum; 00502 00503 // ###################################################################### 00504 inline void SurpriseModelSP1::combineFrom(const Image<SurpriseModelSP1>& models, 00505 const Image<float>& weights) 00506 { 00507 // combined alpha is the weighted sum of means, and combined beta is 00508 // the sum of weights (both possibly scaled by a factor): 00509 00510 COMBINE_FROM(models,weights) 00511 } 00512 00513 // ###################################################################### 00514 inline void SurpriseModelSP1::combineFrom(const Image<SurpriseModelSP1>& models, 00515 const Image<float>& weights, 00516 const Point2D<int>& pos, 00517 const int width, 00518 const int height, 00519 const int offset) 00520 { 00521 // combined mean is just the weighted sum of all the means; the 00522 // formula for combined variance is barely more complicated: 00523 00524 COMBINE_FROM_WMIN(models,weights,pos,width,height,offset) 00525 } 00526 00527 // ###################################################################### 00528 00529 #undef COMBINE_INIT 00530 #undef COMBINE_TYPE 00531 #undef COMBINE_UPDATE 00532 #undef COMBINE_FINISH 00533 00534 // ###################################################################### 00535 inline double SurpriseModelSP1::getMean() const 00536 { return itsAlpha / itsBeta; } 00537 00538 // ###################################################################### 00539 inline double SurpriseModelSP1::getVar() const 00540 { return itsAlpha / (itsBeta * itsBeta); } 00541 00542 // ###################################################################### 00543 inline double SurpriseModelSP1::getUpdateFac() const 00544 { return itsUpdateFac; } 00545 00546 // ###################################################################### 00547 inline double SurpriseModelSP1::getAlpha() const 00548 { return itsAlpha; } 00549 00550 // ###################################################################### 00551 inline double SurpriseModelSP1::getBeta() const 00552 { return itsBeta; } 00553 00554 // ###################################################################### 00555 void SurpriseModelSP1::preSetAlpha() 00556 { 00557 itsAlpha = itsAlpha/itsBeta; 00558 } 00559 00560 // ###################################################################### 00561 // ###################################################################### 00562 // SurpriseModelSPC implementation 00563 // ###################################################################### 00564 // ###################################################################### 00565 00566 SurpriseModelSPC::SurpriseModelSPC(const double updatefac, 00567 const double sampleval, 00568 const double samplevar) : 00569 SurpriseModel(updatefac, sampleval, samplevar), 00570 itsN(1), 00571 itsAlpha(itsN * sampleval / (1.0 - updatefac)), 00572 itsBeta(M_PI) 00573 { } 00574 00575 // ###################################################################### 00576 SurpriseModelSPC::~SurpriseModelSPC() 00577 { } 00578 00579 // ###################################################################### 00580 inline void SurpriseModelSPC::reset() 00581 { load(itsInitialVal, itsInitialVar); } 00582 00583 // ###################################################################### 00584 inline void SurpriseModelSPC::init(const double updfac, 00585 const double sampleval, 00586 const double samplevar) 00587 { 00588 SurpriseModel::init(updfac, sampleval, samplevar); 00589 load(sampleval, samplevar); 00590 } 00591 00592 // ###################################################################### 00593 inline void SurpriseModelSPC::load(const double sampleval, 00594 const double samplevar) 00595 { 00596 itsAlpha = itsN * sampleval / (1.0 - itsUpdateFac); 00597 itsBeta = M_PI; 00598 } 00599 00600 // ###################################################################### 00601 inline double SurpriseModelSPC::surprise(const SurpriseModelSPC& sample) 00602 { 00603 // first, decay alpha: 00604 itsAlpha *= itsUpdateFac; 00605 00606 // a zero response can trip us up since phi(x) >= 0.0 00607 // Added by Nate to avoid certain crashes 00608 if (itsAlpha <= 0.0) itsAlpha = 0.0000001; 00609 00610 // let's find out the alpha and beta of our model once we update 00611 // it with the incoming sample (i.e., let's compute the posterior): 00612 const double newAlpha = itsAlpha + itsN * sample.itsAlpha / sample.itsBeta; 00613 00614 // surprise is KL(new || old): 00615 static const double itsC1 = D_SQRT_2/2.0F - 1.0F; 00616 static const double itsC2 = D_LOG_SQRT_2; 00617 00618 const double s = KLgammaConst<double>(newAlpha,itsAlpha,itsC1,itsC2,true); 00619 00620 // the posterior becomes our new prior: 00621 itsAlpha = newAlpha; 00622 00623 return s; 00624 } 00625 00626 // ###################################################################### 00627 inline void SurpriseModelSPC::preComputeHyperParams(const SurpriseModelSPC& sample) 00628 { LFATAL("Unimplemented in this model!"); } 00629 00630 // ###################################################################### 00631 #define COMBINE_INIT itsAlpha = 0.0; itsBeta = 0.0; 00632 #define COMBINE_TYPE SurpriseModelSPC 00633 // Note alpha has been preset in its value so what we have here is 00634 // functionally: itsAlpha += weight * m->itsAlpha/m->itsBeta 00635 // See preSetAlpha() which does this short cut step 00636 #define COMBINE_UPDATE \ 00637 itsAlpha += weight * m->itsAlpha; \ 00638 itsBeta += weight * m->itsBeta; 00639 #define COMBINE_FINISH \ 00640 wsum = 1/wsum; \ 00641 itsBeta *= wsum; \ 00642 itsAlpha *= itsBeta * wsum; 00643 00644 // ###################################################################### 00645 inline void SurpriseModelSPC::combineFrom(const Image<SurpriseModelSPC>& models, 00646 const Image<float>& weights) 00647 { 00648 // combined alpha is the weighted sum of means, and combined beta is 00649 // the sum of weights (both possibly scaled by a factor): 00650 00651 COMBINE_FROM(models,weights) 00652 } 00653 00654 // ###################################################################### 00655 inline void SurpriseModelSPC::combineFrom(const Image<SurpriseModelSPC>& models, 00656 const Image<float>& weights, 00657 const Point2D<int>& pos, 00658 const int width, 00659 const int height, 00660 const int offset) 00661 { 00662 // combined mean is just the weighted sum of all the means; the 00663 // formula for combined variance is barely more complicated: 00664 00665 COMBINE_FROM_WMIN(models,weights,pos,width,height,offset) 00666 } 00667 00668 // ###################################################################### 00669 00670 #undef COMBINE_INIT 00671 #undef COMBINE_TYPE 00672 #undef COMBINE_UPDATE 00673 #undef COMBINE_FINISH 00674 00675 // ###################################################################### 00676 inline double SurpriseModelSPC::getMean() const 00677 { return itsAlpha / itsBeta; } 00678 00679 // ###################################################################### 00680 inline double SurpriseModelSPC::getVar() const 00681 { return itsAlpha / (itsBeta * itsBeta); } 00682 00683 // ###################################################################### 00684 inline double SurpriseModelSPC::getUpdateFac() const 00685 { return itsUpdateFac; } 00686 00687 // ###################################################################### 00688 inline double SurpriseModelSPC::getAlpha() const 00689 { return itsAlpha; } 00690 00691 // ###################################################################### 00692 inline double SurpriseModelSPC::getBeta() const 00693 { return itsBeta; } 00694 00695 // ###################################################################### 00696 void SurpriseModelSPC::preSetAlpha() 00697 { 00698 itsAlpha = itsAlpha/itsBeta; 00699 } 00700 // ###################################################################### 00701 // ###################################################################### 00702 // SurpriseModelSPF implementation 00703 // ###################################################################### 00704 // ###################################################################### 00705 00706 SurpriseModelSPF::SurpriseModelSPF(const double updatefac, 00707 const double sampleval, 00708 const double samplevar) : 00709 SurpriseModel(updatefac, sampleval, samplevar), 00710 itsN(1), 00711 itsAlpha(itsN * sampleval / (1.0 - updatefac)), 00712 itsBeta(itsN / (1.0 - updatefac)) 00713 { } 00714 00715 // ###################################################################### 00716 SurpriseModelSPF::~SurpriseModelSPF() 00717 { } 00718 00719 // ###################################################################### 00720 inline void SurpriseModelSPF::reset() 00721 { load(itsInitialVal, itsInitialVar); } 00722 00723 // ###################################################################### 00724 inline void SurpriseModelSPF::init(const double updfac, 00725 const double sampleval, 00726 const double samplevar) 00727 { 00728 SurpriseModel::init(updfac, sampleval, samplevar); 00729 load(sampleval, samplevar); 00730 } 00731 00732 // ###################################################################### 00733 inline void SurpriseModelSPF::load(const double sampleval, 00734 const double samplevar) 00735 { 00736 itsAlpha = itsN * sampleval / (1.0 - itsUpdateFac); 00737 itsBeta = itsN / (1.0 - itsUpdateFac); 00738 } 00739 00740 // ###################################################################### 00741 inline double SurpriseModelSPF::surprise(const SurpriseModelSPF& sample) 00742 { 00743 // first, decay alpha and beta: 00744 itsAlpha *= itsUpdateFac; itsBeta *= itsUpdateFac; 00745 00746 // a zero response can trip us up since phi(x) >= 0.0 00747 // Added by Nate to avoid certain crashes 00748 if (itsAlpha <= 0.0) itsAlpha = 0.0000001; 00749 00750 // let's find out the alpha and beta of our model once we update 00751 // it with the incoming sample (i.e., let's compute the posterior): 00752 const double newAlpha = itsAlpha + itsN * sample.itsAlpha / sample.itsBeta; 00753 const double newBeta = itsN * sample.itsAlpha / itsAlpha; 00754 00755 // surprise is KL(new || old): 00756 const double s = KLgamma<double>(newAlpha,newBeta,itsAlpha,itsBeta,true); 00757 00758 // the posterior becomes our new prior: 00759 itsAlpha = newAlpha; itsBeta = newBeta; 00760 00761 return s; 00762 } 00763 00764 // ###################################################################### 00765 inline void SurpriseModelSPF::preComputeHyperParams(const SurpriseModelSPF& sample) 00766 { LFATAL("Unimplemented in this model!"); } 00767 00768 // ###################################################################### 00769 #define COMBINE_INIT itsAlpha = 0.0; itsBeta = 0.0; 00770 #define COMBINE_TYPE SurpriseModelSPF 00771 // Note alpha has been preset in its value so what we have here is 00772 // functionally: itsAlpha += weight * m->itsAlpha/m->itsBeta 00773 // See preSetAlpha() which does this short cut step 00774 #define COMBINE_UPDATE \ 00775 itsAlpha += weight * m->itsAlpha; \ 00776 itsBeta += weight * m->itsBeta; 00777 #define COMBINE_FINISH \ 00778 wsum = 1/wsum; \ 00779 itsBeta *= wsum; \ 00780 itsAlpha *= itsBeta * wsum; 00781 00782 // ###################################################################### 00783 inline void SurpriseModelSPF::combineFrom(const Image<SurpriseModelSPF>& models, 00784 const Image<float>& weights) 00785 { 00786 // combined alpha is the weighted sum of means, and combined beta is 00787 // the sum of weights (both possibly scaled by a factor): 00788 00789 COMBINE_FROM(models,weights) 00790 } 00791 00792 // ###################################################################### 00793 inline void SurpriseModelSPF::combineFrom(const Image<SurpriseModelSPF>& models, 00794 const Image<float>& weights, 00795 const Point2D<int>& pos, 00796 const int width, 00797 const int height, 00798 const int offset) 00799 { 00800 // combined mean is just the weighted sum of all the means; the 00801 // formula for combined variance is barely more complicated: 00802 00803 COMBINE_FROM_WMIN(models,weights,pos,width,height,offset) 00804 } 00805 00806 // ###################################################################### 00807 00808 #undef COMBINE_INIT 00809 #undef COMBINE_TYPE 00810 #undef COMBINE_UPDATE 00811 #undef COMBINE_FINISH 00812 00813 // ###################################################################### 00814 inline double SurpriseModelSPF::getMean() const 00815 { return itsAlpha / itsBeta; } 00816 00817 // ###################################################################### 00818 inline double SurpriseModelSPF::getVar() const 00819 { return itsAlpha / (itsBeta * itsBeta); } 00820 00821 // ###################################################################### 00822 inline double SurpriseModelSPF::getUpdateFac() const 00823 { return itsUpdateFac; } 00824 00825 // ###################################################################### 00826 inline double SurpriseModelSPF::getAlpha() const 00827 { return itsAlpha; } 00828 00829 // ###################################################################### 00830 inline double SurpriseModelSPF::getBeta() const 00831 { return itsBeta; } 00832 00833 // ###################################################################### 00834 void SurpriseModelSPF::preSetAlpha() 00835 { 00836 itsAlpha = itsAlpha/itsBeta; 00837 } 00838 00839 // ###################################################################### 00840 // ###################################################################### 00841 // SurpriseModelCS implementation 00842 // ###################################################################### 00843 // ###################################################################### 00844 00845 SurpriseModelCS::SurpriseModelCS(const double updatefac, 00846 const double sampleval, 00847 const double samplevar) : 00848 SurpriseModel(updatefac, sampleval, samplevar), 00849 itsN(1), 00850 itsAlpha(itsN * sampleval / (1.0 - updatefac)), 00851 itsBeta(0.5) 00852 { } 00853 00854 // ###################################################################### 00855 SurpriseModelCS::~SurpriseModelCS() 00856 { } 00857 00858 // ###################################################################### 00859 inline void SurpriseModelCS::reset() 00860 { load(itsInitialVal, itsInitialVar); } 00861 00862 // ###################################################################### 00863 inline void SurpriseModelCS::init(const double updfac, 00864 const double sampleval, 00865 const double samplevar) 00866 { 00867 SurpriseModel::init(updfac, sampleval, samplevar); 00868 load(sampleval, samplevar); 00869 } 00870 00871 // ###################################################################### 00872 inline void SurpriseModelCS::load(const double sampleval, 00873 const double samplevar) 00874 { 00875 itsAlpha = itsN * sampleval / (1.0 - itsUpdateFac); 00876 itsBeta = 0.5; 00877 } 00878 00879 // ###################################################################### 00880 inline double SurpriseModelCS::surprise(const SurpriseModelCS& sample) 00881 { 00882 // first, decay alpha and beta: 00883 itsAlpha *= itsUpdateFac; 00884 00885 // a zero response can trip us up since phi(x) >= 0.0 00886 // Added by Nate to avoid certain crashes 00887 if (itsAlpha <= 0.0) itsAlpha = 0.0000001; 00888 00889 // let's find out the alpha and beta of our model once we update 00890 // it with the incoming sample (i.e., let's compute the posterior): 00891 const double newAlpha = itsAlpha + itsN * sample.itsAlpha / sample.itsBeta; 00892 00893 // surprise is KL(new || old): 00894 const double s = KLgamma<double>(newAlpha,itsAlpha,true); 00895 00896 // the posterior becomes our new prior: 00897 itsAlpha = newAlpha; 00898 00899 return s; 00900 } 00901 00902 // ###################################################################### 00903 inline void SurpriseModelCS::preComputeHyperParams(const SurpriseModelCS& sample) 00904 { LFATAL("Unimplemented in this model!"); } 00905 00906 // ###################################################################### 00907 #define COMBINE_INIT itsAlpha = 0.0; itsBeta = 0.0; 00908 #define COMBINE_TYPE SurpriseModelCS 00909 // Note alpha has been preset in its value so what we have here is 00910 // functionally: itsAlpha += weight * m->itsAlpha/m->itsBeta 00911 // See preSetAlpha() which does this short cut step 00912 #define COMBINE_UPDATE \ 00913 itsAlpha += weight * m->itsAlpha/m->itsBeta; 00914 #define COMBINE_FINISH \ 00915 wsum = 1/wsum; \ 00916 itsAlpha *= itsBeta * wsum; 00917 00918 // ###################################################################### 00919 inline void SurpriseModelCS::combineFrom(const Image<SurpriseModelCS>& models, 00920 const Image<float>& weights) 00921 { 00922 // combined alpha is the weighted sum of means, and combined beta is 00923 // the sum of weights (both possibly scaled by a factor): 00924 00925 COMBINE_FROM(models,weights) 00926 } 00927 00928 // ###################################################################### 00929 inline void SurpriseModelCS::combineFrom(const Image<SurpriseModelCS>& models, 00930 const Image<float>& weights, 00931 const Point2D<int>& pos, 00932 const int width, 00933 const int height, 00934 const int offset) 00935 { 00936 // combined mean is just the weighted sum of all the means; the 00937 // formula for combined variance is barely more complicated: 00938 00939 COMBINE_FROM_WMIN(models,weights,pos,width,height,offset) 00940 } 00941 00942 // ###################################################################### 00943 00944 #undef COMBINE_INIT 00945 #undef COMBINE_TYPE 00946 #undef COMBINE_UPDATE 00947 #undef COMBINE_FINISH 00948 00949 // ###################################################################### 00950 inline double SurpriseModelCS::getMean() const 00951 { return itsAlpha / itsBeta; } 00952 00953 // ###################################################################### 00954 inline double SurpriseModelCS::getVar() const 00955 { return itsAlpha / (itsBeta * itsBeta); } 00956 00957 // ###################################################################### 00958 inline double SurpriseModelCS::getUpdateFac() const 00959 { return itsUpdateFac; } 00960 00961 // ###################################################################### 00962 inline double SurpriseModelCS::getAlpha() const 00963 { return itsAlpha; } 00964 00965 // ###################################################################### 00966 inline double SurpriseModelCS::getBeta() const 00967 { return itsBeta; } 00968 00969 // ###################################################################### 00970 void SurpriseModelCS::preSetAlpha() 00971 { 00972 itsAlpha = itsAlpha/itsBeta; 00973 } 00974 00975 // ###################################################################### 00976 // ###################################################################### 00977 // SurpriseModelGG implementation 00978 // ###################################################################### 00979 // ###################################################################### 00980 00981 SurpriseModelGG::SurpriseModelGG(const double updatefac, 00982 const double sampleval, 00983 const double samplevar) : 00984 SurpriseModel(updatefac, sampleval, samplevar), 00985 itsCombineFromRun(false), 00986 itsN(1), 00987 itsJointKLBiasType(SU_KL_STATIC), 00988 itsAlpha(itsN * sampleval / (1.0 - updatefac)), 00989 itsBeta(itsN / (1.0 - updatefac)), 00990 itsSLfac(1.0f), 00991 itsSSfac(1.0f) 00992 00993 { } 00994 00995 // ###################################################################### 00996 SurpriseModelGG::~SurpriseModelGG() 00997 { } 00998 00999 // ###################################################################### 01000 inline void SurpriseModelGG::reset() 01001 { load(itsInitialVal, itsInitialVar); } 01002 01003 // ###################################################################### 01004 inline void SurpriseModelGG::init(const double updfac, 01005 const double sampleval, 01006 const double samplevar) 01007 { 01008 SurpriseModel::init(updfac, sampleval, samplevar); 01009 load(sampleval, samplevar); 01010 } 01011 01012 // ###################################################################### 01013 inline void SurpriseModelGG::load(const double sampleval, 01014 const double samplevar) 01015 { 01016 itsAlpha = itsN * sampleval / (1.0 - itsUpdateFac); 01017 itsBeta = itsN / (1.0 - itsUpdateFac); 01018 } 01019 01020 // ###################################################################### 01021 inline double SurpriseModelGG::surprise(const SurpriseModelGG& sample) 01022 { 01023 ASSERT(itsCombineFromRun); 01024 // first, decay alpha and beta: 01025 itsAlpha *= itsUpdateFac; itsBeta *= itsUpdateFac; 01026 01027 // a zero response can trip us up since phi(x) >= 0.0 01028 // Added by Nate to avoid certain crashes 01029 if (itsAlpha <= 0.0) itsAlpha = 0.0000001; 01030 01031 // let's find out the alpha and beta of our model once we update 01032 // it with the incoming sample (i.e., let's compute the posterior): 01033 // NOTICE that we compute alpha and beta the same as with the SP model 01034 // for temporal surprise. 01035 const double newAlpha = itsAlpha + itsN * sample.itsAlpha / sample.itsBeta; 01036 const double newBeta = itsBeta + itsN; 01037 01038 // New Expected value of the mean, we add the new sample in to create 01039 // the new gauss distribution over space. Notice that the values 01040 // will go away next epoch like with space in the SP model. 01041 const double newExp = sample.itsAlpha / sample.itsBeta; 01042 const double newMean = (itsSum + newExp)/(itsWeightSum + 1); 01043 01044 // Compute new space variance 01045 const double newSS = (newExp*newExp + itsSS)/(itsWeightSum + 1); 01046 const double newVar = newSS - newMean * newMean; 01047 01048 // compute sigma from variance 01049 itsSig = sqrt(itsVar); 01050 const double newSig = sqrt(newVar); 01051 01052 double s = 0.0000001; 01053 01054 // we hack sigma to prevent nan in a uniform image. 01055 if(itsSig > 0.0 && newSig > 0.0) 01056 { 01057 // surprise is KL(new || old): 01058 // use the joint gamma / gaussian surprise 01059 // Computed in util/MathFunction.H 01060 if(itsJointKLBiasType == SU_KL_NONE) 01061 s = KLjointGammaGauss<double>(newAlpha, newMean, 01062 newBeta, newSig, 01063 itsAlpha, itsMean, 01064 itsBeta, itsSig, 01065 true); 01066 else if(itsJointKLBiasType == SU_KL_STATIC) 01067 s = KLjointGammaGauss<double>(newAlpha, newMean, 01068 newBeta, newSig, 01069 itsAlpha, itsMean, 01070 itsBeta, itsSig, 01071 true, 01072 itsSLfac, 01073 itsSSfac); 01074 else 01075 LERROR("Invalid bias type %d given for KL bias",itsJointKLBiasType); 01076 } 01077 01078 01079 //LINFO("KL S %f NA %f NM %f NB %f NS %f OA %f OM %f OB %f OS %f",s,newAlpha, newMean, 01080 // newBeta, newSig, 01081 // itsAlpha, itsMean, 01082 // itsBeta, itsSig); 01083 // the posterior becomes our new prior: 01084 itsAlpha = newAlpha; itsBeta = newBeta; 01085 01086 // force to recompute neighborhood in the next iteration. 01087 itsCombineFromRun = false; 01088 01089 return s; 01090 } 01091 01092 // ###################################################################### 01093 inline void SurpriseModelGG::preComputeHyperParams(const SurpriseModelGG& sample) 01094 { LFATAL("Unimplemented in this model!"); } 01095 01096 // ###################################################################### 01097 #define COMBINE_INIT itsMean = 0.0; itsVar = 0.0; 01098 #define COMBINE_TYPE SurpriseModelGG 01099 01100 // The expected value is alpha/beta which we use as the value for computing 01101 // the space surprise in a gaussian manner. 01102 01103 #define COMBINE_UPDATE \ 01104 const double expVal = m->itsAlpha / m->itsBeta; \ 01105 itsMean += weight * expVal; \ 01106 itsVar += weight * expVal * expVal; 01107 #define COMBINE_FINISH \ 01108 itsSum = itsMean; \ 01109 itsSS = itsVar; \ 01110 itsWeightSum = wsum; \ 01111 itsMean /= wsum; itsVar /= wsum; \ 01112 itsVar -= itsMean * itsMean; \ 01113 itsCombineFromRun = true; 01114 01115 // ###################################################################### 01116 inline void SurpriseModelGG::combineFrom(const Image<SurpriseModelGG>& models, 01117 const Image<float>& weights) 01118 { 01119 // combined alpha is the weighted sum of means, and combined beta is 01120 // the sum of weights (both possibly scaled by a factor): 01121 01122 COMBINE_FROM(models,weights) 01123 } 01124 01125 // ###################################################################### 01126 inline void SurpriseModelGG::combineFrom(const Image<SurpriseModelGG>& models, 01127 const Image<float>& weights, 01128 const Point2D<int>& pos, 01129 const int width, 01130 const int height, 01131 const int offset) 01132 { 01133 // combined mean is just the weighted sum of all the means; the 01134 // formula for combined variance is barely more complicated: 01135 01136 COMBINE_FROM_WMIN(models,weights,pos,width,height,offset) 01137 } 01138 01139 // ###################################################################### 01140 01141 #undef COMBINE_INIT 01142 #undef COMBINE_TYPE 01143 #undef COMBINE_UPDATE 01144 #undef COMBINE_FINISH 01145 01146 // ###################################################################### 01147 inline double SurpriseModelGG::getMean() const 01148 { return itsAlpha / itsBeta; } 01149 01150 // ###################################################################### 01151 inline double SurpriseModelGG::getVar() const 01152 { return itsAlpha / (itsBeta * itsBeta); } 01153 01154 // ###################################################################### 01155 inline double SurpriseModelGG::getUpdateFac() const 01156 { return itsUpdateFac; } 01157 01158 // ###################################################################### 01159 inline double SurpriseModelGG::getAlpha() const 01160 { return itsAlpha; } 01161 01162 // ###################################################################### 01163 inline double SurpriseModelGG::getBeta() const 01164 { return itsBeta; } 01165 01166 // ###################################################################### 01167 void SurpriseModelGG::setBias(const double slfac, 01168 const double ssfac, 01169 const SU_KL_BIAS klbias) 01170 { 01171 itsSLfac = slfac; 01172 itsSSfac = ssfac; 01173 itsJointKLBiasType = klbias; 01174 } 01175 01176 // ###################################################################### 01177 // SurpriseModelPM implementation 01178 // ###################################################################### 01179 SurpriseModelPM::SurpriseModelPM(const double updatefac, 01180 const double sampleval, 01181 const double samplevar) : 01182 SurpriseModel(updatefac, sampleval, samplevar), 01183 itsN(1), 01184 itsSample(itsN * sampleval / (1.0 - updatefac)), 01185 itsBeta0(1) 01186 //itsBeta0(itsN / (1.0 - updatefac)) 01187 { 01188 itsAlpha0 = itsSample; 01189 itsAlpha1 = itsSample; 01190 itsAlpha2 = itsSample; 01191 itsBeta1 = itsBeta0; 01192 itsBeta2 = itsBeta0; 01193 itsInitBeta = itsBeta0; 01194 itsExpectAlpha1 = 1; 01195 itsExpectAlpha2 = 1; 01196 itsXBar1 = 0; 01197 itsXBar2 = 0; 01198 } 01199 01200 // ###################################################################### 01201 SurpriseModelPM::~SurpriseModelPM() 01202 { } 01203 01204 // ###################################################################### 01205 inline void SurpriseModelPM::reset() 01206 { load(itsInitialVal, itsInitialVar); } 01207 01208 // ###################################################################### 01209 inline void SurpriseModelPM::init(const double updfac, 01210 const double sampleval, 01211 const double samplevar) 01212 { 01213 SurpriseModel::init(updfac, sampleval, samplevar); 01214 load(sampleval, samplevar); 01215 } 01216 01217 // ###################################################################### 01218 inline void SurpriseModelPM::load(const double sampleval, 01219 const double samplevar) 01220 { 01221 itsSample = sampleval; 01222 } 01223 01224 // ###################################################################### 01225 inline double SurpriseModelPM::surprise(const SurpriseModelPM& sample) 01226 { 01227 // a zero response can trip us up since phi(x) >= 0.0 01228 // Added by Nate to avoid certain crashes 01229 if (itsAlpha1 <= 0.0) itsAlpha1 = 0.0000001; 01230 if (itsAlpha2 <= 0.0) itsAlpha2 = 0.0000001; 01231 01232 // surprise is KL(new || old): 01233 return KLgamma<double>(itsAlpha2,itsBeta2,itsAlpha1,itsBeta1,true); 01234 } 01235 01236 // ###################################################################### 01237 inline void SurpriseModelPM::preComputeHyperParams(const SurpriseModelPM& sample) 01238 { 01239 // the posterior becomes our new prior: 01240 // Here we store values from current time at 2 to two iterations back at 01241 // time 0 so that we can compute a covaraince between terms over time. 01242 01243 itsAlpha0 = itsAlpha1; 01244 itsAlpha1 = itsAlpha2; 01245 01246 const double alphaUpdate0 = itsAlpha0 * itsUpdateFac; 01247 const double alphaUpdate1 = itsAlpha1 * itsUpdateFac; 01248 01249 const double data = sample.itsSample / itsBeta2; 01250 01251 //itsAlpha2 = alphaUpdate1 + data; 01252 //if(alphaUpdate1 > 0) 01253 // { 01254 // itsAlpha2 = alphaUpdate1 + 01255 // (log(itsBeta2) - psi(alphaUpdate1) + log(sample.itsSample)) / 01256 // itsBeta1; 01257 // } 01258 //else 01259 // { 01260 itsAlpha2 = alphaUpdate1 + data; 01261 // } 01262 01263 itsLgamma1 = itsLgamma2; 01264 itsLgamma2 = lgamma(itsAlpha2); 01265 01266 itsBeta1 = itsBeta2; 01267 01268 itsExpectAlpha1 = alphaUpdate0 + itsXBar1; 01269 itsExpectAlpha2 = alphaUpdate1 + itsXBar2; 01270 01271 itsXBar2 = (sample.itsSample + itsXBar1*itsUpdateFac) / 01272 (1 + itsUpdateFac); 01273 itsXBar1 = itsXBar2; 01274 } 01275 01276 // ###################################################################### 01277 inline void SurpriseModelPM::combineFrom(const Image<SurpriseModelPM>& models, 01278 const Image<float>& weights) 01279 { 01280 LFATAL("This method not supported for this type of object"); 01281 } 01282 01283 // ###################################################################### 01284 inline void SurpriseModelPM::combineFrom(const Image<SurpriseModelPM>& models, 01285 const Image<float>& weights, 01286 const Point2D<int>& pos, 01287 const int width, 01288 const int height, 01289 const int offset) 01290 { 01291 ASSERT(weights.getWidth() == 2 * width + 1); 01292 ASSERT(weights.getHeight() == 2 * height + 1); 01293 ASSERT(models.coordsOk(pos)); 01294 01295 // combined mean is just the weighted sum of all the means; the 01296 // formula for combined variance is barely more complicated: 01297 01298 double wsum = 0.0F; // find out how much total weight we use 01299 double cov = 0.0F; // the covariance term 01300 Image<SurpriseModelPM>::const_iterator m = models.begin(); 01301 Image<float>::const_iterator w = weights.begin(); 01302 01303 // define bounds of our scan in the weight mask and go for it: 01304 w += offset - pos.i; 01305 if((itsExpectAlpha2 != 0) && (itsExpectAlpha1 != 0)) 01306 { 01307 for (ushort j = 0; j < height; j++) 01308 { 01309 for (ushort i = 0; i < width; i++) 01310 { 01311 const double weight = *w++; 01312 if (weight) 01313 { 01314 // We use floats since precision in this part is less important 01315 // and we may be able to fit all the terms into registers at 01316 // the same time which will speed this up a whole lot. 01317 const double aRatio2 = m->itsExpectAlpha2 / itsExpectAlpha2; 01318 const double aRatio1 = m->itsExpectAlpha1 / itsExpectAlpha1; 01319 const double ratDiff = aRatio2 - aRatio1; 01320 cov += (weight * ratDiff) * itsAlpha1; 01321 wsum += weight; 01322 } 01323 ++m; 01324 } 01325 // skip to next line: 01326 w += width + 1; 01327 } 01328 } 01329 else 01330 { 01331 cov = itsAlpha2; wsum = 1; 01332 } 01333 const double combinedAlpha2 = cov / wsum; 01334 const double ratio = combinedAlpha2 / itsAlpha2; 01335 // scale alpha and beta so that if all local models were the same we 01336 // get the same parameters for our neighborhood model: 01337 01338 //LINFO("ALPHA1 %f ALPHA2 %f",itsAlpha1,itsAlpha2); 01339 01340 if((itsAlpha2 != 0) && (ratio != 0)) 01341 { 01342 //LINFO("ALPHA1 %f ALPHA2 %f ratio %f itsBeta1 %f UDF %f", 01343 // itsAlpha1,itsAlpha2,ratio,itsBeta1,itsUpdateFac); 01344 itsBeta2 = itsInitBeta * ((ratio * itsBeta1 * itsUpdateFac) + 1); 01345 //itsBeta2 = ratio + (itsBeta1 * itsUpdateFac + 1); 01346 01347 //itsBeta2 = (ratio * (1/itsBeta1))*((itsBeta1 * itsUpdateFac) + 1); 01348 //itsBeta2 = ratio + 1 + (itsBeta1 * itsUpdateFac); 01349 //itsBeta2 = itsInitBeta * ((ratio * itsBeta1) + 1); 01350 } 01351 else 01352 itsBeta2 = itsBeta1 * itsUpdateFac + 1; 01353 01354 } 01355 01356 // ###################################################################### 01357 inline double SurpriseModelPM::getMean() const 01358 { return itsAlpha2 / itsBeta2; } 01359 01360 // ###################################################################### 01361 inline double SurpriseModelPM::getVar() const 01362 { return itsAlpha2 / (itsBeta2 * itsBeta2); } 01363 01364 // ###################################################################### 01365 inline double SurpriseModelPM::getUpdateFac() const 01366 { return itsUpdateFac; } 01367 01368 // ###################################################################### 01369 // SurpriseModelOD implementation 01370 // ###################################################################### 01371 SurpriseModelOD::SurpriseModelOD(const double updatefac, 01372 const double sampleval, 01373 const double samplevar) : 01374 SurpriseModel(updatefac, sampleval, samplevar), 01375 itsN(1), 01376 itsLambda(sampleval) 01377 { } 01378 01379 // ###################################################################### 01380 SurpriseModelOD::~SurpriseModelOD() 01381 { } 01382 01383 // ###################################################################### 01384 inline void SurpriseModelOD::reset() 01385 { load(itsInitialVal, itsInitialVar); } 01386 01387 // ###################################################################### 01388 inline void SurpriseModelOD::init(const double updfac, 01389 const double sampleval, 01390 const double samplevar) 01391 { 01392 SurpriseModel::init(updfac, sampleval, samplevar); 01393 load(sampleval, samplevar); 01394 } 01395 01396 // ###################################################################### 01397 inline void SurpriseModelOD::load(const double sampleval, 01398 const double samplevar) 01399 { 01400 itsLambda = sampleval; 01401 } 01402 01403 // ###################################################################### 01404 inline double SurpriseModelOD::surprise(const SurpriseModelOD& sample) 01405 { 01406 // let's compute how likely the data is given our current model: 01407 double ret = poisson(int(sample.itsLambda+0.4999), itsLambda); 01408 01409 // now update our lambda: 01410 itsLambda = itsLambda + itsUpdateFac * (sample.itsLambda - itsLambda); 01411 01412 // return the "surprise": 01413 ret = 1.0 / (ret + 1.0e-5) - 1.0; 01414 if (ret < 0.0) ret = 0.0; 01415 01416 return ret * 0.00001; 01417 } 01418 01419 // ###################################################################### 01420 inline void SurpriseModelOD::preComputeHyperParams(const SurpriseModelOD& sample) 01421 { LFATAL("Unimplemented in this model!"); } 01422 01423 // ###################################################################### 01424 inline void SurpriseModelOD::combineFrom(const Image<SurpriseModelOD>& 01425 models, const Image<float>& weights) 01426 { 01427 ASSERT(models.isSameSize(weights)); 01428 01429 // combined lambda is the weighted sum of lambdas: 01430 itsLambda = 0.0; 01431 Image<SurpriseModelOD>::const_iterator m = models.begin(), 01432 stop = models.end(); 01433 double wsum = 0.0; // find out how much total weight we use 01434 Image<float>::const_iterator w = weights.begin(); 01435 while(m != stop) 01436 { 01437 const double weight = double(*w++); 01438 itsLambda += weight * m->itsLambda; 01439 wsum += weight; 01440 ++m; 01441 } 01442 } 01443 01444 // ###################################################################### 01445 inline void SurpriseModelOD::combineFrom(const Image<SurpriseModelOD>& 01446 models, const Image<float>& weights, 01447 const Point2D<int>& pos, 01448 const int width, 01449 const int height, 01450 const int offset) 01451 { 01452 ASSERT(weights.getWidth() == 2 * width + 1); 01453 ASSERT(weights.getHeight() == 2 * height + 1); 01454 ASSERT(models.coordsOk(pos)); 01455 01456 // combined lambda is the weighted sum of lambdas: 01457 itsLambda = 0.0; 01458 Image<SurpriseModelOD>::const_iterator m = models.begin(); 01459 Image<float>::const_iterator w = weights.begin(); 01460 double wsum = 0.0; // find out how much total weight we use 01461 01462 // define bounds of our scan in the weight mask and go for it: 01463 w += offset - pos.i; 01464 for (int j = 0; j < height; j ++) 01465 { 01466 for (int i = 0; i < width; i ++) 01467 { 01468 const double weight = double(*w++); 01469 if (weight) 01470 { 01471 itsLambda += weight * m->itsLambda; 01472 wsum += weight; 01473 } 01474 ++m; 01475 } 01476 // skip to next line: 01477 w += width + 1; 01478 } 01479 } 01480 01481 // ###################################################################### 01482 inline double SurpriseModelOD::getMean() const 01483 { return itsLambda; } 01484 01485 // ###################################################################### 01486 inline double SurpriseModelOD::getVar() const 01487 { return itsLambda; } 01488 01489 // ###################################################################### 01490 inline double SurpriseModelOD::getUpdateFac() const 01491 { return itsUpdateFac; } 01492 01493 // ###################################################################### 01494 /* So things look consistent in everyone's emacs... */ 01495 /* Local Variables: */ 01496 /* indent-tabs-mode: nil */ 01497 /* End: */