cascade
This commit is contained in:
133
src/NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.cpp
Normal file
133
src/NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#include <NeuralNetwork/ConstructiveAlgorithms/CascadeCorrelation.h>
|
||||
|
||||
using namespace NeuralNetwork::ConstructiveAlgorihtms;
|
||||
|
||||
float CascadeCorrelation::trainOutputs(Cascade::Network &network, const std::vector<CascadeCorrelation::TrainingPattern> &patterns) {
|
||||
std::size_t outputs = patterns[0].second.size();
|
||||
|
||||
FeedForward::Network p(network.getNeuronSize() - outputs-1);
|
||||
p.appendLayer(outputs);
|
||||
Learning::QuickPropagation learner(p);
|
||||
learner.setLearningCoefficient(0.9);
|
||||
|
||||
for(std::size_t neuron = 0; neuron < outputs; neuron++) {
|
||||
p[1][neuron+1].setWeights(network.getNeuron(network.getNeuronSize() - outputs + neuron)->getWeights());
|
||||
p[1][neuron+1].setActivationFunction(network.getNeuron(network.getNeuronSize() - outputs + neuron)->getActivationFunction());
|
||||
}
|
||||
|
||||
std::cout << p.stringify() << "\n";
|
||||
std::vector<TrainingPattern> patternsForOutput;
|
||||
|
||||
for(auto &pattern:patterns) {
|
||||
patternsForOutput.emplace_back(getInnerNeuronsOutput(network,pattern.first), pattern.second);
|
||||
}
|
||||
|
||||
float lastError = std::numeric_limits<float>::max();
|
||||
float error = std::numeric_limits<float>::max();
|
||||
std::size_t iteration = 0;
|
||||
std::size_t iterWithoutImporvement=0;
|
||||
do {
|
||||
lastError=error;
|
||||
for(auto &pattern:patternsForOutput) {
|
||||
learner.teach({pattern.first.begin()+1,pattern.first.end()}, pattern.second);
|
||||
}
|
||||
|
||||
error = 0;
|
||||
for(auto &pattern:patternsForOutput) {
|
||||
std::vector<float> output = p.computeOutput(pattern.first);
|
||||
for(std::size_t outputIndex = 0; outputIndex < output.size(); outputIndex++) {
|
||||
error += pow(output[outputIndex] - pattern.second[outputIndex],2);
|
||||
}
|
||||
}
|
||||
|
||||
if(lastError - error < _minimalErrorStep) {
|
||||
iterWithoutImporvement++;
|
||||
}else {
|
||||
iterWithoutImporvement=0;
|
||||
}
|
||||
} while (iteration++ < 500 && iterWithoutImporvement < 300);
|
||||
std::cout << "iter: " << iteration << ", error: " << error << ", " << (lastError-error) << "\n";
|
||||
|
||||
for(std::size_t neuron = 0; neuron < outputs; neuron++) {
|
||||
network.getNeuron(network.getNeuronSize() - outputs + neuron)->setWeights(p[1][neuron+1].getWeights());
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
void CascadeCorrelation::trainCandidates(Cascade::Network &network, std::shared_ptr<Neuron> &candidate, const std::vector<TrainingPattern> &patterns) {
|
||||
std::size_t outputs = patterns[0].second.size();
|
||||
|
||||
std::vector<TrainingPattern> patternsForOutput;
|
||||
|
||||
for(auto &pattern:patterns) {
|
||||
patternsForOutput.emplace_back(getInnerNeuronsOutput(network, pattern.first), pattern.second);
|
||||
}
|
||||
|
||||
std::vector<std::vector<float>> errors (patterns.size());
|
||||
std::vector<float> meanErrors (outputs);
|
||||
for(std::size_t patternNumber = 0; patternNumber < patterns.size(); patternNumber++) {
|
||||
auto &pattern=patterns[patternNumber];
|
||||
errors[patternNumber].resize(network.outputs());
|
||||
|
||||
std::vector<float> output = network.computeOutput(patterns[patternNumber].first);
|
||||
for(std::size_t outputIndex = 0; outputIndex < network.outputs(); outputIndex++) {
|
||||
float error = pow(pattern.second[outputIndex] - output[outputIndex],2);
|
||||
errors[patternNumber][outputIndex]=error;
|
||||
meanErrors[outputIndex] += error;
|
||||
}
|
||||
}
|
||||
|
||||
std::for_each(meanErrors.begin(), meanErrors.end(), [&patterns](float &n){ n/=patterns.size(); });
|
||||
|
||||
std::size_t iterations=0;
|
||||
std::size_t iterationsWithoutIprovement=0;
|
||||
float lastCorrelations=0;
|
||||
float correlation=std::numeric_limits<float>::max();
|
||||
do {
|
||||
lastCorrelations=correlation;
|
||||
|
||||
std::vector<float>activations;
|
||||
std::vector<float>correlations(errors[0].size());
|
||||
std::vector<float>correlationSigns(errors[0].size());
|
||||
|
||||
for(auto &pattern:patternsForOutput) {
|
||||
activations.push_back((*candidate)(pattern.first));
|
||||
}
|
||||
|
||||
for(std::size_t err=0;err<meanErrors.size();err++) {
|
||||
for(std::size_t activ=0;activ<activations.size();activ++) {
|
||||
correlations[err] += activations[activ] * (errors[activ][err] - meanErrors[err]);
|
||||
}
|
||||
correlationSigns[err] = correlations[err] > 0? 1.0 : -1.0;
|
||||
}
|
||||
|
||||
correlation = std::accumulate(correlations.begin(), correlations.end(),0.0);
|
||||
std::vector<float> derivatives(candidate->getWeights().size());
|
||||
for (std::size_t input=0;input<candidate->getWeights().size();input++) {
|
||||
float dcdw = 0.0;
|
||||
|
||||
for(std::size_t err=0;err<errors.size();err++) {
|
||||
float thetaO = 0.0;
|
||||
for(std::size_t meanError = 0; meanError < meanErrors.size(); meanError++) {
|
||||
(*candidate)(patternsForOutput[err].first);
|
||||
float derivative = candidate->getActivationFunction().derivatedOutput(candidate->value(), candidate->output());
|
||||
thetaO+=correlationSigns[meanError] * (errors[err][meanError] - meanErrors [meanError]) * derivative * candidate->weight(input);
|
||||
}
|
||||
dcdw += thetaO;
|
||||
}
|
||||
derivatives[input]=dcdw;
|
||||
}
|
||||
|
||||
for(std::size_t weightIndex = 0; weightIndex < derivatives.size(); weightIndex++) {
|
||||
candidate->weight(weightIndex) += derivatives[weightIndex]*0.1;
|
||||
}
|
||||
|
||||
if(correlation+0.0001 <= lastCorrelations) {
|
||||
iterationsWithoutIprovement++;
|
||||
} else {
|
||||
iterationsWithoutIprovement=0;
|
||||
}
|
||||
|
||||
std::cout << correlation << "\n";
|
||||
} while (iterations ++ < 200 && iterationsWithoutIprovement <3);
|
||||
}
|
||||
Reference in New Issue
Block a user