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 到 numLabels
的 k
和在 [641;645;1001;1010;1100]
范围内的 yapp
,永远不会验证相等性。我不认为这会消除错误,但你会得到所有类的全零标签,这永远不会导致正确的结果
是的,这正是问题所在。这个实现是针对所有在 libsvm 中的 svm。请对解决此错误的任何其他实现有任何想法
好吧,既然yapp
和ytest
都包含标签,它们应该包含相同的值范围(即从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 个错误“模型不支持概率估计和下标分配维度不匹配”的主要内容,如果未能解决你的问题,请参考以下文章
MATLAB/Octave 中的 LIBSVM - libsvmread 的输出是啥?