【问题标题】:How to implement k-fold cross validation with multi-class SVM如何使用多类 SVM 实现 k 折交叉验证
【发布时间】:2016-01-16 14:59:59
【问题描述】:

我正在研究年龄预测主题,我可以通过训练每个具有正数的类而不是所有其他类来实现具有 11 个类的多类 SVM,如 here 和 here 所示。 但问题出在for循环中,如下图,训练数据需要11个循环:

for k = 1:numClasses
    %Vectorized statement that binarizes Group
    %where 1 is the current class and 0 is all other classes
    G_x_All = (train_label == u(k));
    G_x_All = double (G_x_All);
    SVMStruct{k} = svmtrain(Data_Set, G_x_All);
end

那么,数据分类也需要对每张图像进行 11 次循环:

for j = 1:total_images
  for k = 1:numClasses
      if(svmclassify(SVMStruct{k}, Test_Img(j,:)));
          break;
      end
  end
  Age (j) = u(k); % Put the number of correct class in Age vector
end

我的菜鸟问题是,在所有这些循环之后,我怎样才能制作k-fold cross validation?

编辑 ::>

这是根据zelanix先生的建议对代码进行的最后一次更新,但我得到了不好的结果。你能帮我提高它的性能吗?

u = unique(train_label);
numClasses = length (u);
N = size (Data_Set,1)
A = 10;
indices = crossvalind('Kfold', N, A);
cp = classperf (train_label);

for i = 1:A
    Test = (indices == i); 
    Train = ~Test;         
    SVMStruct = cell(numClasses, 1); % Clear data structure.

    % Build models
  for k = 1:numClasses
    %Vectorized statement that binarizes Group
    %where 1 is the current class and 0 is all other classes
    G_x_All = (train_label == u(k));
    G_x_All = double (G_x_All);
    SVMStruct{k} = svmtrain(Data_Set (Train,:), G_x_All(Train,:));
  end

  Age = NaN(size(Data_Set, 1), 1);

  % Classify test cases
  for k = 1:numClasses
      if(svmclassify(SVMStruct{k}, Data_Set(Test,:)));
          break;
      end
  end
   Age = u(k);
   if Age == 1
       disp ('Under 10 years old');
   elseif Age == 10
       disp ('Between 10 and 20 years old');
   elseif Age == 20
       disp ('Between 20 and 30 years old');
   elseif Age == 30
       disp ('Between 30 and 40 years old');
   elseif Age == 40
       disp ('Between 40 and 50 years old');
   elseif Age == 50
       disp ('Between 50 and 60 years old');
   elseif Age == 60
       disp ('Upper 60 years old');
   else
       disp ('Unknown');
   end

classperf(cp, Age, Test);
    disp (i)
end
cp.CorrectRate

请注意,我将标签数量从 11 个减少到 7 个。

【问题讨论】:

    标签: matlab svm cross-validation


    【解决方案1】:

    您需要的一般结构如下(假设您的数据在变量your_data 中,大小为N x M 其中N 是样本数,M 是特征数并且您的类标签位于变量 your_classes 中,大小为 M x 1):

    K = 10; % The number of folds
    N = size(your_data, 1); % The number of data samples to train / test
    idx = crossvalind('Kfold', N, K)
    
    % your_classes should contain the class between 1 and numClasses.
    cp = classperf(your_classes);
    
    for i = 1:K
        Data_Set = your_data(idx ~= i, :); % The data to train on, 90% of the total.
        train_label = your_classes(idx ~= i, :); % The class labels of your training data.
        Test_Img = your_data(idx == i, :); % The data to test on, 10% of the total.
        test_label = your_classes(idx == i, :); % The class labels of your test data.
    
        SVMStruct = cell(numClasses, 1); % Clear data structure.
    
        % Your training routine, copied verbatim
        for k = 1:numClasses
            %Vectorized statement that binarizes Group
            %where 1 is the current class and 0 is all other classes
            G_x_All = (train_label == u(k));
            G_x_All = double (G_x_All);
            SVMStruct{k} = svmtrain(Data_Set, G_x_All);
        end
    
        Age = NaN(size(Test_Img, 1), 1);
    
        % Your test routine, copied (almost) verbatim
        for j = 1:size(Test_Img, 1)
          for k = 1:numClasses
              if(svmclassify(SVMStruct{k}, Test_Img(j,:)));
                  break;
              end
          end
          Age(j) = u(k); % Put the number of correct class in Age vector
        end
    
        cp = classperf(cp, Age, idx == i);
    end
    
    cp.CorrectRate
    

    这是未经测试的,我不确定您的分类实际上是如何工作的。您似乎打破了第一个匹配的分类,这可能不是正确的分类,或者确实是最有可能的分类。您还需要一些方法来记录它并将其与test_label 中的真实类标签相匹配。我建议您查看classperf 函数,但这是一个单独的问题。

    另请注意,matlab 在 fitcecoc 函数中内置了多类 SVM 分类,这可能更适合您的需求。

    编辑您更新的代码(如上所述)的问题在于您的分类方法。您循环并测试样本是否属于每个类别并在第一个匹配的类别上中断。这不太可能是最有可能的分类,所以我对你得到糟糕的结果并不感到惊讶。

    您的样本可能与第一个模型匹配,但只有很小的差距,但它并没有找到与之匹配的模型。超过前几个分类的可能性很小,如果到最后没有被任何分类器匹配,你会怎么做?

    使用 SVM 的多类分类通常是通过选择样本被分类的可能性最高的类来实现的(在所有测试为阳性的类中,选择离决策边界最远的一个 - fitcecoc 在内部执行此操作)。但这无法手动使用 svmclassify,因为它无法让您访问这些详细信息。

    fitcecoc 仍然无法让您访问您可能需要的所有值,因此如果您真的想手动执行此操作,那么我建议您查看libsvm,否则使用fitcecoc。

    正如 cmets 中提到的,svmtrain 和 svmclassify 现在无论如何都已弃用 - libsvm 还提供了更大的可能性来进行调整和使用内置 MATLAB 实现无法实现的性能。

    顺便说一句,多类逻辑回归更容易理解,也可以取得很好的结果。

    【讨论】:

    • 非常感谢@zelanix 的帮助。我已经编辑了代码以在break 之后显示下一步。顺便说一句,在实现您的代码后,我有一些问题:我应该把train_label 和test_label 放在哪里?看起来无法使用!另外,由于使用K-fold,我想不再需要Test_Img,因为它会从Data_Set随机获取测试图像,对吗?
    • 我已经稍微更新了答案,包括使用classperf 记录性能。我认为classperf 要求类标签为1:numClasses,而不是使用u(k) 进行转换。 train_label 是必需的,并且在您的训练例程中使用,但您是对的,test_label 在这样实施时不使用,但在其他实施选择中可能是必需的。
    • 我已经更新了zelanix先生的代码,你能检查一下吗? @zelanix
    • 更准确地说:svmtrain 和 svmclassify 将在未来被弃用,新包由 templateSVM、fitcecoc 和 predict 组成。
    • @AbuQusay,我已根据您更新的代码更新了我的答案。
    猜你喜欢
    • 2016-12-15
    • 2015-03-31
    • 1970-01-01
    • 2016-01-15
    • 2017-11-24
    • 1970-01-01
    • 2017-02-06
    • 2020-08-29
    • 2017-09-22
    相关资源
    最近更新 更多