diff options
| author | Ben Boeckel <MathStuf@gmail.com> | 2007-10-26 20:46:09 +0000 |
|---|---|---|
| committer | Ben Boeckel <MathStuf@gmail.com> | 2007-10-26 20:46:09 +0000 |
| commit | 4385af885daf460a18e236f08509358f764b2c8c (patch) | |
| tree | 6c2838312dd7f42769280e24e8abc16b53c165cb /ai/Layer.cpp | |
| parent | 1f08afc80c73087bf9bde639754670548b89fc9f (diff) | |
| download | sigen-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.cpp | 333 |
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; +} |
