我使用SURF和BOW训练了SVM,现在无论我预测什么图像,它总是返回1,即使是负样本图像也返回1作为输出
以下是SVM的参数设置:
CvSVMParams Params;Params.svm_type=CvSVM::C_SVC;Params.kernel_type=CvSVM::LINEAR;Params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);Params.gamma=3;CvSVM svm;svm.train(training_mat,labels,cv::Mat(),cv::Mat(),Params);
这是我的预测代码:
predict_img = cvLoadImage("ss.jpg",0);detector.detect(predict_img, keypoint2);RetainBestKeypoints(keypoint2, 20);dextract.compute( predict_img, keypoint2, descriptors_2);Mat my_img_3 = descriptors_2.reshape(1,1);float response = svm.predict(my_img_3);cout<<response;
这是初始化代码:
BOWImgDescriptorExtractor dextract(extractor,matcher);SurfFeatureDetector detector(500);
回答:
你应该检查是否设置了足够大的C
值(在你的代码中没有看到,所以应该按照OpenCV文档设置为1000),以强制生成一个合理的模型。你应该尝试许多不同的值,对于许多实际问题,甚至需要使用10^10
量级的C
值。如果C
值太小,SVM将简单地寻找一个具有小范数的超平面,而不真正关注正确的分类。在OpenCV实现中可以通过Cvalue
参数访问这个值。
Params.gamma=3;
尽管这不会导致错误,但你不需要设置gamma
值,因为在线性核中不使用它,它仅在RBF核中需要。
你还应该确保训练的正样本和负样本数量相似(或者使用某种类权重技术),因为这也可能导致“平凡”的模型。