Ask Your Question

thomas's profile - activity

2019-04-17 07:57:54 -0600 received badge  Popular Question (source)
2014-10-23 05:31:22 -0600 received badge  Editor (source)
2014-10-23 05:29:02 -0600 asked a question CvSVM::EPS_SVR train_auto assertion sv_count != 0 failed

I have the following code:

CvSVMParams params;
params.svm_type = CvSVM::EPS_SVR;
params.kernel_type = CvSVM::RBF;
params.term_crit = TermCriteria(CV_TERMCRIT_ITER, (int)1e7, 1e-6);

CvSVM svm;
svm.train_auto(_data, _resp, _var_idx, _train_idx, params);

Here _data and _resp are Mats holding the feature vectors and responses, _var_idx containing the active features and _train_idx the active samples. For the parameter grids the default values are used. Unfortunately, the code produces the following error:

OpenCV Error: Assertion failed (sv_count != 0) in do_train, file /home/.../opencv-2.4.9/modules/ml/src/svm.cpp, line 1346

When I run a regression one the same data with parameters selected by hand it works fine. And when I switch to a classification problem (and change the corresponding parameters and SVM type) it also works. In that case for single training as well as for auto training. Also, when switching to CvSVM::NU_SVR the auto training works fine.

Another thing that bothers me is that I also have to provide the parameter p (EPS_EVR) or nu (NU_SVR) when I want to do auto training. The documentation says that those are also estimated using their corresponding default grids. Why is that so?

Thanks in advance.

EDIT:

I've made a small example that suffers from this problem. Just in case anyone want to try it out and reproduce the problem:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/ml/ml.hpp>

using namespace cv;
using namespace std;

int main() {

    Mat X(1000, 2, CV_32FC1);
    Mat Y(1000, 1, CV_32FC1);

    randu(X, -2, 2);

    for(int i = 0; i < 1000; i++){
        Y.at<float>(i,0) = pow(X.at<float>(i,0),2) + pow(X.at<float>(i,1),2) - 1;
    }

    CvSVMParams params;
    params.svm_type = CvSVM::EPS_SVR;
    params.kernel_type = CvSVM::RBF;
    params.term_crit = TermCriteria(CV_TERMCRIT_ITER, (int)1e7, 1e-6);
    params.p = 0.1;

    CvSVM svm;
    svm.train_auto(X, Y, Mat::ones(1,2, CV_8U), Mat::ones(1,1000, CV_8U), params);

    return 0;
}
2014-09-15 06:51:13 -0600 asked a question MLP sigmoid output +/-epsilon

This may seem like a duplicate question to this, but the difference is that there I was asking whether the output range is [-1,1] or [0,1]. I have accepted that the range is [0,1] if the the activation function is the sigmoid with alpha != 0 and beta != 0 (as stated in the documentation). Anyway, it seems to me that the output range is more like [0-eps, 1+eps].

My question is: Why is there a small epsilon and how can I turn this off?

One thing I could think of is that the output neurons aren't sigmoid units but linear units. Although it is explicitly stated that all neurons have the same activation function, this could explain this behavior.

Here is a small example that shows what I mean:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/ml/ml.hpp>

using namespace cv;
using namespace std;

int main() {

    int POS = 1, NEG = 0;

    int SAMPLES = 100;
    float SPLIT = 0.8;

    float C_X = 0.5;
    float C_Y = 0.5;
    float R = 0.3;

    Mat X(SAMPLES, 2, CV_32FC1);
    Mat Y(SAMPLES, 1, CV_32FC1);

    randu(X, 0, 1);

    for(int i = 0; i < SAMPLES; i++){
        Y.at<float>(i,0) = pow((X.at<float>(i,0) - C_X),2) + pow((X.at<float>(i,1) - C_Y),2) < pow(R,2) ? POS : NEG;
    }

    Mat X_train = X(Range(0, (int)(SAMPLES*SPLIT)), Range::all());
    Mat Y_train = Y(Range(0, (int)(SAMPLES*SPLIT)), Range::all());

    Mat X_test = X(Range((int)(SAMPLES*SPLIT), SAMPLES), Range::all());
    Mat Y_test = Y(Range((int)(SAMPLES*SPLIT), SAMPLES), Range::all());

    CvANN_MLP_TrainParams params(
                 cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000, 0.000001),
                 CvANN_MLP_TrainParams::BACKPROP,
                 0.1,
                 0.1);

    Mat layers = (Mat_<int>(3,1) << 2, 4, 1);

    CvANN_MLP net(layers, CvANN_MLP::SIGMOID_SYM, 1, 1);
    net.train(X_train, Y_train, Mat(), Mat(), params);

    Mat predictions(Y_test.size(), CV_32F); 
    net.predict(X_test, predictions);

    cout << predictions << endl;

    Mat error = predictions-Y_test;
    multiply(error, error, error);

    float mse = sum(error)[0]/error.rows;

    cout << "MSE: " << mse << endl;

    return 0;
    }

