00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
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
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
00130 max_active = numUnitsCommitted();
00131 break;
00132 }
00133 resonant = vigilanceCrit(max_active);
00134 if(!resonant) itsF1[max_active].activity = -1;
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
00161
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
00170
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) {
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
00219
00220
00221
00222