Bad results when testing libsvm in matlab - matlab

can someone help me to solve this?
I want to test whether this classification is already good or not. So, I try with data testing=data training. it will give 100% (acc) if the classification is good.
this is the code that I found from this site:
data= [170 66 ;
160 50 ;
170 63 ;
173 61 ;
168 58 ;
184 88 ;
189 94 ;
185 88 ]
labels=[-1;-1;-1;-1;-1;1;1;1];
numInst = size(data,1);
numLabels = max(labels);
testVal = [1 2 3 4 5 6 7 8];
trainLabel = labels(testVal,:);
trainData = data(testVal,:);
testData=data(testVal,:);
testLabel=labels(testVal,:);
numTrain = 8; numTest =8
%# train one-against-all models
model = cell(numLabels,1);
for k=1:numLabels
model{k} = svmtrain(double(trainLabel==k), trainData, '-c 1 -t 2 -g 0.2 -b 1');
end
%# get probability estimates of test instances using each model
prob = zeros(numTest,numLabels);
for k=1:numLabels
[~,~,p] = svmpredict(double(testLabel==k), testData, 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 == testLabel) ./ numel(testLabel) %# accuracy
C = confusionmat(testLabel, pred) %# confusion matrix
and this is the results:
optimization finished, #iter = 16
nu = 0.645259 obj = -2.799682,
rho = -0.437644 nSV = 8, nBSV = 1 Total nSV = 8
Accuracy = 100% (8/8) (classification)
acc =
0.3750
C =
0 5
0 3
I dont know why there's two accuracy, and its different. the first one is 100% and the second one is 0.375. is my code false? it should be 100% not 37.5%. Can u help me to correct this code??

If your using libsvm then you should change the name of the MEX file since Matlab already has a svm toolbox with the name svmtrain. However, the code is running so it seems you did change the name just not on the code you provided.
The second one is wrong, don't know exactly why. However, I can tell you that you will almost always get 100% accuracy if you use the test_Data = training_Data. That result really does not mean anything, since the algorithm can be overfit and not be shown in your results. Test your algorithm against new data and that will give you a realistic accuracy.

Is that the code you're using? I don't think your svmtrain invocation is valid. You should have svmtrain(MAT, VECT, ...) where MAT is a matrix of data, and VECT is a vector with the labels of each row of MAT. The remaining parameters are string-value pairs, meaning you'll have a string identifier and its corresponding valie.
When I ran your code (Linux, R2011a) I got an error on the svmtrain call. Running with svmtrain(trainData, double(trainLabel==k)) gave a valid output (for that line). Of course, it appears that you're not using pure matlab, as your svmpredict call isn't native matlab, but rather a matlab binding from LIBSVM...

C = confusionmat(testLabel, pred)
swap their positions
C= confusionmat(pred,testLabel)
or use this
[ConMat,order] = confusionmat(pred,testLabel)
shows the confusion matrix and the class order

The problem is in
[~,~,p] = svmpredict(double(testLabel==k), testData, model{k}, '-b 1');
p does not contain the predicted labels, it has the probability estimates of the labels being correct. LIBSVM's svmpredict already calculates accuracy for you correctly, that's why it says 100% in the debug output.
The fix is simple:
[p,~,~] = svmpredict(double(testLabel==k), testData, model{k}, '-b 1');
According to LIBSVM's Matlab bindings README:
The function 'svmpredict' has three outputs. The first one,
predictd_label, is a vector of predicted labels. The second output,
accuracy, is a vector including accuracy (for classification), mean
squared error, and squared correlation coefficient (for regression).
The third is a matrix containing decision values or probability
estimates (if '-b 1' is specified). If k is the number of classes
in training data, for decision values, each row includes results of
predicting k(k-1)/2 binary-class SVMs. For classification, k = 1 is a
special case. Decision value +1 is returned for each testing instance,
instead of an empty vector. For probabilities, each row contains k values
indicating the probability that the testing instance is in each class.
Note that the order of classes here is the same as 'Label' field
in the model structure.

I am sorry to tell that all answers are totally wrong!!
The main error done in the code is:
numLabels = max(labels);
because it returns (1), although it should return 2 if the labels are positive numbers, and then svmtrain/svmpredict will loop twice.
Anyway, change line labels=[-1;-1;-1;-1;-1;1;1;1];
to labels=[2;2;2;2;2;1;1;1];
and it will work successfully ;)

Related

Predicting same values for entire test Set in MATLAB using LIBSVM

