# 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