6

I'm trying to implement Multi-Layer Perceptrons (MLP) neural networks using EmguCV 3.1 (a dot NET wrapper for OpenCV library) in C#(Windows Form). In order to practice with this library I decide to implement OR operation using MLP.

I create MLP using "Initialize" method and learn it using "Train" method as below:

private void Initialize()
{
    NETWORK.SetActivationFunction(
    ANN_MLP.AnnMlpActivationFunction.SigmoidSym);

    NETWORK.SetTrainMethod(ANN_MLP.AnnMlpTrainMethod.Backprop);

    Matrix<double> layers = new Matrix<double>(new Size(4, 1));
    layers[0, 0] = 2;
    layers[0, 1] = 2;
    layers[0, 2] = 2;
    layers[0, 3] = 1;
    NETWORK.SetLayerSizes(layers);
}

private void Train()
{
    // providing data for input

    Matrix<float> input = new Matrix<float>(4, 2);
    input[0, 0] = MIN_ACTIVATION_FUNCTION; input[0, 1] = MIN_ACTIVATION_FUNCTION;
    input[1, 0] = MIN_ACTIVATION_FUNCTION; input[1, 1] = MAX_ACTIVATION_FUNCTION;
    input[2, 0] = MAX_ACTIVATION_FUNCTION; input[2, 1] = MIN_ACTIVATION_FUNCTION;
    input[3, 0] = MAX_ACTIVATION_FUNCTION; input[3, 1] = MAX_ACTIVATION_FUNCTION;

    //providing data for output
    Matrix<float> output = new Matrix<float>(4, 1);
    output[0, 0] = MIN_ACTIVATION_FUNCTION;
    output[1, 0] = MAX_ACTIVATION_FUNCTION;
    output[2, 0] = MAX_ACTIVATION_FUNCTION;
    output[3, 0] = MAX_ACTIVATION_FUNCTION;


    // mixing input and output for training
    TrainData mixedData = new TrainData(
        input,
        Emgu.CV.ML.MlEnum.DataLayoutType.RowSample,
        output);

    // stop condition = 1 million iterations
    NETWORK.TermCriteria = new MCvTermCriteria(1000000);

    // training
    NETWORK.Train(mixedData);
}

Where MIN_ACTIVATION_FUNCTION, and MAX_ACTIVATION_FUNCTION are equal to -1.7159 and 1.7159, respectively (according to OpenCV Documentation). After 1000000 iterations of (as you see in my code in stop condition), I test my network for prediction using Predict method as below:

private void Predict()
{
    Matrix<float> input = new Matrix<float>(1, 2);
    input[0, 0] = MIN_ACTIVATION_FUNCTION;
    input[0, 1] = MIN_ACTIVATION_FUNCTION;

    Matrix<float> output = new Matrix<float>(1, 1);

    NETWORK.Predict(input, output);
    MessageBox.Show(output[0, 0].ToString());

    //////////////////////////////////////////////

    input[0, 0] = MIN_ACTIVATION_FUNCTION;
    input[0, 1] = MAX_ACTIVATION_FUNCTION;

    NETWORK.Predict(input, output);
    MessageBox.Show(output[0, 0].ToString());

    //////////////////////////////////////////////

    input[0, 0] = MAX_ACTIVATION_FUNCTION;
    input[0, 1] = MIN_ACTIVATION_FUNCTION;

    NETWORK.Predict(input, output);
    MessageBox.Show(output[0, 0].ToString());

    ////////////////////////////////////////////////

    input[0, 0] = MAX_ACTIVATION_FUNCTION;
    input[0, 1] = MAX_ACTIVATION_FUNCTION;

    NETWORK.Predict(input, output);
    MessageBox.Show(output[0, 0].ToString());
}

Here is a sample of what NETWORK predicts:
-0.00734469
-0.03184918
0.02080269
-0.006674092

I expect be some thing like this:
-1.7
+1.7
+1.7
+1.7


What is wrong among my codes?

Note that I also use 0, 1 for MIN_ACTIVATION_FUNCTION and MAX_ACTIVATION_FUNCTION values but I still do not any good results.

Update 1: I edit my codes as first answer refers me (even I test my code with idea referenced in comments). Now I get NaN when call predict method.

Babak.Abad
  • 2,839
  • 10
  • 40
  • 74

2 Answers2

0

It seems that you have an error in the providing data for output. Use output array instead of input.

I think your output responses should be 2D-matrix (with 2 columns). The last layer should have 2 output neurons, because you have 2 classes for example (1, 0) is class "True" and (0, 1) is class "False". Also try to change the architecture of your network. Logic operator OR is linearly separable i.e. it can be performed using a single perceprton.

Didgeridoo
  • 1,222
  • 2
  • 14
  • 21
  • Thank you a lot for your. Now my problem is all of outputs are NaN! How can I fix it? – Babak.Abad May 04 '17 at 11:47
  • Make sure to set the layer size first, then the activation function. See http://stackoverflow.com/questions/36871277/opencv-3-1-ann-predict-returns-nan. Glad to help you! – Didgeridoo May 04 '17 at 16:12
  • 1
    @Babak.Abad I ran your code and received NaN results too. I used the latest NuGet package EmguCV v3.1.0.1 for .NET Framework 4.5. Also I tried to run an example from [Wiki](http://www.emgu.com/wiki/index.php/ANN_MLP_(Neural_Network)_in_CSharp) for Emgu CV 3.x but I had all NaN for `response` after call `network.Predict(...)`. It is very abnormal behaviour with `ANN_MLP` in Emgu CV, seems it is bug. Try to rewrite your code using C++ (Open CV) or using another C# library for neural networks. – Didgeridoo May 04 '17 at 22:03
  • Thank you for your help. I think that it is a bug. I also test different combination as you said. Do you know any library using OpenCL 1.2? I tested AforgeNet, but it is not fast for training because it is not based on GPU. – Babak.Abad May 05 '17 at 21:11
  • Try to see wiki page [Comparison of deep learning software](https://en.wikipedia.org/wiki/Comparison_of_deep_learning_software). There are some libraries for example experimental [Caffe OpenCL](https://github.com/BVLC/caffe/tree/opencl), [OpenCV with OpenCL](http://opencv.org/platforms/opencl.html) but you should write C# wrappers on it. – Didgeridoo May 09 '17 at 09:40
0

According to new version of EmguCV (Emgu.CV-3.1.0-r16.12) the problem was a bug in version 3.1.0 Now it is fixed in Emgu.CV-3.1.0-r16.12. By downloading this version, I get correct responses from my network.

Babak.Abad
  • 2,839
  • 10
  • 40
  • 74