Weka 개발[10] - NBTree 소스 소개

6190 단어
나의 많지 않은 독자 중 한 명이 나에게 이메일을 보냈는데, 그는 NBTree와 J48의 차이가 무엇인지 알아내지 못했다고 말했다. 당시에 나도 시간이 없었기 때문에 오늘에 이르러서야 비로소 대충 보았다.대강 말하다.
다음은 J48의 buildClassifier 코드입니다.
public void buildClassifier(Instances instances) throws Exception {
 
    ModelSelection modSelection;
 
    if (m_binarySplits)
        modSelection = new BinC45ModelSelection(m_minNumObj, instances);
    else
       modSelection = new C45ModelSelection(m_minNumObj, instances);
    if (!m_reducedErrorPruning)
       m_root = new C45PruneableClassifierTree(modSelection, 
!m_unpruned,m_CF, m_subtreeRaising, !m_noCleanup);
    else
       m_root = new PruneableClassifierTree(modSelection, 
!m_unpruned,m_numFolds, !m_noCleanup, m_Seed);
       m_root.buildClassifier(instances);
}

NBTree의 buildClassifier 코드는 다음과 같습니다.
public void buildClassifier(Instances instances) throws Exception {
    
    NBTreeModelSelection modSelection = 
        new NBTreeModelSelection(m_minNumObj, instances);
 
    m_root = new NBTreeClassifierTree(modSelection);
    m_root.buildClassifier(instances);
}

여기에 비교적 특수한 모델 셀렉션 클래스가 있는데 이 클래스는 이전에 언급한 적이 없다. 이것은 트리를 결정하는 모델 클래스이다. 예를 들어 위 J48 코드의 BINC45 모델 셀렉션은 연속 속성에 대해 분열할 때 두 개의 서브 결점만 나눈다.두 마디를 더 하자면 사실 BINC45 Model Selection과 C45 Model Selection 클래스는 앞으로 강의할 NBTree Model Selection 클래스를 포함하여 모두 차이가 많지 않다. *** Model Selection 클래스 중의 select 모델 함수는 Classifier Split 모델 대상을 되돌려준다. Classifier Split Model은 어떻게 분열되는지 고민하는 모델이다.
위에서 말한 바와 같이 우리는 J48과 NBTree가 코드에서 서로 다른 구조 트리의 모델을 선택한 것을 알 수 있다. 물론 그들은 다르다(물론 이것은 쓸데없는 말이다). 다른 점은 J48에서 mminNumObj 기본값은 2이고 NBTree에서 mminNumObj의 기본값은 30입니다.
NBTree도 고전적인 알고리즘이 아니라는 것을 감안하면 어떤 사람들은 어떻게 된 일인지 모를 수도 있다. 대략적으로 말하자면 결정 트리의 구조 방법과 비슷하다. 먼저 결정 트리를 구축하고 잎 결점마다 베일스 분류기를 구성한다(이것이 바로 m minNumObj가 30원인인 이유이다).구체적인 내용은 논문: Scaling Up the Accuracy of Naive-Bayes Classifiers: A Decision-Tree Hybrid.
우리는 먼저 NBTreeModelSelection 종류를 보고 selectModel 함수를 찾았다. 방금 이 함수는 다른 **MocelSelection과 차이가 많지 않다고 말했는데 나도 근거가 있다. NBTreeModelSelection의 두 가지 경고를 볼 수 있다. 이 두 변수는 NBTreeModelSelection에서 쓸모가 없고 분명히 복사된 것이다.다음 세 변수에 주의하십시오.
NBTreeSplit[] currentModel;
    NBTreeSplit bestModel = null;
NBTreeNoSplit noSplitModel = null;

NBTree Split와 NBTree No Split는 모두 Classifier Split Model을 계승한다. select Model 함수에 주석도 적지 않다. 나도 코드를 설명하지 않는다. 대체로 다음과 같다. 예를 들어 견본이 모두 하나의 견본에 속하면 분열되지 않는다. 그러면 noSplit Model 대상으로 돌아가고 그렇지 않으면 j의 속성에 대해currentel[i]을 조정한다.buildClassifier 함수, 마지막으로 getErrors에 따라 가장 좋은 분열 속성을 결정합니다.
지금까지 열거된 코드는 확실히 J48과 차이가 많지 않다. 그들의 주요 차이점은 NBTreeNoSplit 클래스에 있다.J48에 사용된 Nosplit 클래스의buildClassifer 함수는 다음과 같습니다.
public final void buildClassifier(Instances instances) 
throws Exception {
    m_distribution = new Distribution(instances);
    m_numSubsets = 1;
}