I am using Support Vector Regression(SVR) in libsvm package to predict outputs. Kernel : RBF
Train set size : 729x40
Test set size : 137x40
The output of train set seems fine when measured against ground truth. But the predictions on test set are all the same. It outputs same values.
After checking the related posts, I normalized the data and played with the values of gamma(10-100000) but still the problem persists.
trainGT=games(((games(:,46)>=2010) & (games(:,46)<2015) & (games(:,1)~=8)),43);
featuresTrain=lastGame(games,true,1);
testGT=games((games(:,46)>=2015 & (games(:,1)~=8)),43);
featureTest=lastGame(games,false,1);
eval(['model = svmtrain( trainGT, featuresTrain,''-s 4 -t 2 -c 10 -g 10 ' ''');']);
w = (model.sv_coef' * full(model.SVs));
b = -model.rho;
predictionsTrain = svmpredict(trainGT, featuresTrain,model);
predictionsTest = svmpredict(zeros(length(testGT),1), featureTest, model);
My output is as follows
optimization finished, #iter = 1777
epsilon = 0.630588
obj = -19555.036253, rho = -17.470386
nSV = 681, nBSV = 118
Mean squared error = 305.214 (regression)
Squared correlation coefficient = -1.#IND (regression)
All my predictionTest values are 17.4704 (which is same as the rho value in the output). Can someone please help me on this? Thanks.

libsvm: optimization finished, #iter = 1 nu = nan

I use libsvm to train a svm model in matlab, but when I call
model = svmtrain(labels,Feature,'-t 0');
It gives me this result:
*
optimization finished, #iter = 1
nu = nan
obj = nan, rho = nan
nSV = 0, nBSV = 0
Total nSV = 0
My positive and negative samples are of almost equal number: 935 vs 904 so this problem is not caused by unbalanced training dataset. Also I tried other kernels and none of them work.
You do not want to use svmtrain any more. The new version is templatesvm paired with fitcecoc. The datapages on both functions are quite extensive.
You'll eventually want to use your model to predict other data, use predict for that.
I recently encoutered similar problems when trying to classify terrain in a point cloud with more than two classes. templatesvm and fitcecoc solved my problems.
The code I used is as follows, where trainingdata is my 5 dimensional training data and groups contains the label for each class, which correspond to the cell array classes.
SVMtemp = templateSVM('KernelFunction','polynomial','IterationLimit',1e4,...
'PolynomialOrder',4,'OutlierFraction',ExpOut,...
'Standardize',true); % Create SVM template
Model = fitcecoc(trainingdata(:,4:8),groups,'learners',SVMtemp,'ClassNames',...
classes); % Create the SVM model

libsvm output prediction probability for multi-label classification

I am trying to use libsvm (with Matlab interface) to run some multi-label classification problem. Here is some toy problem using IRIS data:
load fisheriris;
featuresTraining = [meas(1:30,:); meas(51:80,:); meas(101:130,:)];
featureSelectedTraining = featuresTraining(:,1:3);
groundTruthGroupTraining = [species(1:30,:); species(51:80,:); species(101:130,:)];
[~, ~, groundTruthGroupNumTraining] = unique(groundTruthGroupTraining);
featuresTesting = [meas(31:50,:); meas(81:100,:); meas(131:150,:)];
featureSelectedTesting = featuresTesting(:,1:3);
groundTruthGroupTesting = [species(31:50,:); species(81:100,:); species(131:150,:)];
[~, ~, groundTruthGroupNumTesting] = unique(groundTruthGroupTesting);
% Train the classifier
optsStruct = ['-c ', num2str(2), ' -g ', num2str(4), '-b ', 1];
SVMClassifierObject = svmtrain(groundTruthGroupNumTraining, featureSelectedTraining, optsStruct);
optsStruct = ['-b ', 1];
[predLabelTesting, predictAccuracyTesting, ...
predictScoresTesting] = svmpredict(groundTruthGroupNumTesting, featureSelectedTesting, SVMClassifierObject, optsStruct);
However, for the predict probabilities I have got (the first 12 rows of results showed here)
1.08812899093155 1.09025554950852 -0.0140009056912001
0.948911671379753 0.947899227815959 -0.0140009056926024
0.521486301840914 0.509673405799383 -0.0140009056926027
0.914684487894784 0.912534150299246 -0.0140009056926027
1.17426551505833 1.17855350325579 -0.0140009056925103
0.567801459258613 0.557077025701113 -0.0140009056926027
0.506405203427106 0.494342606399178 -0.0140009056926027
0.930191457490471 0.928343421250020 -0.0140009056926027
1.16990617214906 1.17412523596840 -0.0140009056926026
1.16558843984163 1.16986137054312 -0.0140009056926015
0.879648874624610 0.876614924593740 -0.0140009056926027
-0.151223818963057 -0.179682730685229 -0.0140009056925999
I am confused that how some of the probabilities are larger than 1 and some of them are negative?
However, the predicted label seems quite accurate:
1
1
1
1
1
1
1
1
1
1
1
3
with final output of
Accuracy = 93.3333% (56/60) (classification)
Then how to interpret the results of the predicted probabilities? Thanks a lot. A.
The output of an svm are not probabilities!
The score's sign indicates whether it belongs to class A or class B. And if the score is 1 or -1 it is on the margin, although that is not particularly useful to know.
If you really need probabilities, you can convert them using Platt scaling. You basically apply a sigmoid function to them.
I understand that this answer is probably too late, but it may benefit people encountering the same problem.
libsvm can in fact produce probabilities, for which the option '-b' is used.
I think the mistake you made is in the way you defined the optsStruct variable. It should be defined like this: ['-b ' num2str(1)] OR ['-b 1'].
The same applies to the options sent to the svmtrain.

Use the osusvm to recognize faces after the C2 layer in HMAX model

I achieved the computation of the original HMAX model, and I get the results at C2 layer. Now I still have the tuned-layer, in other words, to use the osusvm.
In my project, I have two directories. One containing the training images and other containing the test images.
Reference: lennon310's response in Training images and test images
Firstly, I would like to show you my results at C2 layer (surely that the results should be a vectors). Notice that I extracted only 2 prototypes in the S2 layer (in my project I used 256 prototypes, but only in this question, assume that I used only 2 prototypes), and four prototypes sizes:[4 8 12 16]. So for each image, we get 8 C2 units (2 prototypes x 4 patch sizes = 8).
C2res{1}: For the six training images:
0.0088 0.0098 0.0030 0.0067 0.0063 0.0057
0.0300 0.0315 0.0251 0.0211 0.0295 0.0248
0.1042 0.1843 0.1151 0.1166 0.0668 0.1134
0.3380 0.2529 0.3709 0.2886 0.3938 0.3078
0.2535 0.3255 0.3564 0.2196 0.1681 0.2827
3.9902 5.3475 4.5504 4.9500 6.7440 4.4033
0.8520 0.8740 0.7209 0.7705 0.4303 0.7687
6.3131 7.2560 7.9412 7.1929 9.8789 6.6764
C2res{2}: For the two test images:
0.0080 0.0132
0.0240 0.0001
0.1007 0.2214
0.3055 0.0249
0.2989 0.3483
4.6946 4.2762
0.7048 1.2791
6.7595 4.7728
Secondly, I downloaded the osu-svm matlab toolbox and I added its path:
addpath(genpath('./osu-svm/')); %put your own path to osusvm here
useSVM = 1; %if you do not have osusvm installed you can turn this
%to 0, so that the classifier would be a NN classifier
%note: NN is not a great classifier for these features
Then I used the code below:
%Simple classification code
XTrain = [C2res{1}]; %training examples as columns
XTest = [C2res{2}]; %the labels of the training set
ytrain = [ones(size(C2res{1},2),1)];%testing examples as columns
ytest = [ones(size(C2res{2},2),1)]; %the true labels of the test set
if useSVM
Model = CLSosusvm(XTrain,ytrain); %training
[ry,rw] = CLSosusvmC(XTest,Model); %predicting new labels
else %use a Nearest Neighbor classifier
Model = CLSnn(XTrain, ytrain); %training
[ry,rw] = CLSnnC(XTest,Model); %predicting new labels
end
successrate = mean(ytest==ry) %a simple classification score
Does the code just above is true ? Why I always get a successrate=1 ? I think that I am wrong in some places. Please I need help. If it is true, does another way to compute that ? What can I use instead of successrate in order to get more sexy results?
Note:
The function CLSosusvm is :
function Model = CLSosusvm(Xtrain,Ytrain,sPARAMS);
%function Model = CLSosusvm(Xtrain,Ytrain,sPARAMS);
%
%Builds an SVM classifier
%This is only a wrapper function for osu svm
%It requires that osu svm (http://www.ece.osu.edu/~maj/osu_svm/) is installed and included in the path
%X contains the data-points as COLUMNS, i.e., X is nfeatures \times nexamples
%y is a column vector of all the labels. y is nexamples \times 1
%sPARAMS is a structure of parameters:
%sPARAMS.KERNEL specifies the kernel type
%sPARAMS.C specifies the regularization constant
%sPARAMS.GAMMA, sPARAMS.DEGREE are parameters of the kernel function
%Model contains the parameters of the SVM model as returned by osu svm
Ytrain = Ytrain';
if nargin<3
SETPARAMS = 1;
elseif isempty(sPARAMS)
SETPARAMS = 1;
else
SETPARAMS = 0;
end
if SETPARAMS
sPARAMS.KERNEL = 0;
sPARAMS.C = 1;
end
switch sPARAMS.KERNEL,
case 0,
[AlphaY, SVs, Bias, Parameters, nSV, nLabel] = ...
LinearSVC(Xtrain, Ytrain, sPARAMS.C);
case 1,
[AlphaY, SVs, Bias, Parameters, nSV, nLabel] = ...
PolySVC(Xtrain, Ytrain, sPARAMS.DEGREE, sPARAMS.C, 1,0);
case 2,
[AlphaY, SVs, Bias, Parameters, nSV, nLabel] = ...
PolySVC(Xtrain, Ytrain, sPARAMS.DEGREE, sPARAMS.C, 1,sPARAMS.COEF);
case 3,
[AlphaY, SVs, Bias, Parameters, nSV, nLabel] = ...
RbfSVC(Xtrain, Ytrain, sPARAMS.GAMMA, sPARAMS.C);
end
Model.AlphaY = AlphaY;
Model.SVs = SVs;
Model.Bias = Bias;
Model.Parameters = Parameters;
Model.nSV = nSV;
Model.nLabel = nLabel;
Model.sPARAMS = sPARAMS;
The function CLSosusvmC is :
function [Labels, DecisionValue]= CLSosusvmC(Samples, Model);
%function [Labels, DecisionValue]= CLSosusvmC(Samples, Model);
%
%wrapper function for osu svm classification
%Samples contains the data-points to be classified as COLUMNS, i.e., it is nfeatures \times nexamples
%Model is the model returned by CLSosusvm
%Labels are the predicted labels
%DecisionValue are the values assigned by the Model to the points (Labels = sign(DecisionValue))
[Labels, DecisionValue]= SVMClass(Samples, Model.AlphaY, ...
Model.SVs, Model.Bias, ...
Model.Parameters, Model.nSV, Model.nLabel);
Labels = Labels';
DecisionValue = DecisionValue';
Your code looks good to me.
Since you have only 2 test images, the possible successful rate will be limited to 0, 0.5, 1. And it is expected to achieve the 100% accuracy with a 25% probability ([0 1],[1 0],[1 1],[0 0]). You can shuffle the data, and re-select 2 from the 8 as the test for some times, then observe the accuracy.
Also try to add more images to both training and test samples.
Machine learning has little sense on the set of 8 images. Gather at least 10x more data, and then analyze the results. With such small dataset any results are possible (from 0 to 100 percent), and none of them is realiable.
Meanwhile you can try to perform repeated cross validation:
Shuffle your data
Split it to two-element parts ( [1 2][3 4][5 6][7 8] )
For each of such parts:
a) test on it, while training on the rest, so for example:
train on [3 4 5 6 7 8] and test on [1 2]
b) record the mean score
Repeat the whole process and report the means score

using precomputed kernels with libsvm

I'm currently working on classifying images with different image-descriptors. Since they have their own metrics, I am using precomputed kernels. So given these NxN kernel-matrices (for a total of N images) i want to train and test a SVM. I'm not very experienced using SVMs though.
What confuses me though is how to enter the input for training. Using a subset of the kernel MxM (M being the number of training images), trains the SVM with M features. However, if I understood it correctly this limits me to use test-data with similar amounts of features. Trying to use sub-kernel of size MxN, causes infinite loops during training, consequently, using more features when testing gives poor results.
This results in using equal sized training and test-sets giving reasonable results. But if i only would want to classify, say one image, or train with a given amount of images for each class and test with the rest, this doesn't work at all.
How can i remove the dependency between number of training images and features, so i can test with any number of images?
I'm using libsvm for MATLAB, the kernels are distance-matrices ranging between [0,1].
You seem to already have figured out the problem... According to the README file included in the MATLAB package:
To use precomputed kernel, you must include sample serial number as
the first column of the training and testing data.
Let me illustrate with an example:
%# read dataset
[dataClass, data] = libsvmread('./heart_scale');
%# split into train/test datasets
trainData = data(1:150,:);
testData = data(151:270,:);
trainClass = dataClass(1:150,:);
testClass = dataClass(151:270,:);
numTrain = size(trainData,1);
numTest = size(testData,1);
%# radial basis function: exp(-gamma*|u-v|^2)
sigma = 2e-3;
rbfKernel = #(X,Y) exp(-sigma .* pdist2(X,Y,'euclidean').^2);
%# compute kernel matrices between every pairs of (train,train) and
%# (test,train) instances and include sample serial number as first column
K = [ (1:numTrain)' , rbfKernel(trainData,trainData) ];
KK = [ (1:numTest)' , rbfKernel(testData,trainData) ];
%# train and test
model = svmtrain(trainClass, K, '-t 4');
[predClass, acc, decVals] = svmpredict(testClass, KK, model);
%# confusion matrix
C = confusionmat(testClass,predClass)
The output:
*
optimization finished, #iter = 70
nu = 0.933333
obj = -117.027620, rho = 0.183062
nSV = 140, nBSV = 140
Total nSV = 140
Accuracy = 85.8333% (103/120) (classification)
C =
65 5
12 38