Opencv classifier update error - c++

I am getting an error while trying to update the CvBoost classifier in OpenCV, the error i am getting is as follows
OpenCV Error: Bad argument (The new training data must have the same types and the input and output variables and the same categories for categorical variables) in CvDTreeTrainData::set_data, file /home/bsoni/Downloads/OpenCV-2.4.1/modules/ml/src/tree.cpp, line 172
Basically i am working on a 2 class problem and initially i train the classifier with a set of SURF features. So the process is that i initially train the classifier using a set of surf descriptors.
data.surf_features are a set of 128 bit SURF descriptors
data.surf_classes are a set of class labels which are either +1 or -1
Initially i train the classifier using
void train()
{
CvBoostParams params(CvBoost::REAL,80,0.95,2,false,0);
aSurfBoost.train(data.surf_features,CV_ROW_SAMPLE,data.surf_classes,Mat(),Mat(),Mat(),Mat(),params,false);
}
following that i try to re-train the classifier using the code below
void train()
{
CvBoostParams params(CvBoost::REAL,80,0.95,2,false,0);
aSurfBoost.train(data.surf_features,CV_ROW_SAMPLE,data.surf_classes,Mat(),Mat(),Mat(),Mat(),params,true);
}
the only think i am changing is setting the update parameter to true.
I have checked the Mat.type of the descriptors and in both cases they are the exact same thing.
any suggestions solutions or possibly even workarounds would be welcome.

Related

extracting output data from typed_output_tensor in TFlite

Thanks in advance for your support.
I'm trying to get the output of a tensor after the inference on a .tflite U-net neural network. I'm using Tensorflow lite image classification code as a baseline.
I need to adapt the code for a segmentation task. My question is how I can access the output of the inferenced model (which 128x128x1) and write the result into an image?
I already debugged the code and explored many different approaches. Unfortunately, I'm not confident with the C++ language. What I found is that the command: interpreter->typed_output_tensor<float>(0) should be what I need, as also referenced here: https://www.tensorflow.org/lite/guide/inference#loading_a_model. However, I cannot access the 128x128 tensor generated by the network.
You can find the code at the address: https://github.com/tensorflow/tensorflow/blob/770481fb3e9126f9a29db5667f528e450d54d719/tensorflow/lite/examples/label_image/label_image.cc
The interesting part is here (lines 217 -224):
const float threshold = 0.001f;
std::vector<std::pair<float, int>> top_results;
int output = interpreter->outputs()[0];
TfLiteIntArray* output_dims = interpreter->tensor(output)->dims;
// assume output dims to be something like (1, 1, ... ,size)
auto output_size = output_dims->data[output_dims->size - 1];
I expect the values saved in an image or an alternative way of saving the output tensor

tensorflow: transpose expects a vector of size 1. But input(1) is a vector of size 2

I want to use a trained RNN language model to do inference.So:
I loaded the trained model graph in c++ using
tensorflow::MetaGraphDef graph_def;
TF_CHECK_OK(ReadBinaryProto(Env::Default(), path_to_graph, &graph_def));
TF_CHECK_OK(session->Create(graph_def.graph_def()));
load the model parameters by:
Tensor checkpointPathTensor(tensorflow::DT_STRING, tensorflow::TensorShape());
checkpointPathTensor.scalar<std::string>()() = path_to_ckpt;
TF_CHECK_OK(session_->Run({{graph_def.saver_def().filename_tensor_name(), checkpointPathTensor} },{},{graph_def.saver_def().restore_op_name()},nullptr));
up till now, everything goes fine. Then I want to compute the value of the node "output/output_batch_major":
TF_CHECK_OK(session->Run(inputs,{"output/output_batch_major"},{"post_control_dependencies"}, &outputs));
I got the error:
2018-07-13 14:13:36.793495: F tf_lm_model_loader.cc:190] Non-OK-status: session->Run(inputs,{"output/output_batch_major"},{"post_control_dependencies"}, &outputs) status: Invalid argument: transpose expects a vector of size 1. But input(1) is a vector of size 2
[[Node: extern_data/placeholders/delayed/sequence_mask_time_major/transpose = Transpose[T=DT_BOOL, Tperm=DT_INT32, _device="/job:localhost/replica:0/task:0/device:CPU:0"](extern_data/placeholders/delayed/SequenceMask/Less, extern_data/placeholders/delayed/sequence_mask_time_major/transpose/perm)]]
Aborted (core dumped)
I checked the graph using tensorboard, extern_data/placeholders/delayed/sequence_mask_time_major/transpose/perm is a Tensor with size 2, is this Tensor the input(1) in the error? How can I fix the problem?Any idea? Thanks in advance!
I had a similar issue on the input tensor to my predictor. I expanded the dimension by one and the issue was resolved. I suggest running the predictor in python, first. This helps to identify the size of the input tensor that you are passing to the predictor. Then, replicate the exact same size in C++. Also, based on your code snippet, I am not sure how you define the inputs to the Run method. I defined is as follows in my code:
std::vector<std::pair<std::string, tensorflow::Tensor>> input = {
{"input_1", input_tensor }
};
where "input_1" is the name of my input layer.
I hope this helps.
I get this error when pass wrong input type into tensorflow model. The model require 3d dimension array, I pass 1d dimension instead of so check your input data first.

Error when using Decision Trees in OpenCV 3.0.0-rc1

