关于adaboost+haar特征实现人脸检测过程的一些细节问题

本人在用C语言编写基于adanboost算法和haar特征的人脸检测代码时遇到一些问题,所以想请教一下各位,问题如下:
1.在训练阶段,是否把每一训练的图片都调整为相同的大小(我找的人脸库图片大小稍微有差距的)。
2.在训练阶段,如果我没有理解错的话是对同一特征模板,固定位置和大小(一个固定位置的窗口,这也是我问题1的由来),然后拿这个窗口遍历所有样本,求出对应的特征值,然后改变窗口的大小和位置。重复前面的步骤。得到了不同位置,不同大小的同一特征模板下所有样本的特征值。然后再通过实验找出这堆特征值之中的最佳阈值给分类器,这样就得到了基于一种haar特征的分类器。然后更换特征模板,重复上述步骤,得到了很多种haar特征模板的分类器。然后用这些分类器合成第一个弱分类器,用这个弱分类器对所有的样本进行投票,记录投票结果,然后更新样本权重,使用带有权重的样本训练第二个分类器,重复上述步骤,最后结合成一个强分类器。
我想知道我所理解的过程有没有问题?
3.第三个问题,来源于第二个问题我描述的过程中,有一个做法叫做更新样本权重,我不理解更新样本权重是什么意思,是把每个样本的新权重乘到灰度值上面吗?

基于Monster 组和GPT的调写:

  • 1.在训练阶段,把所有的训练图片调整为相同的大小可以确保在特征计算时输入图像的大小一致,这有助于简化特征计算过程和降低计算复杂度。建议将所有的训练图片调整为相同的大小。
  • 2.在训练阶段,你理解是正确的。对于每种Haar特征模板,要将其应用于所有训练样本的不同位置和尺度上,并计算特征值。然后,根据特征值和标签之间的关系,找到最佳的分类阈值,并将此Haar特征模板与该分类阈值结合起来形成一个基本分类器。用AdaBoost算法组合多个基本分类器形成强分类器。
  • 3.在AdaBoost算法中,每个训练样本都有一个权重,初始时所有样本的权重相等。在训练过程中,AdaBoost算法根据当前分类器的性能,调整错误分类样本的权重,使得被错误分类的样本得到更高的权重,而被正确分类的样本得到更低的权重。所以,更新样本权重是指根据当前分类器的性能,重新计算每个样本的权重。更新样本权重不会影响图像的灰度值。

参考GPT:
1 在训练阶段,建议将所有的训练图片调整为相同的大小,这样可以简化处理流程,并且减少对特征的影响,使得特征更具有泛化性能。如果图片大小差距较大,可以进行缩放、裁剪等操作,将图片调整到相同的大小。

2 在训练阶段,对于每一个特征模板,需要遍历所有的训练样本,对于每个样本,计算特征模板在不同位置、不同大小下的特征值。这个过程通常称为计算积分图(integral image)或者积分图像(integral image),可以通过积分图像技术来加速计算。在计算特征值时,通常使用的是滑动窗口的方法,即在图像上滑动一个固定大小的窗口,计算窗口内的特征值。对于不同的特征模板,需要重复这个过程,得到每个特征模板在所有训练样本上的特征值。然后可以对这些特征值进行排序,并尝试不同的阈值,以找到最佳的判决阈值,
3 更新样本权重是指根据当前的分类结果和权重,对样本的权重进行调整。具体来说,在AdaBoost算法的每一轮迭代中,被分类错误的样本权重会被增加,被分类正确的样本权重会被减少,这样可以使得被分类错误的样本在下一轮迭代中得到更多的关注和训练,从而提高分类器的性能。在实现上,通常是通过修改样本的权重,使得被分类错误的样本在下一轮迭代中的权重变大,而被分类正确的样本的权重变小。在具体实现中,可以使用一个权重向量来记录每个样本的权重,对于每个迭代轮次,根据当前分类器的性能和样本的分类结果来更新权重向量的值。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:

  1. 在训练阶段,一般需要将所有的训练图片都调整为相同的大小,否则会影响特征的提取和分类器的训练效果。

  2. 在训练阶段,对于同一特征模板,需要固定位置和大小,然后遍历所有的训练样本,计算出该特征模板在各个位置和大小下的特征值,然后通过实验找出最佳阈值,进而训练出一个基于该特征模板的分类器。接着更换特征模板,重复上述步骤,得到多个基于不同特征模板的分类器。合成弱分类器时,对每个分类器进行加权,最终得到一个弱分类器。在强分类器中,每个弱分类器的权重由AdaBoost算法确定。

  3. 在AdaBoost算法中,每个样本都有一个权重,开始时所有样本的权重相等。在训练弱分类器时,根据分类器的分类结果和实际的分类结果,更新样本的权重,即分类错误的样本权重增加,分类正确的样本权重减少。更新权重的公式如下:

