skika/ensemble/nacre.cpp
// foreground trees make predictions, update votes, keep track of actual labbels
// find warning trees, select candidate trees
// find drifted trees, update potential_drifted_tree_indices
// candidate trees make predictions
foreground trees make predictions, update votes, keep track of actual labbels
find warning trees, select candidate trees
find drifted trees, update potential_drifted_tree_indices
candidate trees make predictions
foreground trees make predictions update votes keep track of actual labbels find warning trees select candidate trees find drifted trees update potential_drifted_tree_indices candidate trees make predictions
void nacre::train() {
    if (foreground_trees.empty()) {
        init();
    }
    potential_drifted_tree_indices.clear();
    stable_tree_indices.clear();
    backtrack_instances.push_back(instance);
    num_instances_seen++;
    int actual_label = instance->getLabel();
    if (actual_labels.size() >= kappa_window_size) {
        actual_labels.pop_front();
    }
    actual_labels.push_back(actual_label);
    vector<int> warning_tree_pos_list;
    vector<int> drifted_tree_pos_list;
    shared_ptr<pearl_tree> cur_tree = nullptr;
    for (int i = 0; i < num_trees; i++) {
        std::poisson_distribution<int> poisson_distr(lambda);
        int weight = poisson_distr(mrand);
        if (weight == 0) {
            continue;
        }
        instance->setWeight(weight);
        cur_tree = static_pointer_cast<pearl_tree>(foreground_trees[i]);
        cur_tree->train(*instance);
        int predicted_label = cur_tree->predict(*instance, true);
        int error_count = (int)(predicted_label != actual_label);
        bool warning_detected_only = false;
        if (detect_change(error_count, cur_tree->warning_detector)) {
            warning_detected_only = true;
            cur_tree->bg_pearl_tree = make_pearl_tree(-1);
            cur_tree->warning_detector->resetChange();
        }
        if (detect_change(error_count, cur_tree->drift_detector)) {
            warning_detected_only = false;
            drifted_tree_pos_list.push_back(i);
            potential_drifted_tree_indices.insert(i);
            cur_tree->warning_detector->resetChange();
            cur_tree->drift_detector->resetChange();
        }
        if (warning_detected_only) {
            warning_tree_pos_list.push_back(i);
        }
        int correct_count = (int)(actual_label == predicted_label);
        if (cur_tree->replaced_tree
                && detect_stability(correct_count, stability_detectors[i])) {
            stability_detectors[i] = make_unique<HT::ADWIN>(stability_delta);
            stable_tree_indices.push_back(i);
        }
    }
    for (int i = 0; i < candidate_trees.size(); i++) {
        candidate_trees[i]->predict(*instance, true);
    }
    for (int i = 0; i < predicted_trees.size(); i++) {
        predicted_trees[i]->predict(*instance, true);
    }
    if (warning_tree_pos_list.size() > 0) {
        pearl::select_candidate_trees(warning_tree_pos_list);
    }
    if (drifted_tree_pos_list.size() > 0) {
        adapt_state(drifted_tree_pos_list, false);
    }
}
void nacre :: train ( ) { if ( foreground_trees . empty ( ) ) { init ( ) ; } potential_drifted_tree_indices . clear ( ) ; stable_tree_indices . clear ( ) ; backtrack_instances . push_back ( instance ) ; num_instances_seen ++ ; int actual_label = instance -> getLabel ( ) ; if ( actual_labels . size ( ) >= kappa_window_size ) { actual_labels . pop_front ( ) ; } actual_labels . push_back ( actual_label ) ; vector < int > warning_tree_pos_list ; vector < int > drifted_tree_pos_list ; shared_ptr < pearl_tree > cur_tree = nullptr ; for ( int i = 0 ; i < num_trees ; i ++ ) { std :: poisson_distribution < int > poisson_distr ( lambda ) ; int weight = poisson_distr ( mrand ) ; if ( weight == 0 ) { continue ; } instance -> setWeight ( weight ) ; cur_tree = static_pointer_cast < pearl_tree > ( foreground_trees [ i ] ) ; cur_tree -> train ( * instance ) ; int predicted_label = cur_tree -> predict ( * instance , true ) ; int error_count = ( int ) ( predicted_label != actual_label ) ; bool warning_detected_only = false ; if ( detect_change ( error_count , cur_tree -> warning_detector ) ) { warning_detected_only = true ; cur_tree -> bg_pearl_tree = make_pearl_tree ( -1 ) ; cur_tree -> warning_detector -> resetChange ( ) ; } if ( detect_change ( error_count , cur_tree -> drift_detector ) ) { warning_detected_only = false ; drifted_tree_pos_list . push_back ( i ) ; potential_drifted_tree_indices . insert ( i ) ; cur_tree -> warning_detector -> resetChange ( ) ; cur_tree -> drift_detector -> resetChange ( ) ; } if ( warning_detected_only ) { warning_tree_pos_list . push_back ( i ) ; } int correct_count = ( int ) ( actual_label == predicted_label ) ; if ( cur_tree -> replaced_tree && detect_stability ( correct_count , stability_detectors [ i ] ) ) { stability_detectors [ i ] = make_unique < HT :: ADWIN > ( stability_delta ) ; stable_tree_indices . push_back ( i ) ; } } for ( int i = 0 ; i < candidate_trees . size ( ) ; i ++ ) { candidate_trees [ i ] -> predict ( * instance , true ) ; } for ( int i = 0 ; i < predicted_trees . size ( ) ; i ++ ) { predicted_trees [ i ] -> predict ( * instance , true ) ; } if ( warning_tree_pos_list . size ( ) > 0 ) { pearl :: select_candidate_trees ( warning_tree_pos_list ) ; } if ( drifted_tree_pos_list . size ( ) > 0 ) { adapt_state ( drifted_tree_pos_list , false ) ; } }
foreground trees make predictions, update votes, keep track of actual labbels
find warning trees, select candidate trees
find drifted trees, update potential_drifted_tree_indices
candidate trees make predictions
foreground trees make predictions update votes keep track of actual labbels find warning trees select candidate trees find drifted trees update potential_drifted_tree_indices candidate trees make predictions
// keep track of actual labels for candidate tree evaluations // detect warning // detect drift // detect stability // if warnings are detected, find closest state and update candidate_trees list // if actual drifts are detected, swap trees and update cur_state // pearl::adapt_state(drifted_tree_pos_list);