-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMLPClassifier.cpp
More file actions
150 lines (122 loc) · 4.57 KB
/
Copy pathMLPClassifier.cpp
File metadata and controls
150 lines (122 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "MLPClassifier.h";
MLPClassifier::MLPClassifier()
{
// For resizing
s_resize.height = 60;
s_resize.width = 60;
imageMatrix = 60 * 60;
}
MLPClassifier::~MLPClassifier()
{
}
void MLPClassifier::trainMLP(vector<string> trainingFilenames, vector<int> trainingLabels)
{
trainingMat = cv::Mat(trainingFilenames.size(), imageMatrix, CV_32FC1);
cv::Mat classificationResult(1, 10, CV_32FC1);
cout << "Analyzing features -> files..." << endl;
//read images
for (int index = 0; index < trainingFilenames.size(); index++)
{
//cout << "Analyzing label -> file: " << trainingLabels[index] << "|" << trainingFilenames[index] << endl;
cv::Mat imgMat = cv::imread(trainingFilenames[index], 0);
// Resize image matrix to 60x60
cv::resize(imgMat, imgMat, s_resize);
int column = 0;
for (int i = 0; i < imgMat.rows; i++)
{
for (int j = 0; j < imgMat.cols; j++)
{
trainingMat.at<float>(index, column++) = imgMat.at<uchar>(i, j);
}
}
}
int layerSizes[] = { trainingMat.cols, 50, 10 };
cv::Mat layers = cv::Mat(1, 3, CV_32SC1);
layers.at<int>(0, 0) = layerSizes[0]; // inputs
layers.at<int>(0, 1) = layerSizes[1]; // hidden layers
layers.at<int>(0, 2) = layerSizes[2]; // outputs
cv::Ptr<cv::ml::ANN_MLP> mlp = cv::ml::ANN_MLP::create();
mlp->setLayerSizes(layers);
//create the network using a sigmoid function with alpha and beta parameters 0.6 and 1 specified respectively
mlp->setActivationFunction(cv::ml::ANN_MLP::SIGMOID_SYM, 0.6, 1);
// terminate the training after either 1000 iterations or a very small change in the network wieghts below the specified value
mlp->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 300, 0.0001));
// use backpropogation for training
mlp->setTrainMethod(cv::ml::ANN_MLP::BACKPROP, 0.0001);
cv::Mat trainingClass = cv::Mat::zeros(trainingMat.rows, 10, CV_32FC1);
for (int i = 0; i < trainingMat.rows; i++)
{
trainingClass.at<float>(i, trainingLabels.at(i)) = 1.f;
}
//cv::Ptr<cv::ml::TrainData> trainData = cv::ml::TrainData::create(trainingMat, cv::ml::ROW_SAMPLE, trainingClass);
// Train
cout << "Training MLP. Grab a coffee, this may take a while..." << std::endl;
mlp->train(trainingMat, cv::ml::ROW_SAMPLE, trainingClass);
cout << "Saving MLP data" << std::endl;
mlp->save("MLPClassifier.yml");
}
void MLPClassifier::testMLP(vector<string> testFilenames, vector<int> testLabels)
{
cv::Mat testMat(testFilenames.size(), imageMatrix, CV_32FC1);
cv::Ptr<cv::ml::ANN_MLP> mlp = cv::ml::StatModel::load<cv::ml::ANN_MLP>("MLPClassifier.yml");
//read images
for (int index = 0; index < testFilenames.size(); index++)
{
cv::Mat imgMat = cv::imread(testFilenames[index], 0);
// Resize image matrix to 60x60
cv::resize(imgMat, imgMat, s_resize);
int column = 0;
for (int i = 0; i < imgMat.rows; i++)
{
for (int j = 0; j < imgMat.cols; j++)
{
testMat.at<float>(index, column++) = imgMat.at<uchar>(i, j);
}
}
}
// Will hold test results
cv::Mat confusion(10, 10, CV_32S, cv::Scalar(0));
// Run tests on validation set
for (int i = 0; i < testMat.rows; i++)
{
int pred = mlp->predict(testMat.row(i), cv::noArray());
int truth = testLabels.at(i);
confusion.at<int>(pred, truth)++;
}
// Get the diagonal values of the matrix (correct values)
cv::Mat correct = confusion.diag();
float accuracy = (sum(correct)[0] / sum(confusion)[0]) * 100;
cout << "Correct: " << sum(correct)[0] << " (" << accuracy << "%)" << std::endl;
//cout << "confusion:\n" << confusion << endl;
// Print pretty confusion matrix
cout << "MLP CONFUSION MATRIX" << endl;
cout << setw(5) << "0" << setw(8) << "1" << setw(8) << "2" << setw(8) << "3" << setw(8) << "4" << setw(8) << "5" << setw(8) << "6" << setw(8) << "7" << setw(8) << "8" << setw(8) << "9" << endl;
cout << "_________________________________________________________________________________" << endl;
for (int i = 0; i < 10; i++)
{
cout << i << "|" << setw(2);
for (int j = 0; j < 10; j++)
{
cout << setw(3) << confusion.at<int>(i, j) << " | ";
}
cout << endl;
}
//plot_binary(testMat, correct, "Predictions MLP");
}
// plot data and class
void MLPClassifier::plot_binary(cv::Mat& data, cv::Mat& classes, string name) {
int size = 200;
cv::Mat plot(size, size, CV_8UC3);
plot.setTo(cv::Scalar(255.0, 255.0, 255.0));
for (int i = 0; i < data.rows; i++) {
float x = data.at<float>(i, 0) * size;
float y = data.at<float>(i, 1) * size;
if (classes.at<float>(i, 0) > 0) {
cv::circle(plot, cv::Point(x, y), 2, CV_RGB(255, 0, 0), 1);
}
else {
cv::circle(plot, cv::Point(x, y), 2, CV_RGB(0, 255, 0), 1);
}
}
cv::imshow(name, plot);
}