Files
AdvancedVision/NeuralDetector/NeuralNetwork.cpp
T
2017-12-20 12:21:17 +01:00

222 lines
5.0 KiB
C++

// Demo: Training of a Neural Network / Back-Propagation algorithm
// Jan Oostindie, Avans Hogeschool, dd 6-12-2016
// email: jac.oostindie@avans.nl
#include "NeuralNetwork.h"
NeuralNetwork::NeuralNetwork()
{
V0 = Mat();
W0 = Mat();
}
NeuralNetwork::~NeuralNetwork()
{
}
Mat NeuralNetwork::Train(Mat& ITset, Mat& OTset)
{
// V0, W0 : weightfactor matrices
// dV0, dW0 : weightfactor correction matrices
Mat dW0, dV0;
// default number of hiddenNeurons. The definite number is user input
// inputNeurons and outputNeurons are implicitly determined via
// the trainingset, i.e.: inputNeurons = ITset.cols ; outputNeurons = OTset.cols;
int hiddenNeurons = 8;
//loadTrainingSet1(ITset, OTset);
initializeBPN(ITset.cols, hiddenNeurons, OTset.cols, V0, dV0, W0, dW0);
//testBPN(ITset, OTset, V0, dV0, W0, dW0);
// IT: current training input of the inputlayer
// OT: desired training output of the BPN
// OH: output of the hiddenlayer
// OO: output of the outputlayer
Mat IT, OT, OH, OO;
// outputError0: error on output for the current input and weighfactors V0, W0
// outputError1: error on output for the current input and new calculated
// weighfactors, i.e. V1, W1
double outputError0, outputError1, sumSqrDiffError = MAX_OUTPUT_ERROR + 1;
Mat V1, W1;
cout << endl << "Starting neural training..." << endl;
int runs = 0;
while ((sumSqrDiffError > MAX_OUTPUT_ERROR) && (runs < MAXRUNS)) {
sumSqrDiffError = 0;
for (int inputSetRowNr = 0; inputSetRowNr < ITset.rows; inputSetRowNr++) {
IT = transpose(getRow(ITset, inputSetRowNr));
OT = transpose(getRow(OTset, inputSetRowNr));
calculateOutputHiddenLayer(IT, V0, OH);
calculateOutputBPN(OH, W0, OO);
adaptVW(OT, OO, OH, IT, W0, dW0, V0, dV0, W1, V1);
calculateOutputBPNError(OO, OT, outputError0);
calculateOutputBPNError(BPN(IT, V1, W1), OT, outputError1);
sumSqrDiffError += (outputError1 - outputError0) * (outputError1 - outputError0);
V0 = V1;
W0 = W1;
}
runs++;
if (runs % 1000 == 0)
cout << "Completed " << runs << " runs, still working on it.. (" << sumSqrDiffError << ")" << endl;
}
cout << "Training complete in " << runs << " runs" << endl;
Mat inputVectorTrainingSet, outputVectorTrainingSet, outputVectorBPN;
// druk voor elke input vector uit de trainingset de output vector uit trainingset af
// tezamen met de output vector die het getrainde BPN (zie V0, W0) genereerd bij de
// betreffende input vector.
for (int row = 0; row < ITset.rows; row++) {
// haal volgende inputvector op uit de training set
inputVectorTrainingSet = transpose(getRow(ITset, row));
// haal bijbehorende outputvector op uit de training set
outputVectorTrainingSet = transpose(getRow(OTset, row));
// bepaal de outputvector die het getrainde BPN oplevert
// bij de inputvector uit de trainingset
outputVectorBPN = BPN(inputVectorTrainingSet, V0, W0);
}
write();
return outputVectorBPN;
}
void NeuralNetwork::Predict(Mat& ITset, string& name)
{
Mat output;
output = transpose(BPN(ITset, V0, W0));
mat_class(output, name);
}
void NeuralNetwork::Read()
{
load();
}
void NeuralNetwork::write()
{
for (pair<int, string> p : classes)
cout << p.first << " - " << p.second << endl;
FileStorage fs("factors.yml", FileStorage::WRITE);
fs << "W0" << W0 << "V0" << V0;
fs.release();
FileStorage fs2("classes.yml", FileStorage::WRITE);
fs2 << "classes" << "{:";
for (pair<int, string> p : classes)
{
string el = "e" + to_string(p.first);
fs2 << el << p.second;
}
fs2 << "}";
fs2.release();
}
void NeuralNetwork::load()
{
FileStorage fs("factors.yml", FileStorage::READ);
fs["W0"] >> W0;
fs["V0"] >> V0;
fs.release();
FileStorage fs2("classes.yml", FileStorage::READ);
classes.clear();
FileNode cls = fs2["classes"];
FileNodeIterator it = cls.begin(), it_end = cls.end();
int idx = 0;
// iterate through a sequence using FileNodeIterator
for (; it != it_end; ++it, idx++)
{
cv::FileNode item = *it;
std::string key = item.name();
string value = (string)item;
classes.insert(pair<int, string>(idx, value));
}
cout << endl << "Available classes: " << endl;
for (pair<int, string> p : classes)
cout << p.first << " - " << p.second << endl;
cout << endl;
fs2.release();
}
void NeuralNetwork::getClass(const string& name, Mat& ref)
{
save_class(name, ref);
}
void NeuralNetwork::save_class(const string& name, Mat& ref)
{
for (pair<int, string> p : classes)
{
if (p.second == name)
{
class_mat(p.first, ref);
return;
}
}
classes.insert(pair<int, string>(classidx, name));
class_mat(classidx, ref);
classidx++;
}
void NeuralNetwork::class_mat(int index, Mat& ref)
{
ref = cv::Mat::zeros(cv::Size(numclasses, 1), CV_32F);
ref.at<float>(index) = 1;
}
void NeuralNetwork::mat_class(Mat& ref, string& name)
{
double maxvalue = 0;
int index = 0;
for (int i = 0; i < ref.cols; i++)
{
double temp = getEntry(ref, 0, i);
if (temp > maxvalue)
{
maxvalue = temp;
index = i;
}
}
name = classes[index] + " " + to_string(maxvalue*100) + "%";
}