我一直在尝试使用OpenCV实现ensemble of exemplar SVM。超出它的一般想法是,给定K个训练样本(例如,汽车图像),可以训练K个SVM,其中每个SVM使用一个正样本和K-1个负面训练。在测试时间,整体将激发K次,最高分是最好的预测。
为实现这一点,我正在使用OpenCV SVM实现(在编写时使用当前的GIT master - 3.0)和C ++接口。作为功能,我使用的是HOG,响应大小为7000。因此,每个图像具有7000D特征向量。
我面临的问题是各种SVM无法正常训练。实际上,他们根本不训练!事实上,训练执行速度非常快,每个SVM总是返回1个支持向量,alpha = 1.0。我不确定这是否是由于我有一个正面与多个(> 900)底片,或者它只是我的代码中的一个错误。然而,经过几次看,我无法发现任何明显的错误。
这就是我设置问题的方法(假设我们得到了整个数据集的HOG响应并将它们放在std :: vector> trainingData中)。请注意,EnsambleSVMElement是一个持有SVM的结构以及一堆其他信息。
简而言之:我设置了一个训练矩阵,其中每一行都包含特定样本的HOG响应。然后我开始分别训练每个SVM。对于每次训练迭代,我创建一个标签向量,其中每个条目设置为-1(负样本),除了与我正在训练的当前SVM关联的条目设置为1(因此,如果我正在训练条目100,则只有正面标签才会出现在标签[100]上。
培训代码
int ensambles = trainingData.size();
if(ensambles>1)
{
//get params to normalise the data in [0-1]
std::vector<float> mins(trainingData.size());
std::vector<float> maxes(trainingData.size());
for(int i=0; i<trainingData.size(); ++i)
{
mins[i] = *std::min_element(trainingData[i].begin(), trainingData[i].end());
maxes[i] = *std::max_element(trainingData[i].begin(), trainingData[i].end());
}
float min_val = *std::min_element(mins.begin(), mins.end());
float max_val = *std::min_element(maxes.begin(), maxes.end());
int featurevector_size = trainingData[0].size();
if(featurevector_size>0)
{
//set-up training data. i-th row contains HOG response for sample i
cv::Mat trainingDataMat(ensambles, featurevector_size, CV_32FC1);
for(int i=0; i<trainingDataMat.rows; ++i)
for(int j=0; j<trainingDataMat.cols; ++j)
trainingDataMat.at<float>(i, j) = (trainingData.at(i).at(j)-min_val)/(max_val-min_val); //make sure data are normalised in [0-1] - libSVM constraint
for(int i=0; i<ensambles; ++i)
{
std::vector<int> labels(ensambles, -1);
labels[i] = 1; //one positive only, and is the current sample
cv::Mat labelsMat(ensambles, 1, CV_32SC1, &labels[0]);
cv::Ptr<cv::ml::SVM> this_svm = cv::ml::StatModel::train<SVM>(trainingDataMat, ROW_SAMPLE, labelsMat, svmparams);
ensamble_svm.push_back(EnsambleSVMElement(this_svm));
Mat sv = ensamble_svm[i].svm->getSupportVectors();
std::cout << "SVM_" << i << " has " << ensamble_svm[i].svm->getSupportVectors().rows << " support vectors." << std::endl;
}
}
else
std::cout <<"You passed empty feature vectors!" << std::endl;
}
else
std::cout <<"I need at least 2 SVMs to create an ensamble!" << std::endl;
cout总是打印&#34; SVM_i有1个支持向量&#34;。
为了完整性,这些是我的SVM参数:
cv::ml::SVM::Params params;
params.svmType = cv::ml::SVM::C_SVC;
params.C = 0.1;
params.kernelType = cv::ml::SVM::LINEAR;
params.termCrit = cv::TermCriteria(cv::TermCriteria::MAX_ITER, (int)1e4, 1e-6);
在0.1和1.0之间改变C不会影响结果。也没有为样本设置权重,如here所示。仅供参考,这就是我设置权重的方式(对负数的重大惩罚):
cv::Mat1f class_weights(1,2);
class_weights(0,0) = 0.01;
class_weights(0,1) = 0.99;
params.classWeights = class_weights;
在我的代码或我的问题表达中,显然存在一些错误。谁能发现那个?
谢谢!
答案 0 :(得分:3)
答案 1 :(得分:0)
我认为你这里有一个小错误:第二行,我认为它应该是
*std::max_element(...), not *std::min_element(...)
float min_val = *std::min_element(mins.begin(), mins.end());
float max_val = *std::min_element(maxes.begin(), maxes.end());