Mit Opencv 3.2.0 versuche ich den Trainings- und Testfehler für ein SVM-Modell zu berechnen, das mit einer Untermenge von erstellt wurde Features mit dem varIdx-Vektor in cv :: ml :: TrainData :: create(). Hier ist der relevante Abschnitt des C++ Codes.Opencv-Fehler bei Verwendung von cv :: ml :: StatModel :: calcError mit auf dem ausgewählten Feature-Subset trainierten Modellen
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;
Hier ist die Ausgabe des Programms:
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
Es ist wie die Vorhersagen sieht verwendet die Fehler zu berechnen ist fehlgeschlagen, da die Anzahl der Spalten Probe nicht gleich der Anzahl von Funktionen ist das, was Ich wollte mit varIdx die Trainingsdaten erstellen.
Dieser Code funktioniert, wenn ich die volle Anzahl von Features verwende, d. H. Setze varIdx = cv :: noArray() in cv: ml :: TrainData :: create().
Ich habe versucht, einen Vektor anstelle einer Matte für varIdx sowie eine CV_8UC1 Mat für varIdx zu verwenden, aber immer noch den gleichen Assertionsfehler zu bekommen.
Jede Hilfe sehr geschätzt!