Files
mlpack/fastlib/trunk/contrib/pram/density_tree/main.cc
T

322 lines
9.7 KiB
C++

/**
* @file main.cc
* @ Parikshit Ram (pram@cc.gatech.edu)
*
*/
#include <string>
#include "fastlib/fastlib.h"
#include "dtree.h"
const fx_entry_doc dtree_main_entries[] = {
{"d", FX_REQUIRED, FX_STR, NULL,
" Data file \n"},
{"folds", FX_PARAM, FX_INT, NULL,
" Number of folds for cross validation.\n"},
{"tree_file", FX_PARAM, FX_STR, NULL,
" The file in which the tree would be printed.\n"},
{"train_time", FX_TIMER, FX_CUSTOM, NULL,
" Training time for obtaining the optimal tree.\n"},
{"test_time", FX_TIMER, FX_CUSTOM, NULL,
" Testing time for the optimal decision tree.\n"},
{"print_tree", FX_PARAM, FX_BOOL, NULL,
" Whether to print the tree or not.\n"},
FX_ENTRY_DOC_DONE
};
const fx_submodule_doc dtree_submodules[] = {
FX_SUBMODULE_DOC_DONE
};
const fx_module_doc dtree_main_doc = {
dtree_main_entries, dtree_submodules,
"DTree Parameters \n"
};
void PermuteMatrix(const Matrix&, Matrix*);
int main(int argc, char *argv[]){
srand( time(NULL));
fx_module *root = fx_init(argc, argv, &dtree_main_doc);
std::string data_file = fx_param_str_req(root, "d");
Matrix dataset;
NOTIFY("Loading data file...\n");
data::Load(data_file.c_str(), &dataset);
NOTIFY("%"LI"d points in %"LI"d dims.", dataset.n_cols(),
dataset.n_rows());
// // getting information about the feature type
// // REAL, INTEGER, NOMINAL. Most probably using
// // enum ... don't know how to use it though.
// ArrayList<enum> dim_type;
// dim_type.Init(dataset.n_rows());
// for (index_t i = 0; i < dim_type.size(); i++) {
// // assign dim type somehow
// } // end for
// finding the max and min vals for the dataset
ArrayList<double> max_vals, min_vals;
max_vals.Init(dataset.n_rows());
min_vals.Init(dataset.n_rows());
Matrix temp_d;
la::TransposeInit(dataset, &temp_d);
for (index_t i = 0; i < temp_d.n_cols(); i++) {
// if (dim_type[i] != NOMINAL) {
Vector dim_vals;
temp_d.MakeColumnVector(i, &dim_vals);
std::vector<double> dim_vals_vec(dim_vals.ptr(),
dim_vals.ptr() + temp_d.n_rows());
sort(dim_vals_vec.begin(), dim_vals_vec.end());
min_vals[i] = *(dim_vals_vec.begin());
max_vals[i] = *(dim_vals_vec.end() -1);
// }
}
// Initializing the tree
DTree *dtree = new DTree();
dtree->Init(max_vals, min_vals, dataset.n_cols());
// Getting ready to grow the tree
ArrayList<index_t> old_from_new;
old_from_new.Init(dataset.n_cols());
for (index_t i = 0; i < old_from_new.size(); i++) {
old_from_new[i] = i;
}
// Saving the dataset since it would be modified
// while growing the tree
Matrix new_dataset;
new_dataset.Copy(dataset);
// starting the training timer
fx_timer_start(root, "train_time");
// Growing the tree
double old_alpha = 0.0;
double alpha = dtree->Grow(new_dataset, &old_from_new);
NOTIFY("%"LI"d leaf nodes in this tree", dtree->subtree_leaves());
// // computing densities for the train points in the
// // big tree
// for (index_t i = 0; i < dataset.n_cols(); i++) {
// Vector test_p;
// dataset.MakeColumnVector(i, &test_p);
// double f = dtree->ComputeValue(test_p);
// printf("%lg ", f);
// } // end for
// printf("\n");
// sequential pruning and saving the alpha vals and the
// values of c_t^2*r_t
std::vector<std::pair<double, double> > pruned_sequence;
while (dtree->subtree_leaves() > 1) {
std::pair<double, double> tree_seq (old_alpha,
-1.0 * dtree->subtree_leaves_error());
pruned_sequence.push_back(tree_seq);
old_alpha = alpha;
alpha = dtree->PruneAndUpdate(old_alpha);
DEBUG_ASSERT_MSG((alpha < DBL_MAX)||(dtree->subtree_leaves() == 1),
"old_alpha:%lg, alpha:%lg, tree size:%"LI"d",
old_alpha, alpha, dtree->subtree_leaves());
DEBUG_ASSERT(alpha > old_alpha);
} // end while
std::pair<double, double> tree_seq (old_alpha,
-1.0 * dtree->subtree_leaves_error());
pruned_sequence.push_back(tree_seq);
NOTIFY("%"LI"d trees in the sequence, max_alpha:%lg.\n",
(index_t) pruned_sequence.size(), old_alpha);
// cross-validation here
index_t folds = fx_param_int(root, "folds", 10);
NOTIFY("Starting %"LI"d-fold Cross validation", folds);
// Permute the dataset once just for keeps
Matrix pdata;
// PermuteMatrix(dataset, &pdata);
pdata.Copy(dataset);
// pdata.PrintDebug("Per");
index_t test_size = dataset.n_cols() / folds;
// Go through each fold
for (index_t fold = 0; fold < folds; fold++) {
// NOTIFY("Fold %"LI"d...", fold+1);
// break up data into train and test set
Matrix test;
index_t start = fold * test_size,
end = min ((fold + 1) * test_size,dataset.n_cols());
pdata.MakeColumnSlice(start, end - start, &test);
Matrix train;
train.Init(pdata.n_rows(), pdata.n_cols() - (end - start));
index_t k = 0;
for (index_t j = 0; j < pdata.n_cols(); j++) {
if (j < start || j >= end) {
Vector temp_vec;
pdata.MakeColumnVector(j, &temp_vec);
train.CopyVectorToColumn(k++, temp_vec);
} // end if
} // end for
DEBUG_ASSERT(k == train.n_cols());
// go through the motions
ArrayList<double> max_vals_cv, min_vals_cv;
max_vals_cv.Init(train.n_rows());
min_vals_cv.Init(train.n_rows());
Matrix temp_t;
la::TransposeInit(train, &temp_t);
for (index_t i = 0; i < temp_t.n_cols(); i++) {
Vector dim_vals;
temp_t.MakeColumnVector(i, &dim_vals);
std::vector<double> dim_vals_vec(dim_vals.ptr(),
dim_vals.ptr()
+ temp_t.n_rows());
sort(dim_vals_vec.begin(), dim_vals_vec.end());
min_vals_cv[i] = *(dim_vals_vec.begin());
max_vals_cv[i] = *(dim_vals_vec.end() -1);
} // end for
// Initializing the tree
DTree *dtree_cv = new DTree();
dtree_cv->Init(max_vals_cv, min_vals_cv, train.n_cols());
// Getting ready to grow the tree
ArrayList<index_t> old_from_new_cv;
old_from_new_cv.Init(train.n_cols());
for (index_t i = 0; i < old_from_new_cv.size(); i++) {
old_from_new_cv[i] = i;
}
// Growing the tree
old_alpha = 0.0;
alpha = dtree_cv->Grow(train, &old_from_new_cv);
// sequential pruning with all the values of available
// alphas and adding values for test values
std::vector<std::pair<double, double> >::iterator it;
for (it = pruned_sequence.begin();
it < pruned_sequence.end() -2; ++it) {
// compute test values for this state of the tree
double val_cv = 0.0;
for (index_t i = 0; i < test.n_cols(); i++) {
Vector test_point;
test.MakeColumnVector(i, &test_point);
val_cv += dtree_cv->ComputeValue(test_point);
}
// update the cv error value
it->second = it-> second - 2.0 * val_cv / (double) dataset.n_cols();
// getting the new alpha value and pruning accordingly
old_alpha = sqrt(((it+1)->first) * ((it+2)->first));
alpha = dtree_cv->PruneAndUpdate(old_alpha);
} // end for
// compute test values for this state of the tree
double val_cv = 0.0;
for (index_t i = 0; i < test.n_cols(); i++) {
Vector test_point;
test.MakeColumnVector(i, &test_point);
val_cv += dtree_cv->ComputeValue(test_point);
}
// update the cv error value
it->second = it->second - 2.0 * val_cv / (double) dataset.n_cols();
} // end for
double optimal_alpha = -1.0, best_cv_error = DBL_MAX;
std::vector<std::pair<double, double> >::iterator it;
for (it = pruned_sequence.begin();
it < pruned_sequence.end() -1; ++it) {
if (it->second < best_cv_error) {
best_cv_error = it->second;
optimal_alpha = it->first;
} // end if
} // end for
// stopping the training timer
fx_timer_stop(root, "train_time");
// Initializing the tree
DTree *dtree_opt = new DTree();
dtree_opt->Init(max_vals, min_vals, dataset.n_cols());
// Getting ready to grow the tree
for (index_t i = 0; i < old_from_new.size(); i++) {
old_from_new[i] = i;
}
// Saving the dataset since it would be modified
// while growing the tree
new_dataset.Destruct();
new_dataset.Copy(dataset);
// Growing the tree
old_alpha = 0.0;
alpha = dtree_opt->Grow(new_dataset, &old_from_new);
NOTIFY("%"LI"d leaf nodes in this tree\n opt_alpha:%lg",
dtree_opt->subtree_leaves(), optimal_alpha);
while (old_alpha < optimal_alpha) {
old_alpha = alpha;
alpha = dtree_opt->PruneAndUpdate(old_alpha);
DEBUG_ASSERT_MSG((alpha < DBL_MAX)||(dtree->subtree_leaves() == 1),
"old_alpha:%lg, alpha:%lg, tree size:%"LI"d",
old_alpha, alpha, dtree->subtree_leaves());
DEBUG_ASSERT(alpha > old_alpha);
} // end while
// Pruning with optimal alpha
NOTIFY("%"LI"d leaf nodes in this tree", dtree_opt->subtree_leaves());
if (fx_param_bool(root, "print_tree", false)) {
dtree_opt->WriteTree(0);
printf("\n");fflush(NULL);
}
// // computing densities for the train points in the
// // optimal tree
// // starting the test timer
fx_timer_start(root, "test_time");
// for (index_t i = 0; i < dataset.n_cols(); i++) {
// Vector test_p;
// dataset.MakeColumnVector(i, &test_p);
// double f = dtree_opt->ComputeValue(test_p);
// printf("%lg\n", f);
// } // end for
// // printf("\n");
// fflush(NULL);
fx_timer_stop(root, "test_time");
// // outputting the optimal tree
// std::string output_file
// = fx_param_str(root, "treee_file", "output.txt");
fx_param_bool(root, "fx/silent", 0);
fx_done(root);
}
void PermuteMatrix(const Matrix& input, Matrix *output) {
ArrayList<index_t> perm_array;
index_t size = input.n_cols();
Matrix perm_mat;
perm_mat.Init(size, size);
perm_mat.SetAll(0.0);
srand( time(NULL));
math::MakeRandomPermutation(size, &perm_array);
for(index_t i = 0; i < size; i++) {
perm_mat.set(perm_array[i], i, 1.0);
}
la::MulInit(input, perm_mat, output);
return;
}