2

我正在实施 Viola Jones 人脸检测算法。我对算法的 AdaBoost 学习部分的第一部分有疑问。

原始论文指出

弱分类器选择算法如下进行。对于每个特征,示例根据特征值进行排序。

我目前正在使用相对较小的 2000 个正图像和 1000 个负图像的训练集。该论文描述了拥有多达 10,000 个的数据集。

AdaBoost 的主要目的是减少 24x24 窗口中的特征数量,总计 160,000+。该算法适用于这些特征并选择最好的特征。

该论文描述了对于每个特征,它在每个图像上计算其值,然后根据值对它们进行排序。这意味着我需要为每个特征创建一个容器并存储所有样本的值。

我的问题是我的程序在只评估了 10,000 个功能(其中只有 6%)后内存不足。所有容器的总大小最终将达到 160,000*3000,即数十亿。我应该如何在不耗尽内存的情况下实现这个算法?我增加了堆大小,它让我从 3% 到 6%,我认为增加它不会起作用。

该论文暗示在整个算法中都需要这些排序值,因此我不能在每个特征之后丢弃它们。

到目前为止,这是我的代码

public static List<WeakClassifier> train(List<Image> positiveSamples, List<Image> negativeSamples, List<Feature> allFeatures, int T) {
    List<WeakClassifier> solution = new LinkedList<WeakClassifier>();

    // Initialize Weights for each sample, whether positive or negative
    float[] positiveWeights = new float[positiveSamples.size()];
    float[] negativeWeights = new float[negativeSamples.size()];

    float initialPositiveWeight = 0.5f / positiveWeights.length;
    float initialNegativeWeight = 0.5f / negativeWeights.length;

    for (int i = 0; i < positiveWeights.length; ++i) {
        positiveWeights[i] = initialPositiveWeight;
    }
    for (int i = 0; i < negativeWeights.length; ++i) {
        negativeWeights[i] = initialNegativeWeight;
    }

    // Each feature's value for each image
    List<List<FeatureValue>> featureValues = new LinkedList<List<FeatureValue>>();

    // For each feature get the values for each image, and sort them based off the value
    for (Feature feature : allFeatures) {
        List<FeatureValue> thisFeaturesValues = new LinkedList<FeatureValue>();

        int index = 0;
        for (Image positive : positiveSamples) {
            int value = positive.applyFeature(feature);
            thisFeaturesValues.add(new FeatureValue(index, value, true));
            ++index;
        }
        index = 0;
        for (Image negative : negativeSamples) {
            int value = negative.applyFeature(feature);
            thisFeaturesValues.add(new FeatureValue(index, value, false));
            ++index;
        }

        Collections.sort(thisFeaturesValues);

        // Add this feature to the list
        featureValues.add(thisFeaturesValues);
        ++currentFeature;
    }

    ... rest of code
4

1 回答 1

1

这应该是选择弱分类器之一的伪代码:

normalize the per-example weights  // one float per example

for feature j from 1 to 45,396:
  // Training a weak classifier based on feature j.
  - Extract the feature's response from each training image (1 float per example)
  // This threshold selection and error computation is where sorting the examples
  // by feature response comes in.
  - Choose a threshold to best separate the positive from negative examples
  - Record the threshold and weighted error for this weak classifier

choose the best feature j and threshold (lowest error)

update the per-example weights

您无需在任何地方存储数十亿个特征。只需在每次迭代中即时提取特征响应。您正在使用积分图像,因此提取速度很快。那是主要的内存瓶颈,它并不多,每个图像中的每个像素只有一个整数......基本上与图像所需的存储量相同。

即使您只是计算了所有图像的所有特征响应并将它们全部保存,因此您不必每次迭代都这样做,但仍然只有:

  • 45396 * 3000 * 4 bytes =~ 520 MB,或者如果您确信有 160000 个可能的功能,
  • 160000 * 3000 * 4 字节 =~ 1.78 GB,或者如果您使用 10000 个训练图像,
  • 160000 * 10000 * 4 字节 =~ 5.96 GB

基本上,即使您确实存储了所有特征值,也不应该耗尽内存。

于 2012-12-08T19:19:50.557 回答