diff options
| author | Ben Boeckel <MathStuf@gmail.com> | 2007-09-21 15:36:22 +0000 |
|---|---|---|
| committer | Ben Boeckel <MathStuf@gmail.com> | 2007-09-21 15:36:22 +0000 |
| commit | 5b55d13ead7e352ee1feaae72009e8abf5bd071a (patch) | |
| tree | 6c2838312dd7f42769280e24e8abc16b53c165cb /ai/Layer.cpp | |
| parent | e94d9893b8753e72adb92b2c5eb203830ddf641c (diff) | |
| download | sigen-5b55d13ead7e352ee1feaae72009e8abf5bd071a.tar.gz sigen-5b55d13ead7e352ee1feaae72009e8abf5bd071a.tar.xz sigen-5b55d13ead7e352ee1feaae72009e8abf5bd071a.zip | |
[FIX] Neural Network methods complete
[FIX] Wrapped Node up into the layer
[FIX] Wrapped NatureEffect into Nature
[FIX] Getting around to fixing up the design of the PokéMod stuff
[FIX] Creating new subclasses now returns pointer to new subclass
[FIX] Simplified interfaces
[FIX] Minor style issues
[FIX] Renamed CoinItem to CoinListObject
[FIX] Renamed MapTrainerTeam to MapTrainerPokemon
[FIX] Renamed MapWildPokemon to MapWildListPokemon
[FIX] Moved global enums to relevant classes
[FIX] Removed general logging features
[DEL] pokemod/Debug.{h, cpp}
[DEL] pokemod/Path.{h, cpp}
[FIX] Using QFile rather than custom Path class for checking for files
[FIX] Set* methods now return a bool to let the caller know if anything actually changed (if it can fail, otherwise it is void)
[ADD] Compliation without errors is required for pokemod from now on before commits
git-svn-id: https://pokegen.svn.sourceforge.net/svnroot/pokegen/trunk@24 6ecfd1a5-f3ed-3746-8530-beee90d26b22
Diffstat (limited to 'ai/Layer.cpp')
| -rw-r--r-- | ai/Layer.cpp | 542 |
1 files changed, 333 insertions, 209 deletions
diff --git a/ai/Layer.cpp b/ai/Layer.cpp index 67d18d13..5afee91a 100644 --- a/ai/Layer.cpp +++ b/ai/Layer.cpp @@ -1,209 +1,333 @@ -/////////////////////////////////////////////////////////////////////////////
-// Name: ai/Layer.cpp
-// Purpose: A layer of a NeuralNet
-// Author: Ben Boeckel
-// Modified by: Ben Boeckel
-// Created: Thu May 5 15:55:21 2007
-// Copyright: ©2007 Nerdy Productions
-// Licence:
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program. If not, see <http://www.gnu.org/licenses/>.
-/////////////////////////////////////////////////////////////////////////////
-
-#include "Layer.h"
-
-PokeGen::NeuralNetwork::Layer::Layer(const Layer *par, const Layer *cld, const unsigned num) :
- parent(par),
- child(cld)
-{
- for (unsigned i = 0; i < num; ++i)
- nodes.append(Node(this, i));
- if (parent)
- parent->RandomizeWeights();
-}
-
-void PokeGen::NeuralNetwork::Layer::SaveData(QFile &fout) const
-{
- fout << "-Layer\n";
- for (unsigned i = 0; i < GetNumNodes(); ++i)
- nodes[i].SaveData(fout);
-}
-
-void PokeGen::NeuralNetwork::Layer::LoadData(const QFile &fin)
-{
- QChar next;
- nodes.clear();
- fin >> next;
- while (next == '+')
- {
- AddNode();
- nodes[GetNumNodes() - 1].LoadData(fin.readLine());
- fin >> next;
- }
-}
-
-void PokeGen::NeuralNetwork::Layer::AddNode()
-{
- nodes.append(Node(this, GetNumNodes()));
- parent->UpdateBias();
-}
-
-void PokeGen::NeuralNetwork::Layer::DeleteNode(const unsigned n)
-{
- if (n < GetNumNodes())
- {
- nodes.erase(nodes.begin() + n);
- parent->UpdateBias(n);
- }
-}
-
-void PokeGen::NeuralNetwork::Layer::UpdateBias(const unsigned n)
-{
- if (n == UINT_MAX)
- bias.append((abs(std::rand()) % 201) / 100.0);
- else if (n < GetNumNodes())
- bias.erase(bias.begin() + n);
- else
- return;
- for (unsigned i = 0; i < GetNumNodes(); ++i)
- nodes[i].UpdateWeights(n);
-}
-
-unsigned PokeGen::NeuralNetwork::Layer::GetNumNodes() const
-{
- return nodes.size();
-}
-
-void PokeGen::NeuralNetwork::Layer::RandomizeWeights()
-{
- bias.clear();
- for (unsigned i = 0; i < child->GetNumNodes(); ++i)
- bias.append((abs(std::rand()) % 201) / 100.0);
- for (unsigned i = 0; i < GetNumNodes(); ++i)
- nodes[i].RandomizeWeights();
-}
-
-void PokeGen::NeuralNetwork::Layer::CalculateErrors()
-{
- for (unsigned i = 0; i < GetNumNodes(); ++i)
- nodes[i].CalculateError();
-}
-
-void PokeGen::NeuralNetwork::Layer::AdjustWeights()
-{
- for (unsigned i = 0; i < GetNumNodes(); ++i)
- nodes[i].AdjustWeights();
-}
-
-void PokeGen::NeuralNetwork::Layer::CalculateValues()
-{
- for (unsigned i = 0; i < GetNumNodes(); ++i)
- nodes[i].CalculateValue();
-}
-
-void PokeGen::NeuralNetwork::Layer::SetInput(const unsigned n, const double i)
-{
- if (n < GetNumNodes())
- nodes[n].SetInput(i);
-}
-
-void PokeGen::NeuralNetwork::Layer::SetDesired(const unsigned n, const double o)
-{
- if (n < GetNumNodes())
- nodes[n].SetDesired(o);
-}
-
-void PokeGen::NeuralNetwork::Layer::SetMomentum(const unsigned n, const double m)
-{
- if (n < GetNumNodes())
- nodes[n].SetMomentum(m);
-}
-
-void PokeGen::NeuralNetwork::Layer::SetMomentumFactor(const unsigned n, const double m)
-{
- if (n < GetNumNodes())
- nodes[n].SetMomentumFactor(m);
-}
-
-void PokeGen::NeuralNetwork::Layer::SetLearnRate(const unsigned n, const double l)
-{
- if (n < GetNumNodes())
- nodes[n].SetLearnRate(l);
-}
-
-void PokeGen::NeuralNetwork::Layer::SetFunction(const unsigned n, const unsigned f)
-{
- if (n < GetNumNodes())
- nodes[n].SetFunction(f);
-}
-
-double PokeGen::NeuralNetwork::Layer::GetOutput(const unsigned n) const
-{
- if (n < GetNumNodes())
- return nodes[n].GetOutput();
- return 0;
-}
-
-double PokeGen::NeuralNetwork::Layer::GetError(const unsigned n) const
-{
- if (n < GetNumNodes())
- return nodes[n].GetError();
- return 0;
-}
-
-double PokeGen::NeuralNetwork::Layer::GetMomentum(const unsigned n) const
-{
- if (n < GetNumNodes())
- return nodes[n].GetMomentum();
- return 0;
-}
-
-double PokeGen::NeuralNetwork::Layer::GetMomentumFactor(const unsigned n) const
-{
- if (n < GetNumNodes())
- return nodes[n].GetMomentumFactor();
- return 0;
-}
-
-double PokeGen::NeuralNetwork::Layer::GetLearnRate(const unsigned n) const
-{
- if (n < GetNumNodes())
- return nodes[n].GetLearnRate();
- return 0;
-}
-
-unsigned PokeGen::NeuralNetwork::Layer::GetFunction(const unsigned n) const
-{
- if (n < GetNumNodes())
- return nodes[n].GetFunction();
- return UINT_MAX;
-}
-
-double PokeGen::NeuralNetwork::Layer::GetWeight(const unsigned n, const unsigned i) const
-{
- if (n < GetNumNodes())
- return nodes[n].GetWeight(i);
- return 0;
-}
-
-void PokeGen::NeuralNetwork::Layer::ChangeBias(const unsigned n, const double d)
-{
- bias[n] += d * GetError(n) * parent->GetBias(n);
-}
-
-double PokeGen::NeuralNetwork::Layer::GetBias(const unsigned n) const
-{
- if (n < GetNumNodes())
- return bias[n];
- return 0;
-}
+///////////////////////////////////////////////////////////////////////////// +// Name: ai/Layer.cpp +// Purpose: A layer of a NeuralNet +// Author: Ben Boeckel +// Modified by: Ben Boeckel +// Created: Thu May 5 15:55:21 2007 +// Copyright: ©2007 Nerdy Productions +// Licence: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. If not, see <http://www.gnu.org/licenses/>. +///////////////////////////////////////////////////////////////////////////// + +#include "Layer.h" + +PokeGen::NeuralNetwork::Layer::Layer(const unsigned num) : + parent(NULL), + child(NULL) +{ + for (unsigned i = 0; i < num; ++i) + AddNode(); +} + +void PokeGen::NeuralNetwork::Layer::SaveData(Ini& nnData, const unsigned i) const +{ + nnData.AddField("numBias", bias.size()); + for (int j = 0; j < bias.size(); ++j) + nnData.AddField(QString("layer%1-bias%2").arg(i).arg(j), bias[i]); + nnData.AddField("numNodes", GetNumNodes()); + for (unsigned j = 0; j < GetNumNodes(); ++j) + { + nnData.AddField(QString("layer%1-node%2-input").arg(i).arg(j), nodes[j].input); + nnData.AddField(QString("layer%1-node%2-output").arg(i).arg(j), nodes[j].output); + nnData.AddField(QString("layer%1-node%2-momentum").arg(i).arg(j), nodes[j].momentum); + nnData.AddField(QString("layer%1-node%2-momentumFactor").arg(i).arg(j), nodes[j].momentumFactor); + nnData.AddField(QString("layer%1-node%2-learnRate").arg(i).arg(j), nodes[j].learnRate); + nnData.AddField(QString("layer%1-node%2-function").arg(i).arg(j), nodes[j].function); + for (int k = 0; k < nodes[j].weights.size(); ++k) + { + nnData.AddField(QString("layer%1-node%2-weight%3").arg(i).arg(j).arg(k), nodes[j].weights[k]); + nnData.AddField(QString("layer%1-node%2-weightChange%3").arg(i).arg(j).arg(k), nodes[j].weightChanges[k]); + } + } +} + +void PokeGen::NeuralNetwork::Layer::SetParent(Layer* par) +{ + parent = par; +} + +void PokeGen::NeuralNetwork::Layer::SetChild(Layer* cld) +{ + child = cld; + if (child) + RandomizeWeights(); +} + +void PokeGen::NeuralNetwork::Layer::AddNode() +{ + nodes.append(Node(child ? child->GetNumNodes() : 0)); + if (parent) + parent->RandomizeWeights(); +} + +bool PokeGen::NeuralNetwork::Layer::DeleteNode(const unsigned n) +{ + if (n < GetNumNodes()) + { + nodes.removeAt(n); + if (parent) + parent->RandomizeWeights(); + return true; + } + return false; +} + +unsigned PokeGen::NeuralNetwork::Layer::GetNumNodes() const +{ + return nodes.size(); +} + +bool PokeGen::NeuralNetwork::Layer::RandomizeWeights() +{ + if (child) + { + bias.clear(); + for (unsigned i = 0; i < child->GetNumNodes(); ++i) + bias.append((abs(std::rand()) % 201) / 100.0); + for (unsigned i = 0; i < GetNumNodes(); ++i) + { + nodes[i].weights.clear(); + nodes[i].weightChanges.clear(); + for (unsigned j = 0; j < child->GetNumNodes(); ++j) + { + nodes[i].weights.append((abs(std::rand()) % 201) / 100.0); + nodes[i].weightChanges.append(0); + } + } + return true; + } + return false; +} + +bool PokeGen::NeuralNetwork::Layer::CalculateErrors() +{ + if (parent) + { + for (unsigned i = 0; i < GetNumNodes(); ++i) + { + if (child) + { + nodes[i].error = 0; + for (unsigned j = 0; j < child->GetNumNodes(); ++j) + nodes[i].error += child->GetError(j) * nodes[i].weights[j]; + } + else + nodes[i].error = nodes[i].desired - nodes[i].output; + switch (nodes[i].function) + { + case Step: + nodes[i].error *= .01; + break; + case SymmetricSigmoid: + nodes[i].error *= 2; + case Sigmoid: + nodes[i].error *= nodes[i].output * (1 - nodes[i].output); + break; + case InverseTangent: + nodes[i].error *= 1 / (1 + (nodes[i].output * nodes[i].output)); + break; + case HyperbolicTangent: + nodes[i].error *= 1 - tanh(nodes[i].output) * tanh(nodes[i].output); + break; + case Radial: + nodes[i].error *= 2 * nodes[i].output * exp(nodes[i].output * nodes[i].output); + } + } + return true; + } + return false; +} + +bool PokeGen::NeuralNetwork::Layer::AdjustWeights() +{ + if (child) + { + double delta; + for (unsigned i = 0; i < GetNumNodes(); ++i) + { + for (unsigned j = 0; j < child->GetNumNodes(); ++j) + { + delta = nodes[i].learnRate * child->GetError(j) * nodes[i].output; + nodes[i].weights[j] += delta + nodes[i].momentum * nodes[i].weightChanges[j] + nodes[i].momentumFactor * nodes[i].weightChanges[j]; + nodes[i].weightChanges[j] = delta; + } + } + for (unsigned i = 0; i < child->GetNumNodes(); ++i) + bias[i] += child->GetLearnRate(i) * child->GetError(i) * bias[i]; + return true; + } + return false; +} + +bool PokeGen::NeuralNetwork::Layer::CalculateValues() +{ + if (parent) + { + for (unsigned i = 0; i < GetNumNodes(); ++i) + { + double val = 0; + for (unsigned j = 0; j < parent->GetNumNodes(); ++j) + val += parent->GetOutput(j) * parent->GetWeight(j, i); + val += parent->GetBias(i); + switch (nodes[i].function) + { + case Identity: + nodes[i].output = val; + break; + case Step: + nodes[i].output = (val <= 0) ? 0 : 1; + break; + case Sigmoid: + nodes[i].output = 1.0 / (1 + exp(val)); + break; + case SymmetricSigmoid: + nodes[i].output = 2.0 / (1 + exp(val)) - 1; + break; + case InverseTangent: + nodes[i].output = atan(val); + break; + case HyperbolicTangent: + nodes[i].output = tanh(val); + break; + case Radial: + nodes[i].output = exp(val * val); + } + } + return true; + } + return false; +} + +bool PokeGen::NeuralNetwork::Layer::SetInput(const unsigned n, const double i) +{ + if (n < GetNumNodes()) + { + nodes[n].input = i; + return true; + } + return false; +} + +bool PokeGen::NeuralNetwork::Layer::SetDesired(const unsigned n, const double o) +{ + if (n < GetNumNodes()) + { + nodes[n].desired = o; + return true; + } + return false; +} + +bool PokeGen::NeuralNetwork::Layer::SetMomentum(const unsigned n, const double m) +{ + if (n < GetNumNodes()) + { + nodes[n].momentum = m; + return true; + } + return false; +} + +bool PokeGen::NeuralNetwork::Layer::SetMomentumFactor(const unsigned n, const double m) +{ + if (n < GetNumNodes()) + { + nodes[n].momentumFactor = m; + return true; + } + return false; +} + +bool PokeGen::NeuralNetwork::Layer::SetLearnRate(const unsigned n, const double l) +{ + if (n < GetNumNodes()) + { + nodes[n].learnRate = l; + return true; + } + return false; +} + +bool PokeGen::NeuralNetwork::Layer::SetFunction(const unsigned n, const unsigned f) +{ + if ((n < GetNumNodes()) && (f < FunctionEnd)) + { + nodes[n].function = f; + return true; + } + return false; +} + +double PokeGen::NeuralNetwork::Layer::GetOutput(const unsigned n) const +{ + if (n < GetNumNodes()) + return nodes[n].output; + return 0; +} + +double PokeGen::NeuralNetwork::Layer::GetDesired(const unsigned n) const +{ + if (n < GetNumNodes()) + return nodes[n].desired; + return 0; +} + +double PokeGen::NeuralNetwork::Layer::GetError(const unsigned n) const +{ + if (n < GetNumNodes()) + return nodes[n].error; + return 0; +} + +double PokeGen::NeuralNetwork::Layer::GetMomentum(const unsigned n) const +{ + if (n < GetNumNodes()) + return nodes[n].momentum; + return 0; +} + +double PokeGen::NeuralNetwork::Layer::GetMomentumFactor(const unsigned n) const +{ + if (n < GetNumNodes()) + return nodes[n].momentumFactor; + return 0; +} + +double PokeGen::NeuralNetwork::Layer::GetLearnRate(const unsigned n) const +{ + if (n < GetNumNodes()) + return nodes[n].learnRate; + return 0; +} + +unsigned PokeGen::NeuralNetwork::Layer::GetFunction(const unsigned n) const +{ + if (n < GetNumNodes()) + return nodes[n].function; + return FunctionEnd; +} + +double PokeGen::NeuralNetwork::Layer::GetWeight(const unsigned n, const unsigned i) const +{ + if (n < GetNumNodes()) + return nodes[n].weights[i]; + return 0; +} + +double PokeGen::NeuralNetwork::Layer::GetBias(const unsigned n) const +{ + if (n < child->GetNumNodes()) + return bias[n]; + return 0; +} |
