Search code examples
matlabimage-processingsvmlibsvmsupervised-learning

2 errors in libsvm matlab "Model does not support probabiliy estimates and Subscripted assignment dimension mismatch"


I want to classify a list of 5 test images using the library LIBSVM with a strategy 'one against all' in order to obtain probabilities for each class. the used code is bellow :

load('D:\xapp.mat');
load('D:\xtest.mat');
load('D:\yapp.mat');%% matrix contains true class of images yapp=[641;645;1001;1010;1100]
load('D:\ytest.mat');%% matrix contains unlabeled class of test set  ytest=[1;2;3;4;5]
numLabels=max(yapp);
numTest=size(ytest,1);
%# train one-against-all models
model = cell(numLabels,1);
for k=1:numLabels
   model{k} = svmtrain(double(yapp==k),xapp, ['-c 1000 -g 10 -b 1 ']);
end
%# get probability estimates of test instances using each model
prob = zeros(numTest,numLabels);
for k=1:numLabels
   [~,~,p] = svmpredict(double(ytest==k), xtest, model{k}, '-b 1');
   prob(:,k) = p(:,model{k}.Label==1);    %# probability of class==k
end
%# predict the class with the highest probability
[~,pred] = max(prob,[],2);
acc = sum(pred == ytest) ./ numel(ytest)    %# accuracy

I obtain this error :

Model does not support probabiliy estimates
Subscripted assignment dimension mismatch.
Error in comp (line 98)
prob(:,k) = p(:,model{k}.Label==1); %# probability of class==k

please, help me to solve this error and thanks in advance


Solution

  • What you're trying to do is to use a code snippet that evaluates a SVM classifier performances whereas your goal is to properly estimate the labels for your test set.

    I assume your five labels are [641;645;1001;1010;1100] (as in yapp). First thing you have to do is delete ytest, because you don't know any labels for the test set. It is pointless to fill ytest with some dummy values: the SVMs will return our predicted labels.

    The first error, as already pointed out in the comments is in

    numLabels=max(yapp);
    

    you must change max() with length() in order to gather the number of classes.

    The training stage is almost correct.
    Given the fact that k goes from 1 to 5 whereas yapp has the range above, you should consider changing double(yapp==k) into double(yapp==yapp(k)): in this manner we mark as positive the k-th value in yapp. Given the fact that k goes from 1 to 5, then yapp(k) will go from 641 to 1100.

    And now the prediction stage.
    The first input for svmpredict() should be the test labels but now we don't know them so we can fill it with a vector of zeros (there will be as many zeros as there are patterns in the test set). That is because svmpredict() automatically returns the accuracy as well if the test labels are known, but that's not the case. So you must change the second for-loop to

    for k=1:numLabels
       [~,~,p] = svmpredict(zeros(size(xtest,1),1), xtest, model{k}, '-b 1');
       prob(:,k) = p(:,model{k}.Label==1);    %# probability of class==k
    end
    

    and finally predict the labels with

    [~,pred] = max(prob,[],2);
    

    and pred contains the predicted labels.

    Note 1: in this method, however, you cannot measure accuracy and/or other parameters because what we called the test set actually is not a test set. A test set is a labelled set and we pretend we don't know its labels in order to let the SVM predict them and then match the predicted labels with the actual labels in order to measure its accuracy.

    Note 2: predicted labels in pred will most likely have values in range 1 to 5 due to the second for-loop. However, since your labels have different values, you can map back taking into account that 1 is 641, 2 is 645, 3 is 1001, 4 is 1010, 5 is 1100.