summaryrefslogtreecommitdiffstats
path: root/ai/Layer.cpp
diff options
context:
space:
mode:
authorBen Boeckel <MathStuf@gmail.com>2007-10-26 20:46:09 +0000
committerBen Boeckel <MathStuf@gmail.com>2007-10-26 20:46:09 +0000
commit4385af885daf460a18e236f08509358f764b2c8c (patch)
tree6c2838312dd7f42769280e24e8abc16b53c165cb /ai/Layer.cpp
parent1f08afc80c73087bf9bde639754670548b89fc9f (diff)
downloadsigen-4385af885daf460a18e236f08509358f764b2c8c.tar.gz
sigen-4385af885daf460a18e236f08509358f764b2c8c.tar.xz
sigen-4385af885daf460a18e236f08509358f764b2c8c.zip
Reverted repo back to rev24 because committing of rev25 messed up
git-svn-id: https://pokegen.svn.sourceforge.net/svnroot/pokegen/trunk@26 6ecfd1a5-f3ed-3746-8530-beee90d26b22
Diffstat (limited to 'ai/Layer.cpp')
-rw-r--r--ai/Layer.cpp333
1 files changed, 333 insertions, 0 deletions
diff --git a/ai/Layer.cpp b/ai/Layer.cpp
new file mode 100644
index 00000000..5afee91a
--- /dev/null
+++ b/ai/Layer.cpp
@@ -0,0 +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 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;
+}