5

I am trying to implement one vs rest multiclass classification using LIBSVM.

This link was useful http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/ovr_multiclass/ but i get an error in the function 'ovrpredict()'.

The function is as below:

function [pred, ac, decv] = ovrpredict(y, x, model)

labelSet = model.labelSet;
labelSetSize = length(labelSet);
models = model.models;
decv= zeros(size(y, 1), labelSetSize);

for i=1:labelSetSize
  [l,a,d] = svmpredict(double(y == labelSet(i)), x, models{i});
  decv(:, i) = d * (2 * models{i}.Label(1) - 1);             % ERROR IN THIS LINE
end
[tmp,pred] = max(decv, [], 2);
pred = labelSet(pred);
ac = sum(y==pred) / size(x, 1);

The error message i get is Reference to non-existent field 'Label'.

Any suggestions will be really helpful.


EDIT 1

The code used to call the functions:\

[trainY trainX]=libsvmread('libfacecombine.train');
[testY testX]=libsvmread('libfacetest.train');
model=ovrtrain(trainY,trainX,'-c 8 -g 4');
[~,accuracy,~]=ovrpredict(testY,testX,model);

The training and testing data viz 'libfacecombine.train' and 'libfacetest.train' is written obtained from .csv files:

f1=createdabase(f);     % where createdatabase is a function to read various images from a folder and arrange into 1D array
[sig1 mn1]=pcam(f1);    % where pcam is a function to find 'pca'(sig1) and 'mean'(mn1) of the data

%labelling is done this way:
%Positive class
        label=[];
        for i=1:length(sig1)
            for j=1:1
                label(i,j)=+1;
            end
        end
    csvwrite('face1.csv',[label sig1]);

%Negative class
        label1=[];
            for i=1:length(sig2)             % sig2 obtained in same way as sig1
                for j=1:1
                    label1(i,j)=-1;
                end
            end
        csvwrite('face2.csv',[label sig2]);

Using "append" mode both these files are joined and converted to .train files. Same thing is done for the testing data.

EDIT 2

I have 5 classes. And labeling is done as: Class 1: +1 contains features from 4 images of Face 1 and -1 contains features from 4 images of not Face 1(faces 2,3,4 and 5). Class 2: +2 contains features from 4 images of Face 2 and -2 contains features from 4 images of not Face 2(faces 1,3,4 and 5).... Class 5: +5 contains features from 4 images of Face 5 and -5 contains features from 4 images of not Face 5(faces 1,2,3 and 4). All these features along with the labels are written in the above given order to .csv files and then converted to .train format. Hence i obtain the training file.

For the test image i take one image of face 1 and give its true label i.e +1 and written into .csv file and then converted to .train. Hence i obtain the testing file. When i run the program i obtain results such as:

Accuracy=92%(12/13)classification; 
Accuracy=61%(8/13)classification;
Accuracy=100%(13/13)classification;
Accuracy=100‌​%(13/13)classification;
Accuracy=100%(13/13)classification;
Accuracy=100%(13/13)cla‌​ssification; 

Why am i obtaining 6 accuracy values when i have only 5 classes?

Community
  • 1
  • 1
