In which order to supply weights for SVM?
I have tried very hard to find some kind of answer or documentation on this and I'm sorry if this is obvious.
I'm using OpenCV's SVM on C++. Let's say I use the labels -1,1,2,4 for the different classes, and I want to use cv::ml::SVM::setClassWeights() to assign weights for these labels (let's say these weights are W-1,W1,W2,W4).
The weights vector (cv::Mat) should have 4 rows and 1 column (4 rows because we use 4 different labels) and contain at each row a weight for one of the labels. But which goes where?
Should I set the weights in this vector [W-1,W1,W2,W4]T? Or maybe set the weights in descenting or ascending order by their value and the algorithm figures it out itself?
Thank you.
edit: For clarity I will put the example here too:
Suppose we have 2 features and 100 training samples and the labels for the training data are -1,1,2,4.
training_mat = cv::Mat::zeros(100, 2, CV_32F);
training_mat.ptr<int>(0)[0] = 56; //this might not be the best way to do this but this came in mind
training_mat.ptr<int>(0)[1] = 76;
training_mat.ptr<int>(1)[0] = 86; //these are data
//etc until filled
labels_mat = cv::Mat::zeros(100, 1, CV_32S);
//note: has 1 row for each row of training_mat
labels_mat.ptr<int>(0)[0] = -1;
labels_mat.ptr<int>(1)[0] = 4;
//etc
weights_mat = cv::Mat::zeros(4,1, CV_32F);
weights_mat.at<float>(0, 0)=?
weights_mat.at<float>(1, 0)=?
weights_mat.at<float>(2, 0)=?
weights_mat.at<float>(3, 0)=?
auto svm = cv::ml::SVM::create();
//... C_SVC
svm->setClassWeight(weights_mat);
//...
I know what the weights for each class have to be (let's say for -1 I want them to be 0.1, 1->0.3, 2->0.4, 4->0.2).
Should I do:
weights_mat.at<float>(0, 0)=0.1
weights_mat.at<float>(1, 0)=0.3
weights_mat.at<float>(2, 0)=0.4
weights_mat.at<float>(3, 0)=0.2
or something else?
could you come up with a minimal reproducing example code for this ?
(and append that to your question)
@berak Suppose we have 2 features and 100 training samples and the labels for the training data are -1,1,2,4.
training_mat = cv::Mat::zeros(100, 2, CV_32F);
training_mat.ptr<int>(0)[0] = 56; //this might not be the best way to do this but this came in mind
training_mat.ptr<int>(0)[1] = 76;
training_mat.ptr<int>(1)[0] = 86; //these are data
//etc until filled
labels_mat = cv::Mat::zeros(100, 1, CV_32S);
//note: has 1 row for each row of training_mat
labels_mat.ptr<int>(0)[0] = -1;
labels_mat.ptr<int>(1)[0] = 4;
//etc
weights_mat = cv::Mat::zeros(4,1, CV_32F);
weights_mat.at<float>(0, 0)=?
weights_mat.at<float>(1, 0)=?
weights_mat.at<float>(2, 0)=?
weights_mat.at<float>(3, 0)=?
auto svm = cv::ml::SVM::create();
//... C_SVC
svm->setClassWeight(weights_mat);
//...
@berak A slight comment for my code. I know what the weights for each class have to be (let's say for -1 I want them to be 0.1, 1->0.3, 2->0.4, 4->0.2).
Should I do:
weights_mat.at<float>(0, 0)=0.1
weights_mat.at<float>(1, 0)=0.3
weights_mat.at<float>(2, 0)=0.4
weights_mat.at<float>(3, 0)=0.2
or something else? Thank you.
Something is wrong training_mat = cv::Mat::zeros(100, 2, CV_32F); training_mat.ptr<int>(0)[0] = 56; //CV_32F is not int you should use training_mat.at<float>(0,0)=56;
training_mat.at<float>(0,1)=76;
and weight must be set train data create
@LBerger you are right and it is in my code. I was quoting from memory when I wrote the the previous messages, I don't have a problem with my code running.
As for the question, what you linked actually solves the problem. Thank you! For each train sample I will just have to pass its label's weight. For the sake of curiosity if you happen to know, should cv::ml::SVM::setClassWeights() by generally avoided? Is there is actually an order in which they should be assigned?
I haven't got time today to investigate but svm seems to use svm.params member and I cannot find where sampleWeights is copied in svm.params