本人技术小白一枚,文章内容为看源码后的理解,若有不足之处,敬请指教。
--------------------------------------------------------------------------------------------------------------------------------------
前段时间看了《机器学习实战》里的Adaboost部分,但书中没有涉及级联,而使用时常常要用到级联来提高分类器效果,所以看了看OpenCV里的这部分源码,对于级联有了点认识,写出来,希望能够帮助一些朋友们。
被Cascade Adaboost的训练问题困扰了好久,今天终于看清了一些。级联训练,其实在内部是样本更新过程。Cascade样本更新,是利用已经训练出的强分类器对训练集中的样本进行预测,被预测为1的样本参与下一级强分类器的样本计数,即预测为1的样本数=numPos+numNeg,但要注意,真正参与训练的样本数要大于numPos+numNeg,因为由前面训练出的强分类器预测为0的值也参与了本级分类器的训练,只不过没有参与numPos+numNeg的计数。
bool CvCascadeClassifier::updateTrainingSet( double minimumAcceptanceRatio, double& acceptanceRatio)
{
int64 posConsumed = 0, negConsumed = 0;
imgReader.restart();
int posCount = fillPassedSamples( 0, numPos, true, 0, posConsumed );//正样本更新
if( !posCount )
return false;
cout << "POS count : consumed " << posCount << " : " << (int)posConsumed << endl;
int proNumNeg = cvRound( ( ((double)numNeg) * ((double)posCount) ) / numPos ); <span style="white-space:pre"> </span>// 负样本需要与正样本满足一定的比例关系
int negCount = fillPassedSamples( posCount, proNumNeg, false, minimumAcceptanceRatio, negConsumed );<span style="white-space:pre"> </span>//负样本更新
if ( !negCount )
return false;
curNumSamples = posCount + negCount;
acceptanceRatio = negConsumed == 0 ? 0 : ( (double)negCount/(double)(int64)negConsumed );
cout << "NEG count : acceptanceRatio " << negCount << " : " << acceptanceRatio << endl;
return true;
}
int CvCascadeClassifier::fillPassedSamples( int first, int count, bool isPositive, double minimumAcceptanceRatio, int64& consumed )
{
int getcount = 0;
Mat img(cascadeParams.winSize, CV_8UC1);
for( int i = first; i < first + count; i++ )
{
for( ; ; )
{
if( consumed != 0 && ((double)getcount+1)/(double)(int64)consumed <= minimumAcceptanceRatio )
return getcount;
bool isGetImg = isPositive ? imgReader.getPos( img ) :<span style="white-space:pre"><span style="white-space:pre"> </span>//从总样本集中抽取正负样本
imgReader.getNeg( img );
if( !isGetImg )
return getcount;
consumed++;
featureEvaluator->setImage( img, isPositive ? 1 : 0, i );<span style="white-space:pre"> </span>//样本已经被送到<span style="font-family: Arial, Helvetica, sans-serif;">featureEvaluator</span>
if( predict( i ) == 1.0F )<span style="white-space:pre"> </span>//只有预测为1时,getcount++,proNumPos或proNumNeg才会更新
{
getcount++;
printf("%s current samples: %d\r", isPositive ? "POS":"NEG", getcount);
break;
}
}
}
return getcount;
}</span>