NBTreeNoSplit 클래스의 buildClassifer 함수를 나열합니다.
public final void buildClassifier(Instances instances) throws Exception {
    m_nb = new NaiveBayesUpdateable();
    m_disc = new Discretize();
    m_disc.setInputFormat(instances);
    Instances temp = Filter.useFilter(instances, m_disc);
    m_nb.buildClassifier(temp);
    if (temp.numInstances() >= 5) {
       m_errors = crossValidate(m_nb, temp, new Random(1));
    }
    m_numSubsets = 1;
}

차이는 여전히 뚜렷하다. m 를 제외하고는numSubset=1 이 표지는 잎 결점의 문장이다.NBTreeNoSplit류의buildClassifier에서 잎 결점에 m 를 구성합니다nb Naive Bayes 분류기, 그러나 다시 말하자면, 한참 동안 이야기했는데, 바로 이 정도의 차이로 NBTree라는 새로운 분류기가 생겼다.
m_root는 NBTreeClassifier Tree 대상입니다. NBTreeClassifier Tree 대상을 다시 한 번 보겠습니다.buildClassifier 함수를 직접 보겠습니다.
public void buildClassifier(Instances data) throws Exception {
    super.buildClassifier(data);
   cleanup(new Instances(data, 0));
   assignIDs(-1);
}

이것은 부모 클래스의buildClsifier를 직접 호출하는 것을 볼 수 있으며, 부모 클래스는Classifier Tree이며, J48에서도 마찬가지로 Clsifier Tree 클래스를 사용합니다.
샘플을 분류하는 경우 NBTree의 classify Instance 함수에서 다음을 반환합니다.
return m_root.classifyInstance(instance);

아까 맞다고 mroot는 NBTreeClassifier Tree 대상이지만 NBTreeClassifier가classifyInstance 함수를 실현하지 못하면 mroot에서 호출된classifyInstance는 실제로ClassifierTree 클래스의 함수입니다.classifyInstance에서 다음을 수행합니다.
for (j = 0; j < instance.numClasses(); j++) {
    currentProb = getProbs(j, instance, 1);
    if (Utils.gr(currentProb, maxProb)) {
       maxIndex = j;
       maxProb = currentProb;
    }
}

이 코드는 재미없다. 견본이 어느 종류에 속하는지 확률이 가장 높으면, 이 종류로 분류된다.이 안의 getProbs 함수에서야말로 우리의 관심사다.
private double getProbs(int classIndex, Instance instance, double weight)
throws Exception {
 
    double prob = 0;
 
    if (m_isLeaf) {
       return weight * localModel().classProb(classIndex, instance, -1);
    } else {
       int treeIndex = localModel().whichSubset(instance);
       if (treeIndex == -1) {
           double[] weights = localModel().weights(instance);
           for (int i = 0; i < m_sons.length; i++) {
              if (!son(i).m_isEmpty) {
              prob += son(i).getProbs(classIndex, instance, 
weights[i] * weight);
              }
           }
           return prob;
       } else {
           if (son(treeIndex).m_isEmpty) {
return weight * localModel().classProb(classIndex, 
instance, treeIndex);
           } else {
              return son(treeIndex).getProbs(classIndex, 
instance, weight);
           }
       }
    }
}

만약에 잎결점이 아니라면: 이 견본이 어느 자결점에 속해야 하는지를 먼저 얻고treeIndex=-1이 이 속성 값이 부족하다는 것을 나타낸다면 그 계산 방법은 각 자결점을 분리해서 계산하고 덧붙이는 것이다.만약 부족한 것이 아니라면, 만약 자결점이 비어 있다면, 자결점의 계산 방법과 같지 않으면, 귀속된다.
잎사귀 결점:localModel이 Classifier SplitModel 대상을 되돌려줍니다. 이 대상은classProb 함수를 호출합니다. NBTreeNoSplit 함수의classProb 함수를 보십시오.
public double classProb(int classIndex, Instance instance, int theSubset)
throws Exception {
m_disc.input(instance);
    Instance temp = m_disc.output();
    return m_nb.distributionForInstance(temp)[classIndex];
}

아까 말씀드린 mnb 이 Naive Bayes 분류기는 distribution ForInstance를 호출합니다.NBTree는 거의 다 말하지 않았는데 마지막에 타격을 주었다. 나는 이 분류기가 이해할 필요가 없다고 느꼈다. 그러나 그 분류기를 제기한 작가는 상상력이 풍부한 사람이라고 생각한다. NBTree의 응용에 대해 나는 이 분류기가 VFDTc에서 사용되었고 몇 개의 개선판에서 사용되었다. 다른 것을 사용한 곳은 나도 모른다. 아는 사람이 있으면 나에게 알려줘.

좋은 웹페이지 즐겨찾기