Я использую реализацию OpenCV алгоритма Random Forest (то есть RTrees) и сталкиваюсь с небольшой проблемой при настройке параметров.
У меня есть 5 классов и 3 переменные, и я хочу добавить вес к классам, потому что размеры выборок для каждого класса сильно различаются.
Я посмотрел на документацию Вот а также Вот и кажется, что приоры Решением является массив, но когда я пытаюсь дать ему 5 весов (для моих 5 классов), это дает мне следующую ошибку:
Ошибка OpenCV: значение одного из аргументов выходит за пределы диапазона (вес каждого класса должен быть положительным) в CvDTreeTrainData :: set_data, файл /home/sguinard/dev/opencv-2.4.13/modules/ml/src/tree.cpp, строка 644
прекращение вызова после создания экземпляра cv :: Exception
what (): /home/sguinard/dev/opencv-2.4.13/modules/ml/src/tree.cpp:644: error: (-211) Вес каждого класса должен быть положительным в функции CvDTreeTrainData :: set_data
Если я хорошо понимаю, это связано с тем, что приоры массив имеет 5 элементов. И когда я пытаюсь дать ему только 3 элемента (как число переменных), все работает.
Согласно документации, этот массив должен использоваться для добавления веса к классам, но на самом деле кажется, что он используется для добавления веса к переменным …
Итак, кто-нибудь знает, как добавить вес к классам по алгоритму RTrees OpenCV? (Я работаю с OpenCV 2.4.13 в C ++)
Заранее спасибо !
Вот мой код:
cv::Mat RandomForest(cv::Mat train_data, cv::Mat response_data, cv::Mat sample_data, int size, int size_predict, float weights[5])
{
#undef CV_TERMCRIT_ITER
#define CV_TERMCRIT_ITER 10
#define ATTRIBUTES_PER_SAMPLE 3
cv::RandomTrees RFTree;
float priors[] = {1,1,1};CvRTParams RFParams = CvRTParams(25, // max depth
500, // min sample count
0, // regression accuracy: N/A here
false, // compute surrogate split, no missing data
5, // max number of categories (use sub-optimal algorithm for larger numbers)
//priors
weights, // the array of priors (use weights or priors)
true,//false, // calculate variable importance
2, // number of variables randomly selected at node and used to find the best split(s).
100, // max number of trees in the forest
0.01f, // forrest accuracy
CV_TERMCRIT_ITER | CV_TERMCRIT_EPS // termination cirteria
);
cv::Mat varIdx = cv::Mat();
cv::Mat vartype( train_data.cols + 1, 1, CV_8U );
vartype.setTo(cv::Scalar::all(CV_VAR_NUMERICAL));
vartype.at<uchar>(ATTRIBUTES_PER_SAMPLE, 0) = CV_VAR_CATEGORICAL;
cv::Mat sampleIdx = cv::Mat();
cv::Mat missingdatamask = cv::Mat();
for (int i=0; i!=train_data.rows; ++i)
{
for (int j=0; j!=train_data.cols; ++j)
{
if(train_data.at<float>(i,j)<0
|| train_data.at<float>(i,j)>10000
|| !float(train_data.at<float>(i,j)))
{train_data.at<float>(i,j)=0;}
}
}
// Training
std::cout << "Training ....." << std::flush;
bool train = RFTree.train(train_data,
CV_ROW_SAMPLE,//tflag,
response_data,//responses,
varIdx,
sampleIdx,
vartype,
missingdatamask,
RFParams);
if (train){std::cout << " Done" << std::endl;}
else{std::cout << " Failed" << std::endl;return cv::Mat();}
std::cout << "Variable Importance : " << std::endl;
cv::Mat VI = RFTree.getVarImportance();
for (int i=0; i!=VI.cols; ++i){std::cout << VI.at<float>(i) << " - " << std::flush;}
std::cout << std::endl;
std::cout << "Predicting ....." << std::flush;
cv::Mat predict(1,sample_data.rows,CV_32F);
float max = 0;
for (int i=0; i!=sample_data.rows; ++i)
{
predict.at<float>(i) = RFTree.predict(sample_data.row(i));
if (predict.at<float>(i)>max){max=predict.at<float>(i);/*std::cout << predict.at<float>(i) << "-"<< std::flush;*/}
}
// Personnal test due to an error I got (everyone sent to 0)
if (max==0){std::cout << " Failed ... Max value = 0" << std::endl;return cv::Mat();}
std::cout << " Done ... Max value = " << max << std::endl;
return predict;
}
Задача ещё не решена.
Других решений пока нет …