2

顔検出に Viola Jones アルゴリズムを実装しています。アルゴリズムの AdaBoost 学習部分の最初の部分に問題があります。

元の論文の状態

弱分類器選択アルゴリズムは次のように進行します。各機能について、例は機能値に基づいて並べ替えられています。

私は現在、2000 枚のポジティブ画像と 1000 枚のネガティブ画像の比較的小さなトレーニング セットを使用しています。この論文では、10,000 もの大規模なデータ セットを持つことについて説明しています。

AdaBoost の主な目的は、合計 160,000 以上の 24x24 ウィンドウ内の機能の数を減らすことです。アルゴリズムはこれらの機能に作用し、最適なものを選択します。

この論文では、各特徴について、各画像でその値を計算し、値に基づいて並べ替えると説明しています。これが意味することは、機能ごとにコンテナーを作成し、すべてのサンプルの値を保存する必要があるということです。

私の問題は、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

これは、弱分類器の 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

何十億もの機能を保存する必要はどこにもありません。各反復でオンザフライで特徴応答を抽出するだけです。インテグラル イメージを使用しているため、抽出は高速です。これはメイン メモリのボトルネックであり、それほど多くはありません。すべての画像のすべてのピクセルに対して 1 つの整数だけです。基本的に、必要な画像と同じ量のストレージです。

すべての画像のすべての機能応答を計算し、それらをすべて保存しただけでも、反復ごとにそれを行う必要はありません。

  • 45396 * 3000 * 4 バイト =~ 520 MB、または 160000 の可能な機能があると確信している場合、
  • 160000 * 3000 * 4 バイト =~ 1.78 GB、または 10000 のトレーニング イメージを使用する場合、
  • 160000 * 10000 * 4 バイト =~ 5.96 GB

基本的に、すべての機能値を保存しても、メモリが不足することはありません。

于 2012-12-08T19:19:50.557 に答える