我有6个一维数据样本作为示例,我试图在这些数据上训练vlfeat的SVM:
data: [188.00000000; 168.00000000; 191.00000000; 150.00000000; 154.00000000; 124.00000000]
前三个样本为正样本,后三个样本为负样本。
我得到的权重(包括偏置)是:
w: -0.6220197226 -0.0002974511
问题是所有样本都被预测为负样本,但它们显然是线性可分的。
在学习过程中,我使用了VlSvmSolverSgd类型的求解器和lambda值0.01。
如果有影响的话,我使用的是C API。
最小工作示例:
void vlfeat_svm_test(){ vl_size const numData = 6 ; vl_size const dimension = 1 ; //double x[dimension * numData] = {188.0,168.0,191.0,150.0, 154.0, 124.0}; double x[dimension * numData] = {188.0/255,168.0/255,191.0/255,150.0/255, 154.0/255, 124.0/255}; double y[numData] = {1, 1, 1, -1, -1, -1} ; double lambda = 0.01; VlSvm *svm = vl_svm_new(VlSvmSolverSgd, x, dimension, numData, y, lambda); vl_svm_train(svm); double const * w= vl_svm_get_model(svm); double bias= vl_svm_get_bias(svm); for(int k=0;k<numData;++k) { double res= 0.0; for(int i=0;i<dimension;++i) { res+= x[k*dimension+i]*w[i]; } int pred= ((res+bias)>0)?1:-1; cout<< pred <<endl; } cout << "w: "; for(int i=0;i<dimension;++i) cout<< w[i] <<" "; cout<< bias <<endl; vl_svm_delete(svm);}
更新:
我还尝试通过将输入数据除以255来缩放,但这没有效果。
更新2:
使用极低的lambda值0.000001似乎解决了这个问题。
回答:
这是因为VLFeat中的SVM求解器并不直接估计模型和偏置,而是使用了一种变通方法,即向数据中添加一个常数分量(如http://www.vlfeat.org/api/svm-fundamentals.html中提到的),并将相应的模型权重作为偏置返回。
因此,偏置项是正则化器的一部分,具有较高偏置的模型在能量方面会被“惩罚”。这种效果在你的情况下尤为明显,因为你的数据维度极低 🙂 因此,你需要选择一个较小的正则化参数LAMBDA值,以降低正则化器的重要性。