我正在尝试使用LIBSVM实现一个vs rest多类分类。
此链接很有用http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/ovr_multiclass/ 但我在函数'ovrpredict()'中得到一个错误。
功能如下:
function [pred, ac, decv] = ovrpredict(y, x, model)
labelSet = model.labelSet;
labelSetSize = length(labelSet);
models = model.models;
decv= zeros(size(y, 1), labelSetSize);
for i=1:labelSetSize
[l,a,d] = svmpredict(double(y == labelSet(i)), x, models{i});
decv(:, i) = d * (2 * models{i}.Label(1) - 1); % ERROR IN THIS LINE
end
[tmp,pred] = max(decv, [], 2);
pred = labelSet(pred);
ac = sum(y==pred) / size(x, 1);
我得到的错误消息是Reference to non-existent field 'Label'
。
任何建议都会非常有用。
用于调用函数的代码:\
[trainY trainX]=libsvmread('libfacecombine.train');
[testY testX]=libsvmread('libfacetest.train');
model=ovrtrain(trainY,trainX,'-c 8 -g 4');
[~,accuracy,~]=ovrpredict(testY,testX,model);
训练和测试数据即“libfacecombine.train”和“libfacetest.train”是从.csv文件中编写的:
f1=createdabase(f); % where createdatabase is a function to read various images from a folder and arrange into 1D array
[sig1 mn1]=pcam(f1); % where pcam is a function to find 'pca'(sig1) and 'mean'(mn1) of the data
%labelling is done this way:
%Positive class
label=[];
for i=1:length(sig1)
for j=1:1
label(i,j)=+1;
end
end
csvwrite('face1.csv',[label sig1]);
%Negative class
label1=[];
for i=1:length(sig2) % sig2 obtained in same way as sig1
for j=1:1
label1(i,j)=-1;
end
end
csvwrite('face2.csv',[label sig2]);
使用“追加”模式,这两个文件将被连接并转换为.train文件。 测试数据也是如此。
我有5节课。标签如下: 等级1:+1包含来自面部1的4个图像的特征,-1包含来自4个不是面部1的图像(面部2,3,4和5)的特征。第2类:+2包含面部2的4个图像的特征,-2包含4个非面部2的图像(面部1,3,4和5)的特征....类别5:+5包含4个图像的特征面5和-5包含来自4个非面5(面1,2,3和4)的图像的特征。所有这些功能以及标签都按照上面给出的顺序写入.csv文件,然后转换为.train格式。因此我获得了培训文件。
对于测试图像,我拍摄一张脸1的图像并给出其真实标签,即+1,并写入.csv文件,然后转换为.train。因此我获得了测试文件。当我运行程序时,我获得了以下结果:
Accuracy=92%(12/13)classification;
Accuracy=61%(8/13)classification;
Accuracy=100%(13/13)classification;
Accuracy=100%(13/13)classification;
Accuracy=100%(13/13)classification;
Accuracy=100%(13/13)classification;
为什么我只有5个班级才能获得6个准确度值?
答案 0 :(得分:2)
通过互联网找到类似这样的解决方案很棘手,但让我们试一试。这篇文章由问题而不是答案组成。但是,我相信如果你回答所有这些问题,你会发现你的错误而没有进一步的帮助 - 或者至少是那里的90%。
所有这些步骤都适用于调试任何类型的MATLAB程序。
工作区中闲置的旧版本变量可能会使调试变得困难。变量名中的拼写错误可能导致意外使用旧版本。在调试开始时使用clear
清除工作区。
我编译了libsvm,添加了ovr_multiclass
个插件,我可以成功运行我编写的以下示例脚本:
clear
% random train and test data
trainX = rand(10, 4);
trainY = randi(4, 10, 1);
testX = rand(10, 4);
testY = randi(4, 10, 1);
model=ovrtrain(trainY,trainX,'-c 8 -g 4');
[~,accuracy,~]=ovrpredict(testY,testX,model);
你可以运行它,或者你得到和以前一样的错误? 这种 最小工作示例 对于调试非常有用。 使用用户生成的小数据可确保错误不会来自意外来源,并有助于缩小原因。
models
单元格数组您声明错误发生在此:
decv(:, i) = d * (2 * models{i}.Label(1) - 1); % ERROR IN THIS LINE
该行的关键部分是models{i}.Label(1)
。这是一个单元格数组models
,并提取i
项。这个i
项应该是一个结构,名为Label
。 Label
应该是一个非空数组,从中可以提取第一个元素。 models
单元格数组是结构model
中的一个字段,它作为第三个参数传递给ovrpredict
。
运行上面非常简单的测试脚本后,我在MATLAB命令窗口中运行以下诊断程序:
>> models = model.models
models =
[1x1 struct]
[1x1 struct]
[1x1 struct]
[1x1 struct]
>> models{1}
ans =
Parameters: [5x1 double]
nr_class: 2
totalSV: 6
rho: -1.2122
Label: [2x1 double]
sv_indices: [6x1 double]
ProbA: []
ProbB: []
nSV: [2x1 double]
sv_coef: [6x1 double]
SVs: [6x4 double]
>> models{1}.Label
ans =
0
1
如果你这样做,你会得到相同的结果吗?如果没有,请在编辑问题时将输出发布到这些命令。
如果模型看起来没问题,但仍然出现错误,请在命令窗口中键入错误调试器:
dbstop if error
当MATLAB在函数中遇到错误时,它将暂停并允许您检查所有变量。
再次运行您的程序(或者我的程序,如果您收到我发布的最小工作示例的错误)。发生错误时,程序应暂停。您的命令提示符应从>>
更改为K>>
。
运行上述步骤以示例model
cells数组。然后尝试复制,粘贴和运行在命令窗口中给出错误的代码行。尝试运行它的一小部分,例如models{i}.Label(1)
然后2 * models{i}.Label(1) - 1
。
键入dbquit
以退出调试器,并dbclear if error
关闭错误时自动调试。
(另请参阅下面有关错误消息的问题 - 请确保错误实际发生在您认为的位置!)
您使用的是哪个版本的MATLAB?例如R2013a
如果在MATLAB命令行中输入which ovrpredict
,您是否看到了预期文件的路径? (即保存在计算机上的正确路径为ovrpredict.m)
您的ovrpredict.m
文件(由which ovrpredict
指出)是否包含您在问题中粘贴的内容?你得到的错误表明他们可能是一个微小的差异,例如额外的空间。
答案 1 :(得分:1)
虽然我不确定如何解决这个问题,但我的意见如下:
在ovrtrain
中,创建了一个模型,其唯一的附加字段为labelSet
。
稍后在overpredict
代码中,代码会尝试读出label
。
所以,我看到三个选项:
编辑:这部分可能不是解决方案,正如评论中所提到的那样
我没有足够的信息知道哪些适用,但是如果 您可以尝试替换
Label
的代码未提供示例 到处都是labelSet
。
请注意,如果它是第1点或第3点,则此代码应始终提供错误,并且永远不会正常运行。