cascade
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Network.h"
|
||||
#include <random>
|
||||
|
||||
namespace NeuralNetwork {
|
||||
namespace Cascade {
|
||||
@@ -10,7 +11,7 @@ namespace NeuralNetwork {
|
||||
* @brief Constructor for Network
|
||||
* @param _inputSize is number of inputs to network
|
||||
*/
|
||||
Network(std::size_t inputSize, std::size_t outputSize) : NeuralNetwork::Network(inputSize,outputSize) {
|
||||
Network(std::size_t inputSize, std::size_t outputSize, const ActivationFunction::ActivationFunction &activationFunction=ActivationFunction::Sigmoid(-4.9)) : NeuralNetwork::Network(inputSize,outputSize) {
|
||||
_neurons.push_back(std::make_shared<BiasNeuron>());
|
||||
|
||||
for(std::size_t i = 0; i < inputSize; i++) {
|
||||
@@ -18,7 +19,7 @@ namespace NeuralNetwork {
|
||||
}
|
||||
|
||||
for(std::size_t i = 0; i < outputSize; i++) {
|
||||
_neurons.push_back(std::make_shared<Neuron>(_neurons.size()));
|
||||
_neurons.push_back(std::make_shared<Neuron>(_neurons.size(),activationFunction));
|
||||
_neurons.back()->setInputSize(inputSize + 1); // +1 is bias
|
||||
}
|
||||
}
|
||||
@@ -29,8 +30,8 @@ namespace NeuralNetwork {
|
||||
|
||||
compute[0] = 1.0;
|
||||
|
||||
for(std::size_t i = 1; i <= _inputs; i++) {
|
||||
compute[i] = input[i - 1];
|
||||
for(std::size_t i = 0; i < _inputs; i++) {
|
||||
compute[i+1] = input[i];
|
||||
}
|
||||
|
||||
// 0 is bias, 1-_inputSize is input
|
||||
@@ -45,14 +46,22 @@ namespace NeuralNetwork {
|
||||
return _neurons.size();
|
||||
}
|
||||
|
||||
const std::vector<std::shared_ptr<NeuronInterface>>& getNeurons() {
|
||||
return _neurons;
|
||||
}
|
||||
|
||||
std::shared_ptr<NeuronInterface> getNeuron(std::size_t id) {
|
||||
return _neurons[id];
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<NeuronInterface>> getOutputNeurons() {
|
||||
return std::vector<std::shared_ptr<NeuronInterface>>(_neurons.end()-_outputs,_neurons.end());
|
||||
}
|
||||
|
||||
std::shared_ptr<NeuronInterface> addNeuron() {
|
||||
_neurons.push_back(std::make_shared<Neuron>());
|
||||
auto neuron = _neurons.back();
|
||||
neuron->setInputSize(_neurons.size() - _outputs);
|
||||
neuron->setInputSize(_neurons.size() - _outputs-1);
|
||||
// 0 is bias, 1-_inputSize is input
|
||||
std::size_t maxIndexOfNeuron = _neurons.size() - 1;
|
||||
// move output to right position
|
||||
@@ -93,12 +102,13 @@ namespace NeuralNetwork {
|
||||
return std::unique_ptr<Network>(net);
|
||||
}
|
||||
|
||||
|
||||
//I I H H O O 6
|
||||
void randomizeWeights() {
|
||||
for(std::size_t neuron = _neurons.size() - _outputs; neuron < _neurons.size(); neuron++) {
|
||||
for(std::size_t weight = 0; weight < _neurons.size() - _outputs; weight++) {
|
||||
_neurons[neuron]->weight(weight) = 1.0 - static_cast<float>(rand() % 2001) / 1000.0;
|
||||
std::mt19937 _generator(rand());
|
||||
std::uniform_real_distribution<> _distribution(-0.3,0.3);
|
||||
for(auto& neuron :getOutputNeurons()) {
|
||||
for(std::size_t weight = 0; weight < neuron->getWeights().size(); weight++) {
|
||||
neuron->weight(weight) = _distribution(_generator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Cascade/Network.h"
|
||||
#include "../FeedForward/Network.h"
|
||||
#include "../Learning/QuickPropagation.h"
|
||||
#include "../ActivationFunction/Tangents.h"
|
||||
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
namespace NeuralNetwork {
|
||||
namespace ConstructiveAlgorihtms {
|
||||
class CascadeCorrelation {
|
||||
typedef std::pair<std::vector<float>, std::vector<float>> TrainingPattern;
|
||||
public:
|
||||
CascadeCorrelation(std::size_t numberOfCandidate = 2, float maxError = 0.7) :
|
||||
_maxError(maxError), _weightRange(1), _numberOfCandidates(numberOfCandidate), _generator(rand()), _distribution() {
|
||||
setWeightRange(_weightRange);
|
||||
}
|
||||
|
||||
Cascade::Network construct(const std::vector<TrainingPattern> &patterns) {
|
||||
std::size_t inputs = patterns[0].first.size();
|
||||
std::size_t outputs = patterns[0].second.size();
|
||||
|
||||
Cascade::Network network(inputs, outputs, NeuralNetwork::ActivationFunction::Tangents());
|
||||
|
||||
network.randomizeWeights();
|
||||
|
||||
int step = 0;
|
||||
float error = trainOutputs(network, patterns);
|
||||
while(step++ < 20 && error > _maxError) {
|
||||
std::shared_ptr<Neuron> candidate = createCandidate(network.getNeuronSize() - outputs);
|
||||
|
||||
trainCandidates(network, candidate, patterns);
|
||||
addBestCandidate(network, candidate);
|
||||
|
||||
error = trainOutputs(network, patterns);
|
||||
}
|
||||
|
||||
std::cout << step << ": " << error << "\n";
|
||||
|
||||
return network;
|
||||
}
|
||||
|
||||
std::size_t getNumberOfCandidates() const {
|
||||
return _numberOfCandidates;
|
||||
}
|
||||
|
||||
void setNumberOfCandidates(std::size_t numberOfCandidates) {
|
||||
_numberOfCandidates = numberOfCandidates;
|
||||
}
|
||||
|
||||
float getWeightRange() const {
|
||||
return _weightRange;
|
||||
}
|
||||
|
||||
void setWeightRange(float weightRange) {
|
||||
_weightRange = weightRange;
|
||||
_distribution = std::uniform_real_distribution<>(-weightRange, weightRange);
|
||||
}
|
||||
|
||||
protected:
|
||||
float _minimalErrorStep = 0.0005;
|
||||
float _maxError;
|
||||
float _weightRange;
|
||||
std::size_t _numberOfCandidates;
|
||||
std::mt19937 _generator;
|
||||
std::uniform_real_distribution<> _distribution;
|
||||
private:
|
||||
|
||||
std::vector<float> getInnerNeuronsOutput(Cascade::Network &network, const std::vector<float> &input) {
|
||||
std::vector<float> output = network.computeOutput(input);
|
||||
std::vector<float> outputOfUnits(network.getNeuronSize() - output.size());
|
||||
outputOfUnits[0] = 1.0;
|
||||
for(std::size_t i = 0; i < input.size(); i++) {
|
||||
outputOfUnits[i + 1] = input[i];
|
||||
}
|
||||
|
||||
for(std::size_t i = input.size() + 1; i < network.getNeuronSize() - output.size(); i++) {
|
||||
outputOfUnits[i] = network.getNeuron(i)->output();
|
||||
}
|
||||
return outputOfUnits;
|
||||
}
|
||||
|
||||
float trainOutputs(Cascade::Network &network, const std::vector<TrainingPattern> &patterns);
|
||||
|
||||
void trainCandidates(Cascade::Network &network, std::shared_ptr<Neuron> &candidates, const std::vector<TrainingPattern> &patterns);
|
||||
|
||||
void addBestCandidate(Cascade::Network &network, const std::shared_ptr<Neuron> &candidate) {
|
||||
auto neuron = network.addNeuron();
|
||||
|
||||
//auto tmp = candidate->getWeights();
|
||||
//std::fill(tmp.begin(),tmp.end(),0.2);
|
||||
//neuron->setWeights(tmp);
|
||||
|
||||
neuron->setWeights(candidate->getWeights());
|
||||
neuron->setActivationFunction(candidate->getActivationFunction());
|
||||
for(auto &n :network.getOutputNeurons()) {
|
||||
auto weights = n->getWeights();
|
||||
for(auto& weight: weights) {
|
||||
weight *=0.7;
|
||||
}
|
||||
weights[weights.size()-1] = _distribution(_generator);
|
||||
n->setWeights(weights);
|
||||
//n->weight(n->getWeights().size() - 1) = _distribution(_generator);
|
||||
//n->weight(n->getWeights().size() - 1) = 0.2;//.distribution(_generator);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Neuron> createCandidate(std::size_t id) { //TODO
|
||||
std::vector<std::shared_ptr<Neuron>> candidates;
|
||||
|
||||
for(std::size_t i = 0; i < _numberOfCandidates; i++) {
|
||||
candidates.push_back(std::make_shared<Neuron>(id));
|
||||
candidates.back()->setInputSize(id);
|
||||
candidates.back()->setActivationFunction(NeuralNetwork::ActivationFunction::Tangents());
|
||||
|
||||
for(std::size_t weightIndex = 0; weightIndex < id; weightIndex++) {
|
||||
candidates.back()->weight(weightIndex) = _distribution(_generator);
|
||||
// candidates.back()->weight(weightIndex) = 0.1;//_distribution(_generator);
|
||||
}
|
||||
}
|
||||
return candidates[0];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user