Sid
  • 249
  • 5
  • 16
  • 1
    how are you calling the function? You need to show your code and the part where you train the models. Also would help if you describe your data as well.. btw I have already showed how to perform one-vs-all classification with libsvm in previous answers, see [here](http://stackoverflow.com/a/14042056/97160) and [here](http://stackoverflow.com/a/9049808/97160). – Amro May 13 '14 at 11:47
  • Can you confirm that the error message you get is `Undefined variable Label`? When you accidentally refer to a variable that doesn't exist, that's not the exact text you would get, which makes me think that you are possibly misremembering the error. In addition, I'm not sure how you could get that error from this line. Perhaps it was `Reference to non-existent field 'Label'` instead? – Sam Roberts May 13 '14 at 14:07
  • @Amro: My dataset is that of face images. I am doing face recognition. I have seen your previous answers but both use fisheriris and the way i have labelled my data is different from this dataset. I will get back with the code where i am callinf the functions. – Sid May 14 '14 at 09:20
  • @SamRoberts: Yes the error message was "Reference to non-existent field 'Label' ". Sorry i had misremembered. How do i overcome it? – Sid May 14 '14 at 09:21
  • @Sid: I dont get it, according to your code above you have two classes (positive and negative instances). So why do need to perform one-vs-rest when you only have a binary classification? Also you are still not providing enough information about your data: how many features do you have? what is the type of class labels? how do you get from the CSV files to the libsvm sparse representaion? If possible you should post a small sample of the data, and a reproducible example code.. – Amro May 17 '14 at 08:44
  • @Amro: (1)I have just given example of 2-class SVM, i want to extend it to n-class SVM , that's why trying to use the above mentioned functions.(2) And i have extracted PCA features(taken the components which give maximum variance).(3) The class labels will be of the form model 1(+1,-1) , model 2(+2,-2)... ans so on. In model 1 the positive class(+1) will have face 1 training images and the negative class(-1) will have all other face images(except face 1 images), – Sid May 19 '14 at 14:21
  • In model 2 the positive class(+2) will have face 2 training images and the negative class(-2) will have all other face images(except face 2 images) and so on. Then the test image needs to be compared with all of these models and the one giving highest accuracy match with test image will be the model to which the test face belongs(to the positive class of that model). – Sid May 19 '14 at 14:23

2 Answers2

3

Finding the solution to something like this is tricky over the internet, but let's have a try. This post is comprised of questions rather than answers. However, I believe that if you answer them all you will find your bug without further help – or at least be 90% of the way there.

All these steps are sensible for debugging any type of MATLAB program.


Ensuring a clear workspace

Old versions of variables hanging around in the workspace can make it hard to debug. A mispelling in a variable name can cause an old version to be used by accident. Clear your workspace with clear at the start of your debugging.


Running a simpler program

I have compiled libsvm, added the ovr_multiclass addons, and I can succesfully run the following example script that I made up:

clear

% random train and test data
trainX = rand(10, 4);
trainY = randi(4, 10, 1);
testX = rand(10, 4);
testY = randi(4, 10, 1);

model=ovrtrain(trainY,trainX,'-c 8 -g 4'); 
[~,accuracy,~]=ovrpredict(testY,testX,model);

Can you run this, or do you get the same error as before? This sort of minimum working example is really useful for debugging. Using small, user-generated data ensures that the errors don't come from unexpected sources and helps to narrow down the cause.


Examining the models cell array

You state that the error is occuring in this :

decv(:, i) = d * (2 * models{i}.Label(1) - 1);             % ERROR IN THIS LINE

The critical part of the line is models{i}.Label(1). This is taking a cell array models, and extracting the ith item. This ith item is expected to be a structure, with a field called Label. Label is expected to be a non-empty array, from which the first element can be extracted. The models cell array is a field in the structure model, which is passed in as a third argument to ovrpredict.

After running my very simple test script above, I run the following diagnostics in the MATLAB command window:

>> models = model.models

models = 

    [1x1 struct]
    [1x1 struct]
    [1x1 struct]
    [1x1 struct]

>> models{1}

ans = 

    Parameters: [5x1 double]
      nr_class: 2
       totalSV: 6
           rho: -1.2122
         Label: [2x1 double]
    sv_indices: [6x1 double]
         ProbA: []
         ProbB: []
           nSV: [2x1 double]
       sv_coef: [6x1 double]
           SVs: [6x4 double]

>> models{1}.Label

ans =

     0
     1

If you do the same, do you get the same result? If not, post your output to these commands in an edit to your question.


Debugging in the function

If the model looks OK but you are still getting the error, turn on the error debugger by typing this into the command window:

dbstop if error

When MATLAB encounters an error in a function it will now pause and allow you to inspect all the variables.

Run your program again (or mine, if you are getting the error with the minimum working example I posted). The program should pause when the error occurs. Your command prompt should change from >> to K>>.

Run through the steps above to example the model cells array. Then try copying, pasting and running the line of code which gave the error in the command window. Try running a smaller portion of it, e.g. models{i}.Label(1) then 2 * models{i}.Label(1) - 1.

Type dbquit to exit the debugger, and dbclear if error to turn off the automatic debugging on error.

(See also my question below about the error message – make sure that the error is actually occuring where you think it is!)


Edit: Some extra questions

  • What version of MATLAB are you using? e.g. R2013a

  • If you type which ovrpredict into the MATLAB command line, do you see the path to the file that you expect? (i.e. the correct path to ovrpredict.m as you have it saved on your computer)

  • Does your ovrpredict.m file (as pointed to by which ovrpredict) contain exactly what you have pasted in your question? The error you are getting suggests their might be a tiny difference, e.g. an extra space.

Bill Cheatham
  • 11,396
  • 17
  • 69
  • 104
  • 1
    Thank you so much. By debugging the function i figured out what was wrong. I had previously changed the variable names while trying to correct the error and somewhere down the line the model, models, labelset, Label had got all mixed up. Thank you once again for the function debugging technique, its really helpful! – Sid May 20 '14 at 08:49
  • the code works perfectly for small dataset but goes on training without a stop(went on for upto two hours! Obviously something was wrong) for the caltech database i'm using. Any suggestions? – Sid May 29 '14 at 06:09
  • How big is the Caltech database? What happens if you subsample the Caltech database to be say 100th of the size? Training models can take a long time (sometimes more than a day!) if there is a lot of data and the model is complex. This new question may be outside the scope of this question, and might need a question of its own... – Bill Cheatham May 29 '14 at 14:11
  • Bill, ya its because of the size of the database , i split it into smaller sets and could obtain the results. Now the thing is, i don't really understand the results. – Sid May 30 '14 at 06:08
  • I have 5 classes. And labeling is done as: Class 1: +1 contains features from 4 images of Face 1 and -1 contains features from 4 images of not Face 1(faces 2,3,4 and 5). Class 2: +2 contains features from 4 images of Face 2 and -2 contains features from 4 images of not Face 2(faces 1,3,4 and 5).... Class 5: +5 contains features from 4 images of Face 5 and -5 contains features from 4 images of not Face 5(faces 1,2,3 and 4). All these features along with the labels are written in the above given order to .csv files and then converted to .train format. Hence i obtain the training file. – Sid May 30 '14 at 06:15
  • For the test image i take one image of face 1 and give its true label i.e +1 and written into .csv file and then converted to .train. Hence i obtain the testing file. When i run the program i obtain results such as: Accuracy=92%(12/13)classification; Accuracy=61%(8/13)classification;Accuracy=100%(13/13)classification;Accuracy=100%(13/13)classification;Accuracy=100%(13/13)classification;Accuracy=100%(13/13)classification; – Sid May 30 '14 at 06:19
  • Why am i obtaining 6 accuracy values when i have only 5 classes? – Sid May 30 '14 at 06:19
  • I think this would best be asked as a new question as this discussion is getting very far from your original query – plus it is hard to see the formatting that is present in these comments! – Bill Cheatham Jun 02 '14 at 13:07
2

Though I am not sure on how to solve this, here are my observations:

In ovrtrain a model is created with the only addition field being labelSet.

Later in overpredict the code tries to read out label.

So, I see three options:

  1. The creation of the model is wrong
  2. A step in the middle is forgotten
  3. The using of the model is wrong

EDIT: THIS PART IS PROBABLY NOT THE SOLUTION, AS MENTIONED IN THE COMMENTS

I have insufficient information to know which of these applies, but if no examples are provided with the code you could try replacing Label by labelSet everywhere.

Note that if it is point 1 or 3, this code should always provide an error and never run properly.

Dennis Jaheruddin
  • 21,208
  • 8
  • 66
  • 122
  • I'll try to replace Label by LabelSet everywhere and get back to you with the results. Thanks! – Sid May 15 '14 at 05:21
  • -1 that wont be correct; `model` is a struct returned by `svmtrain` as a result of creating an SVM model (called multiple times all grouped in another struct). Now since the training is performed in a one-vs-rest fashion (1-vs-not1, 2-vs-not2, ..), each time the `Label` field will contain only two class labels `[0 1]` (value 1 corresponding to instances from class `i` and 0 for the rest). On the other hand, `labelSet` is built from the entire set of labels, and contains all possible class values (`[1 2 3 ..]`). As it stand, the question does not provide enough info to be adequately answered.. – Amro May 17 '14 at 08:43
  • 1
    I am sure that @Amro is correct, but as I don't know how to make the answer better I have decided to place a warning next to my suggestion, and maintain the more general part as it may help you to structurally approach the problem. – Dennis Jaheruddin May 19 '14 at 09:13
  • @DennisJaheruddin: (1)I have just given example of 2-class SVM, i want to extend it to n-class SVM , that's why trying to use the above mentioned functions.(2) And i have extracted PCA features(taken the components which give maximum variance).(3) The class labels will be of the form model 1(+1,-1) , model 2(+2,-2)... ans so on.In model 1 the positive class(+1) will have face 1 training images and the negative class(-1) will have all other face images(except face 1 images), – Sid May 19 '14 at 14:27
  • In model 2 the positive class(+2) will have face 2 training images and the negative class(-2) will have all other face images(except face 2 images) and so on. Then the test image needs to be compared with all of these models and the one giving highest accuracy match with test image will be the model to which the test face belongs(to the positive class of that model). – Sid May 19 '14 at 14:29