This commit is contained in:
2016-05-07 10:59:54 +02:00
parent 58f7f8f69b
commit 47484fc45c
3 changed files with 280 additions and 9 deletions

View 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);
}