C++ 使用cv::ml::StatModel::calcError以及在选定特征子集上训练的模型时出现Opencv错误
使用Opencv 3.2.0,我尝试在SVM模型上计算训练和测试错误,该模型是使用cv::ml::TrainData::create()中的varIdx向量创建的,使用特征子集创建的。下面是C++代码的相关部分。C++ 使用cv::ml::StatModel::calcError以及在选定特征子集上训练的模型时出现Opencv错误,c++,opencv,C++,Opencv,使用Opencv 3.2.0,我尝试在SVM模型上计算训练和测试错误,该模型是使用cv::ml::TrainData::create()中的varIdx向量创建的,使用特征子集创建的。下面是C++代码的相关部分。 using namespace cv; using namespace cv::ml; using namespace std; // Code to read samples and responses from external data file not shown...
using namespace cv;
using namespace cv::ml;
using namespace std;
// Code to read samples and responses from external data file not shown...
// Copy vector to Mat
Mat matSamples(samples.size(), samples.at(0).size(), CV_32F);
for(int i = 0; i < matSamples.rows; i++) {
for(int j = 0; j < matSamples.cols; j++) {
matSamples.at<float>(i, j) = samples.at(i).at(j);
}
}
// Copy vector to Mat
Mat matResponses(responses.size(), 1, CV_32SC1);
for(int i = 0; i < matResponses.rows; i++) {
matResponses.at<int>(i) = responses.at(i);
}
// Create Mat to specify training variables (features)
Mat matVarIdx(1, 7, CV_32SC1);
matVarIdx = (Mat_<int>(1, 7) << 0, 15, 26, 27, 28, 29, 31);
cout << "Using features specified by " << matVarIdx << endl;
// Construct training data from samples read from file above
Ptr<TrainData> td = TrainData::create(
matSamples, // Array of samples
ROW_SAMPLE, // Data in rows
matResponses, // Array of responses
matVarIdx, // Use features specified
noArray(), // Use all data points
noArray(), // Do not use samples weights
noArray() // Do not specify inp and out types
);
// Split training and test data
double ratio = 0.90; // 90% of samples will be labled training data
bool shuffle = true; // randomly shuffle test and training data
td->setTrainTestSplitRatio(ratio, shuffle);
int n_train_samples = td->getNTrainSamples();
int n_test_samples = td->getNTestSamples();
cout << "Found " << n_train_samples << " Train Samples, and "
<< n_test_samples << " Test Samples." << endl;
// Output number of features
cout << "Total number of features " << td->getNAllVars() << " and "
<< td->getNVars() << " features used." << endl;
// Set up SVM's parameters
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::RBF);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 1000, FLT_EPSILON));
// Train the SVM with given parameters
svm->train(td);
// Calculate errors.
Mat results;
float train_performance = svm->StatModel::calcError(
td,
false, // use train data
results);
cout << "Incorrectly classified training samples: " << train_performance << "%" << endl;
float test_performance = svm->StatModel::calcError(
td,
true, // use test data
results);
cout << "Incorrectly classified test samples: " << test_performance << "%" << endl;
看起来用于计算错误的预测失败了,因为样本列的数量不等于我打算在创建训练数据时使用varIdx设置的功能的数量
当我使用全部功能时,即在cv:ml::TrainData::create()中设置varIdx=cv::noArray()时,此代码有效
我尝试过使用向量代替varIdx的Mat,也尝试过使用CV_8UC1 Mat代替varIdx,但仍然得到相同的断言错误
非常感谢您的帮助 查看文档,解释了varIdx向量用于识别感兴趣的特征,并用作基于0的索引列表或活动变量掩码
这样,你可以考虑创建一个ValIDX向量编号,大小为0,也可以是1个值。 我认为您的错误是因为varIdx只包含7个值而不是32个值,并且在预测时OpenCV只期望7个值,但得到了32个值。如果不指定感兴趣的变量,则不会发生此错误,因为算法会以相等的权重考虑每个变量
也不要犹豫,看看库的代码。编译器为您提供了错误发生的位置,因此它可以帮助您理解代码失败的原因Using features specified by [0, 15, 26, 27, 28, 29, 31]
Found 267 Train Samples, and 30 Test Samples.
Total number of features 32 and 7 features used.
OpenCV Error: Assertion failed (samples.cols == var_count && samples.type() == CV_32F) in predict, file /home/lindo/dev/opencv/opencv-3.2.0/modules/ml/src/svm.cpp, line 1930
terminate called after throwing an instance of 'cv::Exception'
what(): /home/lindo/dev/opencv/opencv-3.2.0/modules/ml/src/svm.cpp:1930: error: (-215) samples.cols == var_count && samples.type() == CV_32F in function predict
Aborted