FuzzyART.C

Go to the documentation of this file.
00001 /*!@file Learn/FuzzyART.C  */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
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: John Shen <shenjohn@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Learn/FuzzyART.C $
00035 // $Id: FuzzyART.C 13373 2010-05-09 04:28:40Z jshen $
00036 //
00037 
00038 #include "Component/ModelOptionDef.H"
00039 #include "Component/OptionManager.H"
00040 #include "Component/ModelComponent.H"
00041 #include "Component/ModelParam.H"
00042 #include "Learn/FuzzyART.H"
00043 #include "Util/Assert.H"
00044 #include "Util/log.H"
00045 #include <vector>
00046 
00047 const ModelOptionCateg MOC_Learn_ART = {
00048   MOC_SORTPRI_3,   "ART Model-related Options" };
00049 
00050 const ModelOptionDef OPT_FuzzyART_InputSize = 
00051   { MODOPT_ARG(uint), "FuzzyART_InputSize", &MOC_Learn_ART, OPTEXP_CORE,
00052     "The size of the input vectors to ART",
00053     "fuzzy-art-inputsize", '\0', "<uint>", "2"};
00054 
00055 const ModelOptionDef OPT_FuzzyART_NumCategories = 
00056   { MODOPT_ARG(uint), "FuzzyART_MaxNumCategories", &MOC_Learn_ART, OPTEXP_CORE,
00057     "The maximum number of categories fuzzy ART can learn",
00058     "fuzzy-art-max-categories", '\0', "<uint>", "10"};
00059 
00060 const ModelOptionDef OPT_FuzzyART_ComplementCode = 
00061   { MODOPT_FLAG, "FuzzyART_ComplementCoding", &MOC_Learn_ART, OPTEXP_CORE,
00062     "Use complement coding for the fuzzy ART input layer",
00063     "fuzzy-art-complement-code", '\0', "", "true"};
00064 
00065 const ModelOptionDef OPT_FuzzyART_Alpha = 
00066   { MODOPT_ARG(double), "FuzzyART_Alpha", &MOC_Learn_ART, OPTEXP_CORE,
00067     "Set the choice parameter alpha for fuzzy ART dynamics",
00068     "fuzzy-art-alpha", '\0', "<0..1>", "0.01"};
00069 
00070 const ModelOptionDef OPT_FuzzyART_Beta = 
00071   { MODOPT_ARG(double), "FuzzyART_Beta", &MOC_Learn_ART, OPTEXP_CORE,
00072     "Set the learning rate parameter beta for fuzzy ART dynamics",
00073     "fuzzy-art-beta", '\0', "<0..1>", "0.1"};
00074 
00075 const ModelOptionDef OPT_FuzzyART_Rho = 
00076   { MODOPT_ARG(double), "FuzzyART_Rho", &MOC_Learn_ART, OPTEXP_CORE,
00077     "Set the vigilance parameter rho for fuzzy ART dynamics",
00078     "fuzzy-art-rho", '\0', "<0..1>", "0.9"};
00079 
00080 // ######################################################################
00081 FuzzyART::FuzzyART(OptionManager& mgr, const std::string& descrName, const std::string& tagName) :
00082   ModelComponent(mgr, descrName, tagName),
00083   itsInputSize(&OPT_FuzzyART_InputSize, this), 
00084   itsNumCategories(&OPT_FuzzyART_NumCategories, this),
00085   itsComplementCoded(&OPT_FuzzyART_ComplementCode, this),
00086   itsAlpha(&OPT_FuzzyART_Alpha, this),
00087   itsBeta(&OPT_FuzzyART_Beta, this),
00088   itsRho(&OPT_FuzzyART_Rho, this)
00089 {
00090 }
00091 
00092 void FuzzyART::start2()
00093 {
00094   for(uint i = 0; i < itsNumCategories.getVal(); i++) { 
00095     
00096     Unit L;
00097     if(itsComplementCoded.getVal())
00098       L.weights.assign(2*itsInputSize.getVal(),1.0);
00099     else
00100       L.weights.assign(itsInputSize.getVal(),1.0);
00101     L.committed = false;
00102     itsF1.push_back(L);
00103   }
00104 }
00105 
00106 // ######################################################################
00107 uint FuzzyART::learnInput(std::vector<double> input)
00108 {
00109   ASSERT(input.size() == itsInputSize.getVal());
00110 
00111   if(itsComplementCoded.getVal()) 
00112     itsCurrInput = complementCode(input);
00113   else
00114     itsCurrInput = input;
00115 
00116   // set activations for all units
00117   for(uint i = 0; i < numUnitsCommitted(); i++) {
00118     itsF1[i].activity = choiceFunction(i);
00119   }
00120   bool resonant = false;
00121   uint max_active = 0;
00122   while(!resonant) {
00123     // find pattern of maximum activity
00124     for(uint i = 0; i < numUnitsCommitted(); i++)
00125       if(itsF1[i].activity > itsF1[max_active].activity) 
00126         max_active = i;
00127 
00128     if(itsF1[max_active].activity == -1 || numUnitsCommitted() == 0) {
00129       // all units are made inactive      
00130       max_active = numUnitsCommitted(); // create new node
00131       break;
00132     }
00133     resonant = vigilanceCrit(max_active);
00134     if(!resonant) itsF1[max_active].activity = -1; //inactivate this node
00135   }
00136   updateWeights(max_active);
00137 
00138   if(max_active == itsNumCategories.getVal()) return -1;
00139   return max_active;
00140 }
00141 
00142 // ######################################################################
00143 std::vector<double> FuzzyART::complementCode(const std::vector<double> c) const
00144 {
00145   std::vector<double> d = c;
00146   const uint N = c.size();
00147   for(uint i = 0; i < N; i++)
00148     d.push_back(1-d[i]);
00149 
00150   return d;
00151 }
00152 
00153 // ######################################################################
00154 double FuzzyART::choiceFunction(const uint cat) const
00155 {
00156   std::vector<double> ha = itsF1[cat].weights;
00157   double nom = norm(fuzzyAnd(itsCurrInput,itsF1[cat].weights));
00158   double denom = itsAlpha.getVal() + norm(itsF1[cat].weights);
00159   return nom/denom;
00160   //  return norm(fuzzyAnd(itsCurrInput,itsF1[cat].weights))/
00161   //    (itsAlpha.getVal() + norm(itsF1[cat].weights));
00162 }
00163 
00164 // ######################################################################
00165 bool FuzzyART::vigilanceCrit(const uint cat) const
00166 {
00167   return norm(fuzzyAnd(itsCurrInput,itsF1[cat].weights))/norm(itsCurrInput) >= 
00168     itsRho.getVal();
00169   // if true, resonance
00170   // if false, mismatch reset
00171 }
00172 
00173 // ######################################################################
00174 void FuzzyART::updateWeights(const uint cat)
00175 {
00176   if(cat >= itsNumCategories.getVal()) {
00177     LINFO("Max number of categories #%d hit: input unlearned", itsNumCategories.getVal());
00178     return;
00179   }
00180 
00181   if(!itsF1[cat].committed) { //fast learning mode
00182     itsF1[cat].weights = itsCurrInput;
00183     itsF1[cat].committed = true;
00184     LINFO("activating new node #%d", cat);
00185   }
00186   else {
00187     std::vector<double> fuz = fuzzyAnd(itsCurrInput,itsF1[cat].weights);
00188     for(uint i = 0; i < itsInputSize.getVal(); i++)
00189       itsF1[cat].weights[i] = itsBeta.getVal()*fuz[i] + (1 - itsBeta.getVal()) * itsF1[cat].weights[i];
00190   }
00191 }
00192 
00193 // ######################################################################
00194 uint FuzzyART::numUnitsCommitted() const
00195 {
00196   uint i;
00197   for(i = 0; i < itsNumCategories.getVal(); i++) if (!itsF1[i].committed) break;
00198   return i;
00199 }
00200 
00201 // ######################################################################
00202 std::vector<double> FuzzyART::fuzzyAnd(const std::vector<double> A, const std::vector<double> B) const
00203 {
00204   std::vector<double> ret(itsInputSize.getVal());
00205   for(uint i = 0; i < itsInputSize.getVal(); i++) ret[i] = (A[i] < B[i] ? A[i] : B[i]);
00206   return ret;
00207 }
00208 
00209 // ######################################################################
00210 double FuzzyART::norm(const std::vector<double> A) const
00211 {
00212   double sum = 0;
00213   for(uint i = 0; i < itsInputSize.getVal(); i++) sum += A[i];
00214   return sum;
00215 }
00216 
00217 // ######################################################################
00218 /* So things look consistent in everyone's emacs... */
00219 /* Local Variables: */
00220 /* indent-tabs-mode: nil */
00221 /* End: */
00222 
Generated on Sun May 8 08:05:17 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3