我在Matlab中使用RBF内核训练SVM时遇到了一个奇怪的问题。问题在于,在进行网格搜索时,使用10倍交叉验证,对于C和Sigma值,我总是得到大约.50的AUC值(在.48和.54之间变化) - 我得到了这个来自:[X,Y,T,AUC] = perfcurve(dSet1Label(test),label, 1);
其中dSet1Label(test)
是实际的测试集标签,label
是预测标签。分类器只预测多数类,它占数据的90%以上。
进一步调查时,在查看得分时(从[label,score] = predict(svmStruct, dSet1(test,:));
获得,其中svmStruct
是在9/10数据上训练的模型,而dSet1(test,:)
是剩余的1/10)他们都是一样的:
0.8323 -0.8323
0.8323 -0.8323
0.8323 -0.8323
0.8323 -0.8323
0.8323 -0.8323
0.8323 -0.8323
0.8323 -0.8323
0.8323 -0.8323
0.8323 -0.8323
. .
. .
. .
0.8323 -0.8323
该数据由443个特征和6,453个实例组成,其中542个属于正类。根据标准SVM协议,这些功能已扩展到[0,1]
的范围。这些类由{-1,1}
表示。
我的代码如下:
load('datafile.m');
boxVals = [1,2,5,10,20,50,100,200,500,1000];
rbfVals = [.0001,.01,.1,1,2,3,5,10,20];
[m,n] = size(dataset1);
[c,v] = size(boxVals);
[e,r] = size(rbfVals);
auc_holder = [];
accuracy_holder = [];
for i = 1:v
curBox = boxVals(i)
for j = 1:r
curRBF = rbfVals(j)
valInd = crossvalind('Kfold', m, 10);
temp_auc = [];
temp_acc = [];
cp = classperf(dSet1Label);
for k = 1:10
test = (valInd==k); train = ~test;
svmStruct = fitcsvm(dSet1(train,:), dSet1Label(train), 'KernelFunction', 'rbf', 'BoxConstraint', curBox, 'KernelScale', curRBF);
[label,score] = predict(svmStruct, dSet1(test,:));
accuracy = sum(dSet1Label(test) == label)/numel(dSet1Label(test));
[X,Y,T,AUC] = perfcurve(dSet1Label(test),label, 1);
temp_auc = [temp_auc AUC];
temp_acc = [temp_acc accuracy];
end
avg_auc = mean(temp_auc);
avg_acc = mean(temp_acc);
auc_holder = [auc_holder avg_auc];
accuracy_holder = [accuracy_holder avg_acc];
end
end
谢谢!
*编辑1:看来,无论我将框约束设置为什么,所有数据点都被视为支持向量。
答案 0 :(得分:1)
除非你有一些实现错误(用合成的,分离良好的数据测试你的代码),否则问题可能在于类不平衡。这可以通过调整错误分类成本(See this discussion in CV)来解决。我使用cost
的{{1}}参数将少数类的错误分类成本提高到大多数类的9倍,并查看问题是否仍然存在。要考虑的另一个问题是类分层(请参阅crossvalind文档 - 您必须定义fitcsvm
参数,以便每个折叠都具有类似的类别比例。)