2012-01-21 13 views
12

Wiem, że LIBSVM pozwala tylko na klasyfikację jeden vs w przypadku wielopoziomowej SVM. Chciałbym jednak nieco go zmodyfikować, aby wykonać klasyfikację jeden-na-wszystkie. Próbowałem wykonać jeden przeciwko wszystkim poniżej. Czy to jest właściwe podejście?SVM wielopoziomowy (jeden w porównaniu do wszystkich)

Kod:

TrainLabel;TrainVec;TestVec;TestLaBel; 
u=unique(TrainLabel); 
N=length(u); 
if(N>2) 
    itr=1; 
    classes=0; 
    while((classes~=1)&&(itr<=length(u))) 
     c1=(TrainLabel==u(itr)); 
     newClass=c1; 
     model = svmtrain(TrainLabel, TrainVec, '-c 1 -g 0.00154'); 
     [predict_label, accuracy, dec_values] = svmpredict(TestLabel, TestVec, model); 
     itr=itr+1; 
    end 
itr=itr-1; 
end 

mógłbym zrobić kilka błędów. Chciałbym usłyszeć jakąś opinię. Dzięki.

Druga część: Jako grapeot powiedział: Muszę zrobić Sumowanie (lub głosowanie jako uproszczone rozwiązanie), aby wymyślić ostateczną odpowiedź. Nie jestem pewien, jak to zrobić. Potrzebuję trochę pomocy; Widziałem plik Pythona, ale nadal nie jestem pewien. Potrzebuję pomocy.

+0

Jakie jest dokładnie pytanie? Pytasz, jak wykonać klasyfikację jeden do wszystkich z LibSVM? Czy program wyprowadza oczekiwany rezultat? BTW, parametry LibSVM powinny wynosić '-c 1 -g 0,00153'' (brakowało ci pojedynczej oferty końcowej). – grapeot

+0

Mam edytować pytanie ... – lakesh

+1

@lakesh: Wysłałem odpowiedź na podobne pytanie, może się okazać przydatne: http://stackoverflow.com/a/9049808/97160 – Amro

Odpowiedz

10
%# Fisher Iris dataset 
load fisheriris 
[~,~,labels] = unique(species); %# labels: 1/2/3 
data = zscore(meas);    %# scale features 
numInst = size(data,1); 
numLabels = max(labels); 

%# split training/testing 
idx = randperm(numInst); 
numTrain = 100; numTest = numInst - numTrain; 
trainData = data(idx(1:numTrain),:); testData = data(idx(numTrain+1:end),:); 
trainLabel = labels(idx(1:numTrain)); testLabel = labels(idx(numTrain+1:end)); 
%# train one-against-all models 
model = cell(numLabels,1); 
for k=1:numLabels 
    model{k} = svmtrain(double(trainLabel==k), trainData, '-c 1 -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 
4

Z kodu widzę, że próbujesz najpierw przekształcić etykiety w "jakąś klasę", a nie "w tej klasie", a następnie wzywać LibSVM do przeprowadzania szkoleń i testowania. Kilka pytań i sugestii:

  1. Dlaczego korzystasz z oryginalnego szkolenia TrainingLabel? Moim zdaniem, czy powinno to być model = svmtrain(newClass, TrainVec, '-c 1 -g 0.00154');?
  2. Przy zmodyfikowanym mechanizmie treningu należy również zmodyfikować część przewidywania, np. Użyć sumowania, aby określić końcową etykietę. Zastosowanie przełącznika LibSVM w celu włączenia wyjścia prawdopodobieństwa również poprawi dokładność.
+0

dzięki dużo ... btw, do u wiedzieć, jak zrobić jeden vs jeden przy użyciu LIBSVM? nie jestem pewien jak to zrobić ... – lakesh

+1

Po prostu umieszczenie etykiet innych niż 0 <=> 1 lub -1 <=> 1 jako danych wejściowych jest w porządku. LibSVM rozpozna go i spróbuje dokonać klasyfikacji wielopoziomowej. – grapeot

+0

to jest jeden kontra jeden? – lakesh

1

Zamiast szacunków prawdopodobieństwa, można również użyć wartości decyzyjne następująco

[~,~,d] = svmpredict(double(testLabel==k), testData, model{k}); 
prob(:,k) = d * (2 * model{i}.Label(1) - 1); 

aby osiągnąć ten sam cel.

Powiązane problemy