openCV c ++: проблемы работы с CvBoost (классификатор Adaboost)

Я создаю приложение для классификации людей в изображениях городских условиях.

Я тренирую классификатор следующим образом:

int main (int argc, char **argv)
{

/* STEP 2. Opening the file */
//1. Declare a structure to keep the data
CvMLData cvml;
//2. Read the file
cvml.read_csv ("directory/train_rand.csv");
//3. Indicate which column is the response
cvml.set_response_idx (0);

/* STEP 3. Splitting the samples */
//1. Select 4000 for the training
CvTrainTestSplit cvtts (4000, true);
//2. Assign the division to the data
cvml.set_train_test_split (&cvtts);

printf ("Training ... ");
/* STEP 4. The training */
//1. Declare the classifier
CvBoost boost;
//2. Train it with 100 features
boost.train (&cvml, CvBoostParams (CvBoost::REAL,100, 0, 1, false, 0),
false);

/* STEP 5. Calculating the testing and training error */
// 1. Declare a couple of vectors to save the predictions of each sample
std::vector<float> train_responses, test_responses;
// 2. Calculate the training error
float fl1 = boost.calc_error (&cvml, CV_TRAIN_ERROR, &train_responses);
// 3. Calculate the test error
float fl2 = boost.calc_error (&cvml, CV_TEST_ERROR, &test_responses);

cout<<"Error train: "<<fl1<<endl;

cout<<"Error test: "<<fl2<<endl;

/* STEP 6. Save your classifier */
// Save the trained classifier
boost.save ("./trained_boost_4000samples-100ftrs.xml", "boost");

return 0;
}

train_rand.csv — это файл, в котором первый столбец является категорией. Остальные столбцы будут особенностями проблемы. Например, я мог бы использовать три функции. Каждый из них представляет среднее значение красного, синего и зеленого цвета на пиксель изображения. Так что мой CSV-файл должен выглядеть следующим образом. Обратите внимание, что в первом столбце я использую символ, поэтому OpenCV распознает его как категорию.

B,124.34,45.4,12.4
B,64.14,45.23,3.23
B,42.32,125.41,23.8
R,224.4,35.34,163.87
R,14.55,12.423,89.67
...

Для моей реальной проблемы я использую 100 функций и 8000 образцов. Я тренирую классификатор с половиной данных и проверяю с остальными.

После обучения я получаю тестовую ошибку около 5% (что очень хорошо только для 100 функций).

Теперь я хочу использовать классификатор в новых данных:

CvBoost boost

boost.load("directory/trained_boost_4000samples-100ftrs.xml");

float x = boost.predict(SampleData,Mat(),Range::all(),false,false);
cout<<x;

Я запускаю этот код на тысячах примеров, и он всегда выдает одно и то же значение, равное 2. Я действительно не понимаю, что я делаю здесь неправильно, но даже если я неправильно обучил классификатору, он не будет классифицировать 100% времени таким же образом, также, тестовая ошибка, которую я вычислил ранее, показывает, что классификатор должен работать нормально.

Меня беспокоит то, что в SampleData должно быть то же количество столбцов, что и в примере, который я использовал для обучения. Дело в том, что данные, используемые для обучения, имеют 100 столбцов + 1 ответ, и если я попытаюсь запустить классификатор только с 100 функциями, он выдаст исключение, говорящее о том, что размеры не совпадают. Если я запускаю классификатор с 101 признаком (что абсолютно произвольно), это работает, но результаты не имеют никакого смысла.

Кто-нибудь может мне с этим помочь? Заранее спасибо!

С уважением

2

Решение

Мне удалось заставить работать adaBoost, адаптировав код из документации SVM. Единственная хитрость заключалась в том, что было достаточно выборочных данных (> = 11).

От блог, из которого скопирован ваш код:

ПРИМЕЧАНИЕ. По очень странной причине реализация OpenCV работает не менее чем с 11 выборками.

// Training data
float labels[11] = { 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0};
Mat labelsMat(11, 1, CV_32FC1, labels);

float trainingData[11][2] = {
{501, 10}, {508, 15},
{255, 10}, {501, 255}, {10, 501}, {10, 501}, {11, 501}, {9, 501}, {10, 502}, {10, 511}, {10, 495} };
Mat trainingDataMat(11, 2, CV_32FC1, trainingData);

// Set up SVM's parameters
CvSVMParams params;
params.svm_type    = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit   = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);

// Train a SVM classifier
CvSVM SVM;
SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

// Train a boost classifier
CvBoost boost;
boost.train(trainingDataMat,
CV_ROW_SAMPLE,
labelsMat);

// Test the classifiers
Mat testSample1 = (Mat_<float>(1,2) << 251, 5);
Mat testSample2 = (Mat_<float>(1,2) << 502, 11);

float svmResponse1 = SVM.predict(testSample1);
float svmResponse2 = SVM.predict(testSample2);

float boostResponse1 = boost.predict(testSample1);
float boostResponse2 = boost.predict(testSample2);

std::cout << "SVM:   " << svmResponse1 << " " << svmResponse2 << std::endl;
std::cout << "BOOST: " << boostResponse1 << " " << boostResponse2 << std::endl;

// Output:
//  > SVM:   -1 1
//  > BOOST: -1 1
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]