多分类支持向量机(一对多)

11
我知道LIBSVM在多类SVM方面只允许一对一分类。但是,我想稍微调整一下,使其执行一对所有的分类。我已经尝试了下面的一对所有操作。这是正确的方法吗?
代码:
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

我可能犯了一些错误,希望能听到一些反馈。谢谢。

第二部分: 就像grapeot所说的: 我需要进行Sum-pooling(或投票作为简化解决方案)以得出最终答案。我不确定如何做。我需要一些帮助;我看过python文件但仍不太确定。我需要一些帮助。


问题确切是什么?您是在询问如何使用LibSVM执行一对多分类吗?程序输出的结果是否符合您的预期?顺便说一下,LibSVM参数应该是'-c 1 -g 0.00153'(您缺少了结束单引号)。 - grapeot
1
@lakesh:我在类似问题的帖子中发布了一个答案,你可能会发现它有用:https://dev59.com/ZGox5IYBdhLWcg3wr2Po#9049808 - Amro
3个回答

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

从代码中我可以看到你尝试先将标签转换为“某个类”或“不是这个类”,然后调用LibSVM进行训练和测试。以下是一些问题和建议:

  1. 为什么要使用原始的 TrainingLabel 进行训练?我认为应该是 model = svmtrain(newClass,TrainVec,'-c 1 -g 0.00154');
  2. 使用修改后的训练机制,您还需要调整预测部分,例如使用总汇聚来确定最终标签。在LibSVM中使用-b开关以启用概率输出也会提高准确性。

1
只要将标签设置为除了0<=>1或-1<=>1以外的其他值作为输入,LibSVM就可以识别并尝试进行多类分类。 - grapeot
顺便说一下,当我把它改成newClass时,它会给我这个错误:错误:标签向量和实例矩阵必须是双精度,模型文件应该是一个结构体数组。 - lakshmen
1
在网站http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/multilabel/上可以找到基于LibSVM的Python one-against-all的官方实现。 - grapeot
如果您希望直接从LibSVM计算分类准确度,请确保输入给SVMPredict的真实标签是正确的,即它们应该像(TestLabel == itr)而不是TestLabel本身。或者您可以编写自己的实现来计算精度/召回率。 - grapeot
是的,这是有意设计的。请注意,您正在通过一系列二元分类器来解决问题。因此,SVM的输出是二进制的,但您需要进行总汇(或投票作为简化解决方案)以得出最终答案。您可以参考之前提到的Python文件。 :) - grapeot
显示剩余5条评论

1

除了概率估计,您还可以使用以下决策值

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

为了达到相同的目的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接