For me this produces the following output:

[0.9940818;
0.087859474;
0.072328083;
0.032660298;
-0.0090373717;
0.056480117;
0.13302;
-0.025581671;
0.32763073;
1.0263158;
0.29676101;
0.056798562;
0.070351392;
1.0213233;
0.006240299;
0.96525788;
0.071746305;
1.0048869;
-0.015669812;
0.0023532249]
MSE: 0.0326775

As you can see, there are values just below 0 and above 1.

2014-09-10 12:03:54 -0600 received badge  Student (source)
2014-09-10 09:31:33 -0600 asked a question OpenCV MLP with Sigmoid Neurons, Output range

I have searched for answers here on SO and google to the following question, but haven't found anything, so here is my situation:

I want to realize a MLP that learns some similarity function. I have training and test samples and the MLP set up and running. My problem is how to provide the teacher outputs to the net (from which value range).

Here is is the relevant part of my code:

CvANN_MLP_TrainParams params(
    cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000, 0.000001),
    CvANN_MLP_TrainParams::BACKPROP,
    0.1,
    0.1);

Mat layers = (Mat_<int>(3,1) << FEAT_SIZE, H_NEURONS, 1);

CvANN_MLP net(layers, CvANN_MLP::SIGMOID_SYM, 1, 1);

int iter = net.train(X, Y, Mat(), Mat(), params);

net.predict(X_test, predictions);

The number of input and hidden neurons is set somewhere else and the net has 1 output neuron. X, Y, X_test are Mats containing the training and test samples, no problem here. The problem is, from what value range my Y's have to come and from what value range the predictions will come.

In the documentation I have found the following statements:

For training:

If you are using the default cvANN_MLP::SIGMOID_SYM activation function then the output should be in the range [-1,1], instead of [0,1], for optimal results.

Since I'm NOT using the default sigmoid function (the one with alpha=0 and beta=0), I'm providing my Y's from [0,1]. Is this right, or do they mean something else with 'default sigmoid function'? Im asking this, because for prediction they explicitly mention alpha and beta:

If you are using the default cvANN_MLP::SIGMOID_SYM activation function with the default parameter values fparam1=0 and fparam2=0 then the function used is y = 1.7159*tanh(2/3 * x), so the output will range from [-1.7159, 1.7159], instead of [0,1].

Again, since I'm not using the default sigmoid function, I assume to get predictions from [0,1]. Am I right so far?

What is confusing me here is that I've found another question regarding the output range of OpenCV's sigmoid function, that says the range has to be [-1,1].

And now comes the real confusion: When I train the net and let it make some predictions, I get values slightly larger than 1 (around 1.03), regardless if my Y's come from [0,1] or [-1,1]. And this shouldn't happen in either case.

Could somebody please enlighten me? Am I missing something here?

Thanks in advance.

EDIT:

To make things very clear, I came up with a small example that shows the problem:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/ml/ml.hpp>

using namespace cv;
using namespace std;

int main() {

    int POS = 1;
    int NEG = -1;

    int SAMPLES = 100;
    float SPLIT = 0.8;

    float C_X = 0.5;
    float C_Y = 0.5;
    float R = 0.3;

    Mat X(SAMPLES, 2, CV_32FC1);
    Mat Y(SAMPLES, 1, CV_32FC1);

    randu(X, 0, 1);

    for(int i = 0; i < SAMPLES ...
(more)