2012-12-07 5 views
2

얼굴 검색을위한 Viola Jones 알고리즘을 구현 중입니다. 알고리즘의 일부를 학습하는 AdaBoost의 첫 번째 부분에 문제가 있습니다.Viola Jones AdaBoost가 시작하기 전에 메모리가 부족합니다.

원래 논문은 다음

약한 분류 된 인터넷 ER 선택 알고리즘의 진행을 말한다. 각 기능에 대해 예제는 기능 값에 따라 정렬됩니다.

저는 현재 비교적 작은 양성 이미지 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 
+0

원래의 논문에서는 "탐지기의 기본 해상도가 24x24 인 경우 사각형 피쳐의 완전한 세트는 큽니다 ** 45,396 **"입니다. 160,000이 아닙니다. 160,000을 어떻게 얻습니까? –

+0

또한 모든 기능을 명시 적으로 저장하지 않아도됩니다. 한 번에 모든 교육 패치에서 기능 중 하나에 대해 추출 된 값. 부스팅 알고리즘의 각 단계에서 각 기능의 유용성을 평가하고 가장 적합한 것을 선택하여 강력한 분류 기준에 추가 할 수 있습니다. 동시에 메모리에있는 모든 이미지의 모든 기능에 대한 결과를 실제로 가질 필요는 없습니다. –

+0

5 개 기능 각각에는 약 45,396 개의 가능한 위치/크기가 있습니다. 이 논문은 총 160,000 개의 기능을 언급합니다. 2x2 피쳐 (대각선 영역)는 가능성이 적습니다. – robev

답변

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 바이트 = ~ 520MB, 또는 160000 개의 가능한 기능이 있다고 확신하는 경우
  • 160000 * 3000 * 4 바이트 = 1.78GB, 또는 10000 학습 이미지를 사용하는 경우
  • 160000 * 10000 * 4 바이트 = ~ 5.96 GB

기본적으로 을 실행해도 메모리가 부족하지 않아야합니다.은 모든 기능 값을 저장합니다.

+0

이것은 종이가 묘사 할 때 t = 1, ... T에 대해 다른 루프로 둘러 쌓여 있습니까? 예제 가중치를 어떻게 업데이트합니까? 선택한 피처가 각 예제를 적절하게 분류하는지 판단합니다. 기능을 선택하고 다른 기능을 찾으려면 기능 목록에서 이전에 선택한 기능을 제거합니까? (그래서 당신은 그것을 다시 선택하지 않습니다). 나는 당신이 처음에 모든 가치를 저장하고 그 후에 특징을 발견한다는 인상 아래 있었기 때문에 이것들을 묻습니다. 나는 내 기억 문제로 인해 영리하지 않다. 숫자 대신 객체를 저장하기 때문에 메모리가 부족합니다. – robev

+1

예, 이것은 내부 루프 일뿐입니다. 어느 것이'T' 번 했는가. 업데이트 된 예제 가중치의 공식은 종이에 있습니다 (의사 코드의 4 단계 ... 반복 할 수 있지만 별도의 질문에 대해서는 가장 좋습니다). 피쳐 (특정 반복에서 최상의 기능)를 선택하면 피쳐 ID, 임계 값 및 가중치 (3 개의 부동 소수점)를 저장하여 강력한 분류 기준에 추가합니다. 그런 다음 다음 반복으로 이동하여 새로운 최상의 기능을 찾습니다. 다시 말하지만, 이것들은 알고리즘에 관한 질문 인 것 같습니다. 메모리 사용법이 아니기 때문에 별도의 질문에 가장 적합 할 것입니다. –

+0

후속 질문을 게시하면 나 (그리고 다른 사용자)를 위해 여기에 링크를 붙여 넣을 수 있습니다. –