$w_i^{(t+1)} = w_i^{(t)} \times \exp(-\alpha_ty_iG_t(x_i))$

其中,$w_i^{(t)}$是第$t$轮迭代中第$i$个样本的权重,$\alpha_t$是学习率,$y_i$表示第$i$个样本的真实分类(1为正样本,-1为负样本),$G_t(x_i)$表示第$t$轮迭代完成后的弱分类器的输出结果(1为正样本,-1为负样本)。

更新权重后,需要对样本权重进行归一化,使它们之和等于1,即:

$w_i^{(t+1)} = \frac{w_i^{(t+1)}}{\sum_{j=1}^N w_j^{(t+1)}}$

其中,$N$为样本数。

关于代码实现,这里提供一个伪代码:

double weight[N];
double alpha[T];
int classifier[T][N];

// 初始化样本权重
for(int i = 0; i < N; i++)
    weight[i] = 1.0 / N;

// 循环迭代T次
for(int t = 0; t < T; t++){
    // 训练第t个弱分类器
    train_classifier(classifier[t], weight);
    
    // 计算分类器的误差率
    double error = 0;
    for(int i = 0; i < N; i++){
        if(classifier[t][i] != label[i])
            error += weight[i];
    }
    
    alpha[t] = 0.5 * log((1.0 - error) / error);
    
    // 更新样本权重
    for(int i = 0; i < N; i++){
        if(classifier[t][i] == label[i])
            weight[i] *= exp(-alpha[t]);
        else
            weight[i] *= exp(alpha[t]);
    }
    
    // 归一化样本权重
    double sum = 0;
    for(int i = 0; i < N; i++)
        sum += weight[i];
        
    for(int i = 0; i < N; i++)
        weight[i] /= sum;
}

// 计算最终分类结果
int result[N] = {};
for(int i = 0; i < N; i++){
    double score = 0;
    for(int t = 0; t < T; t++){
        score += alpha[t] * classifier[t][i];
    }
    if(score > 0)
        result[i] = 1;
    else
        result[i] = -1;
}

如果我的回答解决了您的问题,请采纳!

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 给你找了一篇非常好的博客,你可以看看是否有帮助,链接:小工匠聊架构 - 缓存与数据库【双写不一致】&【读写并发不一致】解决方案一览
  • 除此之外, 这篇博客: 半部秘籍--分类、回归、集成与无监督中的 2.2 回归器评价 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    1.可释方差分数(explain variance score)

    2.平均绝对误差(mean absolute error)

    3.均方误差(mean squared error)

    4.均方对数误差(mean squared logarithmic error),适用于具有指数增长的趋势的目标。

    5.中值绝对误差(median absolute error),该函数不支持多输出。

    6.决定系数分数( score)

    
    from sklearn import datasets
    from sklearn.model_selection import train_test_split
    from sklearn.ensemble import RandomForestRegressor
    from sklearn.metrics import mean_squared_error
    from sklearn.metrics import median_absolute_error
    from sklearn.metrics import mean_squared_log_error
    from sklearn.metrics import mean_absolute_error
    from sklearn.metrics import explained_variance_score
    from sklearn.metrics import r2_score
    import numpy as np
    
    bos_house = datasets.load_boston()
    bos_house_data = bos_house['data']
    bos_house_target = bos_house['target']
    
    x_train,x_test,y_train,y_test = train_test_split(bos_house_data,bos_house_target,random_state=41)
    forest_reg = RandomForestRegressor(random_state=41)
    forest_reg.fit(x_train,y_train)
    y_pred = forest_reg.predict(x_test)
    
    #mean_squared_error
    print('MSE为:',mean_squared_error(y_test,y_pred))
    print('MSE为(直接计算):',np.mean((y_test-y_pred)**2))
    
    print('RMSE为:',np.sqrt(mean_squared_error(y_test,y_pred)))
    
    #median_absolute_error
    print(np.median(np.abs(y_test-y_pred)))
    print(median_absolute_error(y_test,y_pred))
    
    #mean_absolute_error
    print(np.mean(np.abs(y_test-y_pred)))
    print(mean_absolute_error(y_test,y_pred))
    
    #mean_squared_log_error
    print(mean_squared_log_error(y_test,y_pred))
    print(np.mean((np.log(y_test+1)-np.log(y_pred+1))**2))
    
    #explained_variance_score
    print(explained_variance_score(y_test,y_pred))
    print(1-np.var(y_test-y_pred)/np.var(y_test))
    
    #r2_score
    print(r2_score(y_test,y_pred))
    print(1-(np.sum((y_test-y_pred)**2))/np.sum((y_test -np.mean(y_test))**2))
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^