I am doing some machine learning in OpenCV and i'm using Decision Trees. I am currently using OpenCV 3.0.0-rc1. Whenever i attempt to train Decision Trees with my training data and labels, i get either
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
or
Segmentation fault
Depending on what i put into setMaxDepth(); if the number is larger than 22, it's bad_alloc, else it's seg fault.
Here's my source code:
//import data
Mat trainData=imread("/home/jetson/Documents/CB/ml/td.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat labels=imread("/home/jetson/Documents/CB/ml/lab.jpg",CV_LOAD_IMAGE_GRAYSCALE);
//convert to the right type
trainData.convertTo(trainData,CV_32FC1);
labels.convertTo(labels,CV_32SC1);
transpose(trainData,trainData);
Ptr<ml::TrainData> tData = ml::TrainData::create(trainData, ml::ROW_SAMPLE, labels);
cout <<"Training data ready\n";
Ptr<ml::DTrees> dec_trees = ml::DTrees::create();
//params
dec_trees->setMaxDepth(1);
dec_trees->setMinSampleCount(10);
dec_trees->setRegressionAccuracy(0.01f);
dec_trees->setUseSurrogates(false);
dec_trees->setMaxCategories(2);
dec_trees->setCVFolds(10);
dec_trees->setUse1SERule(true);
dec_trees->setTruncatePrunedTree(true);
dec_trees->setPriors(Mat());
cout <<"Params set\n";
dec_trees->train(tData);
cout <<"Done!\n";`
In addition to this, when i try to train a SVM model with the same data, using the same steps (below) it works just fine.
Ptr<ml::SVM> svm = ml::SVM::create();
//params
svm->setType(ml::SVM::C_SVC);
svm->setKernel(ml::SVM::POLY);
svm->setGamma(3);
svm->setDegree(0.1);
cout <<"Params set\n";
svm->train(tData);
cout <<"Done!\n";
I need to point out that the error occurs when i try to train the model. I'm using the default parameters for decision trees, as suggested on the OpenCV documentation page.
Does anybody know what's wrong here and how to go about fixing my problem?
Thanks in advance.
EDIT: I upgraded OpenCV to version 3.0.0 and the issues stay the same

SVM parameter optimization in Opencv

I want to optimize SVM parameters in Opencv. But, every time I use train_auto I get C=1 and gamma=1. Some people use LibSVM but I could not write a wrapper for that. Both trainingData and labels are taken from an existing code which gives good results so I am trying to get the same parameters for that code with train_auto. In the original code C=312.5 and gamma=0.50625. I saw that somebody used CvStatModel for python, is it necessary for C++? Where do I make a mistake?
Thanks in advance.
The Code:
CvParamGrid CvParamGrid_C(pow(2.0,-5), pow(2.0,15), pow(2.0,2));
CvParamGrid CvParamGrid_gamma(pow(2.0,-15), pow(2.0,3), pow(2.0,2));
if (!CvParamGrid_C.check() || !CvParamGrid_gamma.check())
cout<<"The grid is NOT VALID."<<endl;
CvSVMParams paramz;
paramz.kernel_type = CvSVM::RBF;
paramz.svm_type = CvSVM::C_SVC;
paramz.term_crit = cvTermCriteria(CV_TERMCRIT_ITER,100,0.000001);
svm.train_auto(trainingData, labels, Mat(), Mat(), paramz,10, CvParamGrid_C, CvParamGrid_gamma, CvSVM::get_default_grid(CvSVM::P), CvSVM::get_default_grid(CvSVM::NU), CvSVM::get_default_grid(CvSVM::COEF), CvSVM::get_default_grid(CvSVM::DEGREE), true);
svm.get_params();
cout<<"gamma:"<<paramz.gamma<<endl;
cout<<"C:"<<paramz.C<<endl;
I modified the code as follows paramz = svm.get_params() and it worked fine.

Can I increase number of SVM training label in OpenCV?

I'm building OCR application with Visual Studio 2010, C++, SVM in OpenCV. It's ok when I train SVM with under 181 different labels but fails when over 181 labels. Below is IDE and OpenCV error message and my code. Please help me, thank you so much!
IDE error message
First-chance exception at 0x771e4b32 in OCR.exe: Microsoft C++
exception: cv::Exception at memory location 0x0081da74.. The thread
'Win32 Thread' (0xdac) has exited with code -1073741510 (0xc000013a).
The program '[2512] OCR.exe: Native' has exited with code -1073741510
(0xc000013a).
OpenCV error message
......\src\opencv\modules\core\src\datastructs.cpp:332: error: (-211)
requested size is negative or too big
SVM's configuration
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
SVM.train( training_vectors, training_labels, cv::Mat(), cv::Mat(), params );
libSVM uses "one vs all" technique to represent multi-class problem using the binary SVM classifier. It means, that if you have N (>2) labels, libSVM will generate N distinct classifiers, each with different data labeling (so it expresses the "one vs all" scheme). This can lead to the memory problems that you are experiencing. Some other models like for example neural networks or knn can represent the multi-class classification without such overhead. So if your data is to large to treat it the way libsvm does you have at least three possible options:
Change SVM to some other model, which can directly addresss mutli-label classification
Try to use other, lighter implementation of the library, especially that opencv does not use the most recent implementation of libsvm (it could help, but does not have to)
You can manually do the "one vs all" implementation and save each separate model. This way you should avoid the memory problems, as at any time you will allocate at most as much memory as it is needed for a binary problem. At the end you just load your models from file and apply simple voting scheme. If saved models are too big, it means that your model overfitted (in SVMs the overfitting is usually expressed as too big number of support vectors, which are in fact the only thing needed to define the model - so if the model has too many sv's to load them to memory it means that it is most probably incorrectly trained and you should try different parameters/kernels)