10#include "bayesnet/classifiers/XSP2DE.h"
11#include "bayesnet/utils/TensorUtils.h"
15XBA2DE::XBA2DE(
bool predict_voting) : Boost(predict_voting) {}
16std::vector<int> XBA2DE::initializeModels(
const Smoothing_t smoothing) {
17 torch::Tensor weights_ = torch::full({m}, 1.0 / m, torch::kFloat64);
18 std::vector<int> featuresSelected = featureSelection(weights_);
19 if (featuresSelected.size() < 2) {
20 notes.push_back(
"No features selected in initialization");
22 return std::vector<int>();
24 for (
int i = 0; i < featuresSelected.size() - 1; i++) {
25 for (
int j = i + 1; j < featuresSelected.size(); j++) {
26 std::unique_ptr<Classifier> model = std::make_unique<XSp2de>(featuresSelected[i], featuresSelected[j]);
27 model->fit(dataset, features, className, states, weights_, smoothing);
28 add_model(std::move(model), 1.0);
31 notes.push_back(
"Used features in initialization: " + std::to_string(featuresSelected.size()) +
" of " +
32 std::to_string(features.size()) +
" with " + select_features_algorithm);
33 return featuresSelected;
35void XBA2DE::trainModel(
const torch::Tensor &weights,
const Smoothing_t smoothing) {
45 X_train_ = TensorUtils::to_matrix(X_train);
46 y_train_ = TensorUtils::to_vector<int>(y_train);
48 X_test_ = TensorUtils::to_matrix(X_test);
49 y_test_ = TensorUtils::to_vector<int>(y_test);
53 torch::Tensor weights_ = torch::full({m}, 1.0 / m, torch::kFloat64);
54 bool finished =
false;
55 std::vector<int> featuresUsed;
57 featuresUsed = initializeModels(smoothing);
58 if (featuresUsed.size() == 0) {
61 auto ypred = predict(X_train);
62 std::tie(weights_, alpha_t, finished) = update_weights(y_train, ypred, weights_);
64 for (
int i = 0; i < n_models; ++i) {
65 significanceModels[i] = alpha_t;
73 double priorAccuracy = 0.0;
74 double improvement = 1.0;
75 double convergence_threshold = 1e-4;
81 bool ascending = order_algorithm == Orders.ASC;
83 std::vector<std::pair<int, int>> pairSelection;
86 pairSelection = metrics.SelectKPairs(weights_, featuresUsed, ascending, 0);
87 if (order_algorithm == Orders.RAND) {
88 std::shuffle(pairSelection.begin(), pairSelection.end(), g);
90 int k = bisection ? pow(2, tolerance) : 1;
93 while (counter++ < k && pairSelection.size() > 0) {
94 auto feature_pair = pairSelection[0];
95 pairSelection.erase(pairSelection.begin());
96 std::unique_ptr<Classifier> model;
97 model = std::make_unique<XSp2de>(feature_pair.first, feature_pair.second);
98 model->fit(dataset, features, className, states, weights_, smoothing);
101 auto ypred = model->predict(X_train);
103 std::tie(weights_, alpha_t, finished) = update_weights(y_train, ypred, weights_);
107 models.push_back(std::move(model));
108 significanceModels.push_back(alpha_t);
114 std::tie(weights_, alpha_t, finished) = update_weights_block(k, y_train, weights_);
116 if (convergence && !finished) {
117 auto y_val_predict = predict(X_test);
118 double accuracy = (y_val_predict == y_test).sum().item<
double>() / (
double)y_test.size(0);
119 if (priorAccuracy == 0) {
120 priorAccuracy = accuracy;
122 improvement = accuracy - priorAccuracy;
124 if (improvement < convergence_threshold) {
134 if (convergence_best) {
136 priorAccuracy = std::max(accuracy, priorAccuracy);
139 priorAccuracy = accuracy;
144 finished = finished || tolerance > maxTolerance || pairSelection.size() == 0;
146 if (tolerance > maxTolerance) {
147 if (numItemsPack < n_models) {
148 notes.push_back(
"Convergence threshold reached & " + std::to_string(numItemsPack) +
" models eliminated");
150 for (
int i = 0; i < numItemsPack; ++i) {
151 significanceModels.pop_back();
156 notes.push_back(
"Convergence threshold reached & 0 models eliminated");
161 if (pairSelection.size() > 0) {
162 notes.push_back(
"Pairs not used in train: " + std::to_string(pairSelection.size()));
165 notes.push_back(
"Number of models: " + std::to_string(n_models));
167std::vector<std::string> XBA2DE::graph(
const std::string &title)
const {
return Ensemble::graph(title); }