libsvm matlab 中的 2 个错误“模型不支持概率估计和下标分配维度不匹配”

Posted

技术标签:

【中文标题】libsvm matlab 中的 2 个错误“模型不支持概率估计和下标分配维度不匹配”【英文标题】:2 errors in libsvm matlab "Model does not support probabiliy estimates and Subscripted assignment dimension mismatch" 【发布时间】:2016-08-10 13:33:50 【问题描述】:

我想使用库 LIBSVM 对包含 5 个测试图像的列表进行分类,并采用“一对一”策略,以获得每个类的概率。使用的代码如下:

load('D:\xapp.mat');
load('D:\xtest.mat');
load('D:\yapp.mat');%% matrix contains true class of images yapp=[641;645;1001;1010;1100]
load('D:\ytest.mat');%% matrix contains unlabeled class of test set  ytest=[1;2;3;4;5]
numLabels=max(yapp);
numTest=size(ytest,1);
%# train one-against-all models
model = cell(numLabels,1);
for k=1:numLabels
   modelk = svmtrain(double(yapp==k),xapp, ['-c 1000 -g 10 -b 1 ']);
end
%# get probability estimates of test instances using each model
prob = zeros(numTest,numLabels);
for k=1:numLabels
   [~,~,p] = svmpredict(double(ytest==k), xtest, modelk, '-b 1');
   prob(:,k) = p(:,modelk.Label==1);    %# probability of class==k
end
%# predict the class with the highest probability
[~,pred] = max(prob,[],2);
acc = sum(pred == ytest) ./ numel(ytest)    %# accuracy

我收到此错误:

模型不支持概率估计 下标分配维度不匹配。 补偿中的错误(第 98 行) prob(:,k) = p(:,modelk.Label==1); 1234562的%#概率==k

请帮我解决这个错误并提前感谢

【问题讨论】:

我认为错误在numLabels=max(yapp); 中。在这一行中,您基本上说有 1100 个标签,而这是不正确的,因为您有 5 个标签。如果yapp=[641;645;1001;1010;1100],那么类的数量是length(yapp),而不是max(yapp) 感谢您的回复,澄清:xapp 代表训练集,xtest 包含测试集。我知道问题来自这一行 numLabels=max(yapp);但是当我用长度(yapp)替换最大值时,我得到了同样的错误。感谢您的任何建议 你也应该注意double(yapp==k)这一行。对于从 1 到 numLabelsk 和在 [641;645;1001;1010;1100] 范围内的 yapp,永远不会验证相等性。我不认为这会消除错误,但你会得到所有类的全零标签,这永远不会导致正确的结果 是的,这正是问题所在。这个实现是针对所有在 libsvm 中的 svm。请对解决此错误的任何其他实现有任何想法 好吧,既然yappytest 都包含标签,它们应该包含相同的值范围(即从1 到5)。如果您事先不知道测试集的标签,那不是一个真正的测试集:这些只是未分类的模式,SVM 将返回它们的估计标签。如果ytest 的内容只是从 1 到 5 的虚拟数字,那么您不能将其用于准确性评估和/或性能评估(就像您在 真实 测试集中所做的那样)。您必须从svmpredict() 收集第一个输出,这些将是估计的标签。 【参考方案1】:

您要做的是使用代码 sn-p 来评估 SVM 分类器的性能,而您的目标是正确估计测试集的标签。

我假设您的五个标签是[641;645;1001;1010;1100](如yapp)。您要做的第一件事是删除ytest,因为您不知道测试集的任何标签。用一些虚拟值填充ytest 是没有意义的:SVM 将返回我们预测的标签。

第一个错误,正如 cmets 中已经指出的那样,在

numLabels=max(yapp);

您必须将max() 更改为length() 才能收集班级数量。

训练阶段几乎是正确的。 鉴于k 从 1 变为 5 而yapp 具有上述范围,您应该考虑将double(yapp==k) 更改为double(yapp==yapp(k)):通过这种方式,我们将yapp 中的第k 个值标记为正。鉴于k 从 1 变为 5,那么 yapp(k) 将从 641 变为 1100。

现在是预测阶段。svmpredict() 的第一个输入应该是测试标签,但现在我们不知道它们,所以我们可以用零向量填充它(测试集中有多少个模式就有多少个零)。这是因为如果测试标签已知,svmpredict() 也会自动返回准确度,但事实并非如此。所以你必须把第二个for循环改成

for k=1:numLabels
   [~,~,p] = svmpredict(zeros(size(xtest,1),1), xtest, modelk, '-b 1');
   prob(:,k) = p(:,modelk.Label==1);    %# probability of class==k
end

最后用

预测标签
[~,pred] = max(prob,[],2);

pred 包含预测标签。

注意 1:但是,在这种方法中,您无法测量准确度和/或其他参数,因为我们所说的测试集实际上并不是测试集。测试集是一个有标签的集合,我们假装不知道它的标签,以便让 SVM 预测它们,然后将预测的标签与实际标签匹配以测量其准确性。

注意 2:由于第二个 for 循环,pred 中的预测标签很可能具有 1 到 5 范围内的值。但是,由于您的标签具有不同的值,因此您可以在考虑 1 是 641、2 是 645、3 是 1001、4 是 1010、5 是 1100 的情况下进行映射。

【讨论】:

我试过这个,但我得到一个矩阵 pred 作为同胞 pred=[5;5;5;5;5] 但实际上类标签在 [641;645;1001;1010; 1100]。究竟是什么问题?

以上是关于libsvm matlab 中的 2 个错误“模型不支持概率估计和下标分配维度不匹配”的主要内容,如果未能解决你的问题,请参考以下文章

Libsvm 模型中的支持向量是如何排列的?

libsvm 交叉验证与 matlab 中的预计算内核

在 Matlab 的 LibSVM 中指定权重

MATLAB/Octave 中的 LIBSVM - libsvmread 的输出是啥?

Matlab 中的 Libsvm 回归预测测试集实例的相同值

Libsvm 分类 MATLAB