SurpriseModel.C

Go to the documentation of this file.
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: */
Generated on Sun May 8 08:06:54 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3