2012-01-21 17 views
12

Sé que LIBSVM solo permite una clasificación uno contra uno cuando se trata de SVM multi-clase. Sin embargo, me gustaría modificarlo un poco para realizar una clasificación de uno contra todos. He intentado realizar one-against-all a continuación. ¿Es este el enfoque correcto?Multi-Class SVM (uno contra todos)

El código:

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 

que podría haber hecho algunos errores. Me gustaría escuchar algunos comentarios. Gracias.

Segunda parte: Como dijo: Necesito hacer Sum-pooling (o votar como una solución simplificada) para llegar a la respuesta final. No estoy seguro de cómo hacerlo. Necesito ayuda en eso; Vi el archivo de Python, pero todavía no estoy muy seguro. Necesito algo de ayuda.

+0

¿Cuál es la pregunta exactamente? ¿Estás preguntando cómo realizar una clasificación uno contra todos con LibSVM? ¿El programa genera el resultado esperado? Por cierto, los parámetros de LibSVM deberían ser ''-c 1 -g 0.00153'' (le faltaba la comilla simple final). – grapeot

+0

He editado la pregunta ... – lakesh

+1

@lakesh: He publicado una respuesta a una pregunta similar, puede que encuentre útil: http://stackoverflow.com/a/9049808/97160 – Amro

Respuesta

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

Desde el código que veo, primero intenta convertir las etiquetas en "alguna clase" frente a "no esta clase", y luego invocar a LibSVM para hacer entrenamientos y pruebas. Algunas preguntas y sugerencias:

  1. ¿Por qué está utilizando el original TrainingLabel para entrenar? En mi opinión, ¿debería ser model = svmtrain(newClass, TrainVec, '-c 1 -g 0.00154');?
  2. Con un mecanismo de entrenamiento modificado, también necesita modificar la parte de predicción, como usar la agrupación de totales para determinar la etiqueta final. El uso del interruptor -b en LibSVM para habilitar la salida de probabilidad también mejorará la precisión.
+0

muchas gracias ... btw, u ¿Sabes cómo hacer uno contra uno usando LIBSVM? No estoy seguro de cómo hacerlo ... – lakesh

+1

Simplemente poniendo etiquetas que no sean 0 <=> 1 o -1 <=> 1 como entrada está bien. LibSVM lo reconocerá e intentará hacer una clasificación de clases múltiples. – grapeot

+0

¿entonces eso es uno contra uno? – lakesh

1

En lugar de estimaciones de probabilidad, también se pueden utilizar los valores de decisión de la siguiente manera

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

para lograr el mismo propósito.

Cuestiones relacionadas