ART1.C

Go to the documentation of this file.
00001 /*!@file Learn/ART1.C Adaptive Resonance Theory */
00002 
00003 
00004 // //////////////////////////////////////////////////////////////////// //
00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00006 // by the University of Southern California (USC) and the iLab at USC.  //
00007 // See http://iLab.usc.edu for information about this project.          //
00008 // //////////////////////////////////////////////////////////////////// //
00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00011 // in Visual Environments, and Applications'' by Christof Koch and      //
00012 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00013 // pending; application number 09/912,225 filed July 23, 2001; see      //
00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00015 // //////////////////////////////////////////////////////////////////// //
00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00017 //                                                                      //
00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00019 // redistribute it and/or modify it under the terms of the GNU General  //
00020 // Public License as published by the Free Software Foundation; either  //
00021 // version 2 of the License, or (at your option) any later version.     //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00026 // PURPOSE.  See the GNU General Public License for more details.       //
00027 //                                                                      //
00028 // You should have received a copy of the GNU General Public License    //
00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00031 // Boston, MA 02111-1307 USA.                                           //
00032 // //////////////////////////////////////////////////////////////////// //
00033 //
00034 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu>
00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Learn/ART1.C $
00036 // $Id: ART1.C 12962 2010-03-06 02:13:53Z irock $
00037 //
00038 
00039 #include "Learn/ART1.H"
00040 #include "Util/Assert.H"
00041 #include "Util/log.H"
00042 #include <math.h>
00043 #include <fcntl.h>
00044 #include <limits>
00045 #include <string>
00046 
00047 ART1::ART1(const int inputSize, const int numClasses) :
00048   itsInputSize(inputSize),
00049   itsNumClasses(numClasses)
00050 {
00051 
00052   //Build layer 1
00053   itsF1.units.resize(itsInputSize);
00054   for(uint i=0; i<itsF1.units.size(); i++)
00055     itsF1.units[i].weights.resize(itsNumClasses);
00056 
00057   //Build layer 2
00058   itsF2.units.resize(itsNumClasses);
00059   for(uint i=0; i<itsF2.units.size(); i++)
00060     itsF2.units[i].weights.resize(itsInputSize);
00061 
00062   //This should be application spacific
00063   itsA1  = 1;
00064   itsB1  = 1.5;
00065   itsC1  = 5;
00066   itsD1  = 0.9;
00067   itsL   = 3;
00068   itsRho = 0.9;
00069 
00070   //Initalize weights
00071   for(uint i=0; i<itsF1.units.size(); i++)
00072     for(uint j=0; j<itsF2.units.size(); j++)
00073     {
00074       itsF1.units[i].weights[j] = (itsB1 - 1) / itsD1 + 0.2;
00075       itsF2.units[j].weights[i] = itsL / (itsL - 1 + itsInputSize) - 0.1;
00076     }
00077 
00078 }
00079 
00080 ART1::~ART1()
00081 {
00082 }
00083 
00084 void ART1::setInput(const std::vector<bool> input)
00085 {
00086   double act;
00087   for(uint i=0; i<itsF1.units.size(); i++)
00088   {
00089     act = input[i] / (1 + itsA1 * (input[i] + itsB1) + itsC1);
00090     itsF1.units[i].output = (act > 0);
00091   }
00092 }
00093 
00094 int ART1::propagateToF2()
00095 {
00096 
00097   double maxOut = -HUGE_VAL;
00098   int winner = -1;
00099   for (uint i=0; i<itsF2.units.size(); i++) {
00100     if (!itsF2.units[i].inhibited) {
00101       double sum = 0;
00102       for (uint j=0; j<itsF1.units.size(); j++) {
00103         sum += itsF2.units[i].weights[j] * itsF1.units[j].output;
00104       }
00105       if (sum > maxOut) {
00106         maxOut = sum;
00107         winner = i;
00108       }
00109     }
00110     itsF2.units[i].output = false;
00111   }
00112   if (winner != -1)
00113     itsF2.units[winner].output = true;
00114 
00115   return winner;
00116 }
00117 
00118 void ART1::propagateToF1(const std::vector<bool> input, const int winner)
00119 {
00120   for (uint i=0; i<itsF1.units.size(); i++) {
00121     double sum = itsF1.units[i].weights[winner] *
00122                  itsF2.units[winner].output;
00123     double act = (input[i] + itsD1 * sum - itsB1) /
00124                  (1 + itsA1 * (input[i] + itsD1 * sum) + itsC1);
00125     itsF1.units[i].output = (act > 0);
00126   }
00127 }
00128 
00129 
00130 void ART1::adjustWeights(const int winner)
00131 {
00132 
00133   for (uint i=0; i<itsF1.units.size(); i++) {
00134     if (itsF1.units[i].output) {
00135       double mag = 0;
00136       for (uint j=0; j<itsF1.units.size(); j++)
00137         mag += itsF1.units[j].output;
00138 
00139       itsF1.units[i].weights[winner] = 1;
00140       itsF2.units[winner].weights[i] = itsL / (itsL - 1 + mag);
00141     } else {
00142       itsF1.units[i].weights[winner] = 0;
00143       itsF2.units[winner].weights[i] = 0;
00144     }
00145   }
00146 }
00147 
00148 
00149 
00150 
00151 int ART1::evolveNet(std::string in)
00152 {
00153 
00154   std::vector<bool> input(itsInputSize);
00155 
00156   for(uint i=0; i<in.size(); i++)
00157     input[i] = (in[i] == 'O');
00158 
00159   for(uint i=0; i<itsF2.units.size(); i++)
00160     itsF2.units[i].inhibited = false;
00161 
00162   bool resonance = false;
00163   bool exhausted = false;
00164   int winner = -1;
00165   do
00166   {
00167     setInput(input);
00168 
00169     winner = propagateToF2();
00170     if (winner != -1) { //we have a winner
00171       propagateToF1(input, winner);
00172 
00173       //Calculate the magnitude of the input
00174       double magInput = 0;
00175       for(uint i=0; i<input.size(); i++)
00176         magInput += input[i];
00177 
00178       //Calculate the magnitude of the input after propagation
00179       double magInput_ = 0;
00180       for(uint i=0; i<itsF1.units.size(); i++)
00181         magInput_ += itsF1.units[i].output;
00182 
00183       if ((magInput_ / magInput) < itsRho)
00184         itsF2.units[winner].inhibited = true;
00185       else
00186         resonance = true;
00187     } else {
00188       exhausted = true;
00189     }
00190   } while (! (resonance || exhausted));
00191 
00192   if (resonance)
00193     adjustWeights(winner);
00194 
00195   if (exhausted)
00196     LINFO("New input and all Classes exhausted");
00197 
00198   return winner;
00199 
00200 }
00201 
00202 // ######################################################################
00203 /* So things look consistent in everyone's emacs... */
00204 /* Local Variables: */
00205 /* indent-tabs-mode: nil */
00206 /* End: */
Generated on Sun May 8 08:40:58 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3