cvTrimWeights的源码在opencv的cvboost.cpp文件之中,具体内容和部分注释如下所
/*
*cvTrimWeights
*作用:对小于一定阈值的权重剔除,因为权重较小的样本对训练结果影响很小,剔除后,这样在训练样本时可以缩短训练时间
*/
CV_BOOST_IMPL
CvMat* cvTrimWeights( CvMat* weights,//训练样本的权重矩阵
CvMat* idx, //训练样本的索引序列矩阵
float factor ) //剔除小权重的样本后剩余样本的比例,根据这个参数来计算需要剔除较小样本的阈值
{
CvMat* ptr = 0;
CV_FUNCNAME( "cvTrimWeights" );
__BEGIN__;
int i, index, num;
float sum_weights;
uchar* wdata;
size_t wstep;
int wnum;
float threshold;
int count;
float* sorted_weights;
CV_ASSERT( CV_MAT_TYPE( weights->type ) == CV_32FC1 );
ptr = idx;
sorted_weights = NULL;
if( factor > 0.0F && factor < 1.0F )
{
size_t data_size;
CV_MAT2VEC( *weights, wdata, wstep, wnum );
num = ( idx == NULL ) ? wnum : MAX( idx->rows, idx->cols );
data_size = num * sizeof( *sorted_weights );
sorted_weights = (float*) cvAlloc( data_size );
memset( sorted_weights, 0, data_size );
sum_weights = 0.0F;
for( i = 0; i < num; i++ )
{
index = icvGetIdxAt( idx, i );//将矩阵idx中第i个位置上的样本序列取出
sorted_weights[i] = *((float*) (wdata + index * wstep));//取出idx第i个位置上的权重
sum_weights += sorted_weights[i];//样本的权重和
}
icvSort_32f( sorted_weights, num, 0 );//对样本排序
sum_weights *= (1.0F - factor); //根据训练样本总的权重和factor来计算需要剔除的小权重训练样本的权重和
i = -1;
do { sum_weights -= sorted_weights[++i]; }//对排序后的样本从最小的小权重的样本开始减去,直到while中条件结束
while( sum_weights > 0.0F && i < (num - 1) );
threshold = sorted_weights[i];
/*跳出do-while循环后,把没有被剔除权重的样本中,最小权重的那个样本的权重赋给threshold。对外表现为:凡是样本的权重小于
这个阈值,就直接剔除*/
while( i > 0 && sorted_weights[i-1] == threshold ) i--;//剔除小权重的样本后,再对原来剔除的那部分中等于阈值的样本捡回来,挺人性化的哈
if( i > 0 || ( idx != NULL && CV_MAT_TYPE( idx->type ) != CV_32FC1 ) )
{
CV_CALL( ptr = cvCreateMat( 1, num - i, CV_32FC1 ) );
count = 0;
for( i = 0; i < num; i++ )
{
index = icvGetIdxAt( idx, i );
if( *((float*) (wdata + index * wstep)) >= threshold )//只对阈值>threshold的权重操作
{
CV_MAT_ELEM( *ptr, float, 0, count ) = (float) index;
count++;
}
}
assert( count == ptr->cols );
}
cvFree( &sorted_weights );
}
__END__;
return ptr; //只返回权重大于阈值的样本
}