diff --git a/include/NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.h b/include/NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.h index 0fd17b7..c3daf1c 100644 --- a/include/NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.h +++ b/include/NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.h @@ -18,7 +18,11 @@ namespace NeuralNetwork { setWeightRange(_weightRange); } - Cascade::Network construct(const std::vector &patterns) { + virtual ~CascadeCorrelation() { + + } + + virtual Cascade::Network construct(const std::vector &patterns) { std::size_t inputs = patterns[0].first.size(); std::size_t outputs = patterns[0].second.size(); @@ -28,6 +32,7 @@ namespace NeuralNetwork { _epoch = 0; float error; + float lastError; if(_maxRandomOutputWeights) { error = trainOutputsRandom(0, network, patterns); } else { @@ -40,11 +45,18 @@ namespace NeuralNetwork { addBestCandidate(network, candidate); + lastError=error; if(_maxRandomOutputWeights) { error = trainOutputsRandom(_epoch, network, patterns); } else { error = trainOutputs(network, patterns); } + + if(_prunningStatus && error*1.01 >= lastError) { // it is not getting bettter + network.removeLastHiddenNeuron(); + error=lastError; + std::cout << "PRUNED\n"; + } } return network; @@ -79,7 +91,15 @@ namespace NeuralNetwork { return _epoch; } - void setErrorThreshold(std::size_t err) { + void setPruningStatus(bool status) { + _prunningStatus=status; + } + + bool getPruningStatus() const { + return _prunningStatus; + } + + void setErrorThreshold(float err) { _errorTreshold = err; } @@ -128,24 +148,25 @@ namespace NeuralNetwork { } protected: - std::shared_ptr _activFunction = std::make_shared(-0.8); + std::shared_ptr _activFunction = std::make_shared(-1.0); float _minimalErrorStep = 0.00005; float _errorTreshold; float _weightRange; + bool _prunningStatus = false; + std::size_t _epoch = 0; std::size_t _maxHiddenUnits = 20; std::size_t _maxRandomOutputWeights = 0; std::size_t _numberOfCandidates; std::size_t _maxOutputLearningIterations = 1000; - std::size_t _maxOutputLearningIterationsWithoutChange = 50; + std::size_t _maxOutputLearningIterationsWithoutChange = 5; std::size_t _maxCandidateIterations = 4000; - std::size_t _maxCandidateIterationsWithoutChange = 50; + std::size_t _maxCandidateIterationsWithoutChange = 5; std::mt19937 _generator; std::uniform_real_distribution<> _distribution; - private: std::vector getInnerNeuronsOutput(Cascade::Network &network, const std::vector &input) { std::vector output = network.computeOutput(input); @@ -161,11 +182,11 @@ namespace NeuralNetwork { return outputOfUnits; } - float trainOutputs(Cascade::Network &network, const std::vector &patterns); + virtual float trainOutputs(Cascade::Network &network, const std::vector &patterns); - float trainOutputsRandom(std::size_t step, Cascade::Network &network, const std::vector &patterns); + virtual float trainOutputsRandom(std::size_t step, Cascade::Network &network, const std::vector &patterns); - std::pair, std::vector> trainCandidates(Cascade::Network &network, std::vector> &candidates, + virtual std::pair, std::vector> trainCandidates(Cascade::Network &network, std::vector> &candidates, const std::vector &patterns); void addBestCandidate(Cascade::Network &network, const std::pair, std::vector> &candidate) { @@ -180,9 +201,9 @@ namespace NeuralNetwork { for(auto &weight: weights) { weight *= 0.9; } - outIndex++; n->setWeights(weights); - n->weight(n->getWeights().size() - 1) = -candidate.second[outIndex] / weightPortion; + n->weight(n->getWeights().size() - 1) = candidate.second[outIndex] / weightPortion; + outIndex++; } } @@ -195,7 +216,7 @@ namespace NeuralNetwork { candidates.back()->setActivationFunction(*_activFunction.get()); for(std::size_t weightIndex = 0; weightIndex < id; weightIndex++) { - candidates.back()->weight(weightIndex) = _distribution(_generator) * 3.0; + candidates.back()->weight(weightIndex) = _distribution(_generator);// * 3.0; } } return candidates; diff --git a/src/NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.cpp b/src/NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.cpp index 33de8a6..87587dc 100644 --- a/src/NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.cpp +++ b/src/NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.cpp @@ -38,6 +38,8 @@ float CascadeCorrelation::trainOutputs(Cascade::Network &network, const std::vec } } + error/=patterns.size(); + if(fabs(lastError - error) < _minimalErrorStep) { iterWithoutImporvement++; } else { @@ -124,6 +126,8 @@ float CascadeCorrelation::trainOutputsRandom(std::size_t step, Cascade::Network } } + error/=patterns.size(); + if(fabs(lastError - error) < _minimalErrorStep) { iterWithoutImporvement++; } else { @@ -237,7 +241,7 @@ std::pair , std::vector> CascadeCo do { lastCorrelation = bestCorrelation; - /*cascor_cand_epoch*/ + /*compute correlations */ for(std::size_t patternIndex = 0; patternIndex < patterns.size(); patternIndex++) { for(auto &candidateStruct : candidatesRegister) { auto candidate = candidateStruct.candidate; @@ -262,11 +266,11 @@ std::pair , std::vector> CascadeCo } } - /*adjust ci_weights*/ + /*Update Weights*/ for(auto &candidateStruct : candidatesRegister) { auto candidate = candidateStruct.candidate; for(std::size_t i = 0; i < candidateStruct.slopes.size(); i++) { - candidate->weight(i) += candidateStruct.slopes[i] * 2; + candidate->weight(i) += candidateStruct.slopes[i]; candidateStruct.slopes[i] = 0.0; } } @@ -301,5 +305,9 @@ std::pair , std::vector> CascadeCo while(iterations++ < _maxCandidateIterations && iterationsWithoutIprovement < _maxCandidateIterationsWithoutChange); std::cout << "iter: " << iterations << ", correlation: " << bestCorrelation << ", " << lastCorrelation << "\n"; + for(auto&a: bestCorrelations) { + a*=-1.0; + } + return {bestCandidate, bestCorrelations}; } \ No newline at end of file