Neural Network in OpenCV 3.1.0
Hello everyone!
I am currently trying to get OpenCV's neural network module running, unluckily so far with less success. Initialization and training works fine (at least as far as I can verify it) but as soon as I try to do a prediction, I'm receiving segmentation fault errors... I tried training / predicting on both Windows 8 as well as Ubuntu 16.04 on a custom Linux build as well as on a third-party Windows build respectively, as soon as I try a prediction, the same error occurs.
I also prepared some usable example code. Of course I know that training on randomly generated data makes not too much sense in practice, I only wanted to keep things simple for a minimum running example:
#include <opencv2/ml/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main(int argc, char *argv[])
{
//create random training data
Mat_<float> data(100, 100);
randn(data, Mat::zeros(1, 1, data.type()), Mat::ones(1, 1, data.type()));
//half of the samples for each class
Mat_<float> responses(data.rows, 1);
for (int i=0; i<responses.rows; ++i)
responses(i, 0) = i < responses.rows / 2 ? 0 : 1;
//create the neural network
Mat_<int> layerSizes(1, 3);
layerSizes(0, 0) = data.cols;
layerSizes(0, 1) = 20;
layerSizes(0, 2) = 1;
Ptr<ANN_MLP> networkPtr = ANN_MLP::create();
ANN_MLP* network = networkPtr.get();
network->setLayerSizes(layerSizes);
network->setActivationFunction(0, 0.1, 0.1);
network->setTrainMethod(0, 0.1, 0.1);
/*
//test to change variable type flags -> problem stays the same
Mat_<int> varType = Mat(1, data.cols+1, CV_8U);
for (int i = 0; i<data.cols; ++i)
varType(0, i) = VAR_ORDERED;
varType(0, varType.cols-1) = VAR_CATEGORICAL;
//varType(0, varType.cols-1) = VAR_ORDERED;
Ptr<TrainData> trainData = TrainData::create(data, ROW_SAMPLE, responses, noArray(), noArray(), noArray(), varType);
*/
Ptr<TrainData> trainData = TrainData::create(data, ROW_SAMPLE, responses);
network->train(trainData);
if (network->isTrained())
{
printf("Predict:\n");
network->predict(Mat::ones(1, data.cols, data.type())); //SEGMENTATION FAULT
printf("Prediction done!\n");
}
return 0;
}
Does anyone got the Neural Network running in OpenCV 3.1.0? For me either I'm doing something wrong (in case, please let me know) or this is a bug in OpenCV... I would appreciate any comments :-)
edit - updated source code:
#include <opencv2/ml/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main(int argc, char *argv[])
{
//create random training data
Mat_<float> data(100, 100);
randn(data, Mat::zeros(1, 1, data.type()), Mat::ones(1, 1, data.type()));
//half of the samples for each class
Mat_<float> responses(data.rows, 2);
for (int i = 0; i<data.rows; ++i)
{
if (i < data.rows/2)
{
data(i, 0) = 1;
data(i, 1) = 0;
}
else
{
data(i, 0) = 0;
data(i, 1) = 1;
}
}
//Mat_<float> responses(data.rows, 1);
//for (int i=0; i<responses.rows; ++i)
// responses(i, 0) = i < responses.rows / 2 ? 0 : 1;
//create the neural network
Mat_<int> layerSizes(1, 3);
layerSizes(0, 0) = data.cols;
layerSizes(0, 1) = 20;
layerSizes(0 ...
it neither segfaults on my win box, nor on ubuntu14 , but:
ANN_MLP* network = networkPtr.get();
-- please don't extract the raw pointer, usecv::Ptr
consistently:then, for a real classification task, you responses should be a 2d Mat. for 2 classes, it should have 2 cols, and each row should look like e.g. (1, 0) for label "0" and (0,1) for label"1" (also, last layer should have 2 neurons then)
Thanks for your comment! I changed the code according to your suggestions (cf. edit of my post), training still works fine but at prediction it keeps seg-faulting. Am I doing something else wrong?
layerSizes(0, 2) = 2;
and:
Thanks for your help! Actually I found out what's the problem (or at least what seems to be a major problem): The problem is the activation function, i.e. the line
where 0 is equivalent to IDENTITY. Writing a 1 there (i.e. SIGMOID_SYM) solves the problem, at least the predictions do work and return some results. I'll post some working example code here soon.
Finally I would like to fully understand your point regarding the output layer size: Using SIGMOID_SYM the predictions work with both configurations, but actually do I need the explicit 1-of-k encoding? If I use a different classifier from OpenCV using a single response vector containing the class indices works fine, does this not hold for neural nets or is there a major difference?