#include <cstdlib>
#include <iostream>
#include <string>
#include <math.h>
#include "utils.h"
#include <float.h>
#include "onboostnn.h"
//using namespace std;
/* Constructor function. This sets the training example file and number
of base models. It also sets to NULL other variables to be used later. */
onboostnn::onboostnn(datafile* examples_to_train, long new_num_base_models,
int new_num_epochs, int new_num_hidden, float newlearningrate,
float newmomentumterm)
{
if (new_num_epochs > 0)
{
num_epochs = new_num_epochs;
}
else
{
num_epochs = 100;
}
if (new_num_hidden > 0)
{
num_hidden = new_num_hidden;
}
if ((examples_to_train != NULL) && (new_num_base_models > 0))
{
setup(examples_to_train, new_num_base_models, new_num_epochs,
new_num_hidden, newlearningrate, newmomentumterm);
}
else
{
training_examples = NULL;
basemodels = NULL;
lambda_correct = NULL;
lambda_wrong = NULL;
epsilons = NULL;
betas = NULL;
init_num_base_models = num_base_models = 0;
classifications = NULL;
votes = NULL;
}
}
/* Destructor function. */
onboostnn::~onboostnn()
{
delete [] basemodels;
basemodels = NULL;
delete [] lambda_correct;
lambda_correct = NULL;
delete [] lambda_wrong;
lambda_wrong = NULL;
delete [] epsilons;
epsilons = NULL;
delete [] betas;
betas = NULL;
delete [] classifications;
classifications = NULL;
delete [] votes;
votes = NULL;
}
/* set_training_example_file:
Input: datafile containing the training examples.
Output: None.
Sets the training example file data structure to point to examples_to_train.
*/
void onboostnn::set_training_example_file(datafile* examples_to_train)
{
training_examples = examples_to_train;
if (votes != NULL)
{
delete [] votes;
}
votes = new double[training_examples->NumClasses()];
}
/* setup:
Inputs: datafile data structure, number of base models to be trained.
Output: none
This function sets the training example datafile data structure to point to
examples_to_train and sets the number of base models to be trained to
new_num_base_models.
*/
void onboostnn::setup(datafile* examples_to_train, long new_num_base_models,
int new_num_epochs, int new_num_hidden,
float newlearningrate, float newmomentumterm)
{
training_examples = examples_to_train;
if (new_num_base_models > 0)
{
init_num_base_models = num_base_models = new_num_base_models;
// For the code below, see if you can just set up 'basemodels'
// as a *nnbp and then do basemodels[i] = new nnbp(blah, blah)
// for each i. This way, you can call the explicit-value
// constructor for all the base models rather than all these
// setter functions.
basemodels = new nnbp[init_num_base_models];
for (int i = 0; i < init_num_base_models; i++)
{
if (new_num_hidden > 0)
{
basemodels[i].set_num_hidden(new_num_hidden);
}
basemodels[i].set_training_file(training_examples);
if (new_num_epochs > 0)
{
basemodels[i].set_num_epochs(new_num_epochs);
}
basemodels[i].set_learning_rate(newlearningrate);
basemodels[i].set_momentum_term(newmomentumterm);
}
lambda_correct = new double[init_num_base_models];
lambda_wrong = new double[init_num_base_models];
epsilons = new double[init_num_base_models];
betas = new double[init_num_base_models];
for (int t = 0; t < init_num_base_models; t++)
{
lambda_correct[t] = 0.0;
lambda_wrong[t] = 0.0;
epsilons[t] = 0.0;
betas[t] = 0.0;
}
classifications = new ClassNo[init_num_base_models];
votes = new double[training_examples->NumClasses()];
}
else
{
std::cout << "ILLEGAL NUMBER OF BASE MODELS: "
<< new_num_base_models << "\n";
exit(1);
}
}
/* set_num_epochs: This function sets the number of epochs in the base models.
*/
void onboostnn::set_num_epochs(int new_num_epochs)
{
for (int t = 0; t < num_base_models; t++)
{
basemodels[t].set_num_epochs(new_num_epochs);
}
}
/* reset:
This function resets the data structures to make it look as though no
training was done. This means resetting the base models contained within
this ensemble. */
void onboostnn::reset()
{
for (int t = 0; t < init_num_base_models; t++)
{
basemodels[t].reset();
lambda_correct[t] = 0.0;
lambda_wrong[t] = 0.0;
epsilons[t] = 0.0;
betas[t] = 0.0;
}
num_base_models = init_num_base_models; // Forget the fact that we
// might have chosen to use fewer than the full set of base
// models.
}
// Do batch boosting with examples in datafile
// training_examples.
void onboostnn::trainbatch()
{
trainbatch(0, training_examples->NumItems());
}
// Do batch training with examples 'first' up to 'last' (these
// are indices into the trainingfile).
void onboostnn::trainbatch(long first, long last)
{
long numexamples = last-first;
long* sample = new long[numexamples];
Description* items = new Description[numexamples];
Boolean* correctp = new Boolean[numexamples];
double* weights = new double[numexamples];
// Initialize weights.
for (int j = 0; j < numexamples; j++)
{
weights[j] = 1.0;
}
// For each base model,...
for (int i = 0; i < init_num_base_models; i++)
{
/* Create training sample according to the weights. The array
'sample' contains indices into the training examples data
structure. */
sample = create_sample(sample, weights, first, last);
for (int j = 0; j < numexamples; j++)
{
// Put the jth randomly chosen sample into the items
// array.
items[j] = (*training_examples)[sample[j]];
}
// Now that the sample with replacement is ready, learn
// the next base model.
basemodels[i].trainbatch(items, numexamples);
// Now we need to adjust the weights.
// First determine which examples are being misclassified by
// the current base model and calculate lambda_wrong[i] (the sum
// of the weights of the incorrectly classified examples) and
// lambda_correct[i] (the sum of the weights of the correctly
// classified examples).
for (int j = first; j < last; j++)
{
// If the example is being classified correctly, then...
if (basemodels[i].test((*training_examples)[j]) ==
training_examples->TrueClass(j))
{
// it is classified correctly,...
correctp[j-first] = 1;
}
else
{
// else it is misclassified and its weight needs to be
// added to lambda_wrong.
correctp[j-first] = 0;
lambda_wrong[i] += weights[j-first];
}
}
// lambda_correct + lambda_wrong = numexamples. This is equivalent
// to epsilon + (1 - epsilon) = 1 from AdaBoost.
lambda_correct[i] = numexamples - lambda_wrong[i];
// The following condition is equivalent to epsilon > 1/2 in
// AdaBoost, i.e., under this condition we stop learning more
// base models.
if (lambda_wrong[i] >= numexamples / 2.0)
{
num_base_models = i; // Note that init_num_base_models (the
// number of base models allocated) is still correct.
return;
}
if (lambda_wrong[i] == 0.0)
{
// If this zero-error base model is the only one we have,
// then we should use it. Otherwise, we should not use it
// because it will get all the weight when classifying new
// examples.
if (i == 0)
{
num_base_models = 1;
return;
}
else
{
num_base_models = i;
}
}
// Now scale up the weights of misclassified examples and scale
// down the weights of correctly-classified examples. The method
// being used is equivalent to AdaBoost's method except that it
// avoids floating-point problems and does not require a separate
// normalization step, so it is more efficient.
for (int j = 0; j < numexamples; j++)
{
if (correctp[j])
{
weights[j] *= numexamples / (2.0 * lambda_correct[i]);
}
else
{
weights[j] *= numexamples / (2.0 * lambda_wrong[i]);
}
}
// This is the new weight distribution to be tried.
}
// We don't need the following data structures specific to the
// learning algorithm.
delete [] sample;
sample = NULL;
delete [] items;
items = NULL;
delete [] correctp;
correctp = NULL;
delete [] weights;
weights = NULL;
}
// Do batch training with examples 'first' up to 'last' (these
// are indices into the trainingfile)--with training file in online mode.
void onboostnn::trainonlinebatch(long first, long last)
{
long numexamples = last-first;
long* sampleindices = new long[numexamples]; // Indices into the original sample. We
// use these to create the actual training sample.
Description* origsample = new Description[numexamples]; // Original training set
Description* items = new Description[numexamples]; // Sample for current base model.
Boolean* correctp = new Boolean[numexamples];
double* weights = new double[numexamples];
// First create the original sample. We have to create it one-at-a-time because
// the training set's datafile is in online mode.
for (int j = 0; j < numexamples; j++)
{
origsample[j] = training_examples->next_example();
}
// Initialize weights.
for (int j = 0; j < numexamples; j++)
{
weights[j] = 1.0;
}
// For each base model,...
for (int i = 0; i < init_num_base_models; i++)
{
/* Create training sample according to the weights. The array
'sampleindices' contains indices into the training set given in
origsample. */
sampleindices = create_sample(sampleindices, weights, first, last);
for (int j = 0; j < numexamples; j++)
{
// Put the jth randomly chosen sample into the items
// array.
items[j] = origsample[sampleindices[j]];
}
// Now that the sample with replacement is ready, learn
// the next base model.
basemodels[i].trainbatch(items, numexamples);
// Now we need to adjust the weights.
// First determine which examples are being misclassified by
// the current base model and calculate lambda_wrong[i] (the sum
// of the weights of the incorrectly classified examples) and
// lambda_correct[i] (the sum of the weights of the correctly
// classified examples).
for (int j = first; j < last; j++)
{
// If the example is being classified correctly, then...
short numattributes = training_examples->return_num_attributes();
DiscrValue exampleclass = origsample[j][numattributes]._discr_val;
if (basemodels[i].test(origsample[j]) == exampleclass)
{
// it is classified correctly,...
correctp[j-first] = 1;
}
else
{
// else it is misclassified and its weight needs to be
// added to lambda_wrong.
correctp[j-first] = 0;
lambda_wrong[i] += weights[j-first];
}
}
// lambda_correct + lambda_wrong = numexamples. This is equivalent
// to epsilon + (1 - epsilon) = 1 from AdaBoost.
lambda_correct[i] = numexamples - lambda_wrong[i];
// The following ifdef-endif combination was set up by Nikunj Oza
// 8-2-01 to test when the first base model's performance is < 0.5.
// #ifdef NO
// The following condition is equivalent to epsilon > 1/2 in
// AdaBoost, i.e., under this condition we stop learning more
// base models.
if (lambda_wrong[i] >= numexamples / 2.0)
{
if (i == 0)
{
num_base_models = 1;
return;
}
else
{
num_base_models = i; // Note that init_num_base_models (the
// number of base models allocated) is still correct.
return;
}
}
// #endif
if (lambda_wrong[i] == 0.0)
{
// If this zero-error base model is the only one we have,
// then we should use it. Otherwise, we should not use it
// because it will get all the weight when classifying new
// examples.
if (i == 0)
{
num_base_models = 1;
return;
}
else
{
num_base_models = i;
}
}
// Now scale up the weights of misclassified examples and scale
// down the weights of correctly-classified examples. The method
// being used is equivalent to AdaBoost's method except that it
// avoids floating-point problems and does not require a separate
// normalization step, so it is more efficient.
for (int j = 0; j < numexamples; j++)
{
if (correctp[j])
{
weights[j] *= numexamples / (2.0 * lambda_correct[i]);
}
else
{
weights[j] *= numexamples / (2.0 * lambda_wrong[i]);
}
}
// This is the new weight distribution to be tried.
}
// We don't need the following data structures specific to the
// learning algorithm.
delete [] origsample;
origsample = NULL;
delete [] sampleindices;
sampleindices = NULL;
delete [] items;
items = NULL;
delete [] correctp;
correctp = NULL;
delete [] weights;
weights = NULL;
}
// Do online boosting learning with the supplied example
void onboostnn::train(Description example)
{
double lambda = 1.0;
for (int t = 0; t < num_base_models; t++)
{
// cout << " Updating base model: " << t << endl;
// Number of times example is to be included.
long k = poisson(lambda);
for (int n = 0; n < k; n++)
{
// The next line is used for weighted training of the base
// models.
// basemodels[t].train((*training_examples)[i], lambda);
basemodels[t].train(example);
}
// Check if example is classified correctly.
Boolean correctp = (basemodels[t].test(example) ==
training_examples->TrueClass(example));
// Now update the lambda_correct and lambda_wrong. Also update
// the weight of the current example.
if (correctp == 1)
{
lambda_correct[t] += lambda;
// double factor = ((i + 1.0) / (2.0 * lambda_correct[t]));
double factor = (lambda_correct[t] + lambda_wrong[t]) /
(2.0 * lambda_correct[t]);
// Since the example has been correctly classified, its
// weight should be decreased, i.e., its multiplier should
// be less than 1.0
// lambda *= factor;
// The following ifdef-endif combination was set up by Nikunj Oza
// 8-2-01 to test when the first base model's performance is < 0.5.
// #ifdef NO
if (factor < 1.0)
{
lambda *= factor;
}
else
{
lambda *= 1.0 / (2.0 * (1.0 - exp(-1.0)));
}
// #endif
}
else
{
lambda_wrong[t] += lambda;
// double factor = ((i + 1.0) / (2.0 * lambda_wrong[t]));
double factor = (lambda_correct[t] + lambda_wrong[t]) /
(2.0 * lambda_wrong[t]);
// Since the example has been misclassified, its weight
// should be increased, i.e., its multiplier should be
// greater than 1.0.
// lambda *= factor;
// The following ifdef-endif combination was set up by Nikunj Oza
// 8-2-01 to test when the first base model's performance is < 0.5.
// #ifdef NO
if (factor > 1.0)
{
lambda *= factor;
}
else
{
lambda *= 1.0 / (2.0 * exp(-1.0));
}
// #endif
}
}
}
// Do online boosting on the training set in the datafile
//'training_examples.'
void onboostnn::train()
{
train(0, training_examples->NumItems());
}
// Do online boosting on the training set in the datafile
// 'training_examples.' (from 'first' up to 'last,' but not including
// 'last.')
void onboostnn::train(long first, long last)
{
for (int i = first; i < last; i++)
{
// cout << "Learning example: " << i << endl;
// Set initial weight.
double lambda = 1.0;
for (int t = 0; t < num_base_models; t++)
{
// cout << " Updating base model: " << t << endl;
// Number of times example is to be included.
long k = poisson(lambda);
for (int n = 0; n < k; n++)
{
// The next line is used for weighted training of the base
// models.
// basemodels[t].train((*training_examples)[i], lambda);
basemodels[t].train((*training_examples)[i]);
}
// Check if example is classified correctly.
Boolean correctp = (basemodels[t].test((*training_examples)[i]) ==
training_examples->TrueClass(i));
// Now update the lambda_correct and lambda_wrong. Also update
// the weight of the current example.
if (correctp == 1)
{
lambda_correct[t] += lambda;
// double factor = ((i + 1.0) / (2.0 * lambda_correct[t]));
double factor = (lambda_correct[t] + lambda_wrong[t]) /
(2.0 * lambda_correct[t]);
// Since the example has been correctly classified, its
// weight should be decreased, i.e., its multiplier should
// be less than 1.0
if (factor < 1.0)
{
lambda *= factor;
}
else
{
lambda *= 1.0 / (2.0 * (1.0 - exp(-1.0)));
}
}
else
{
lambda_wrong[t] += lambda;
// double factor = ((i + 1.0) / (2.0 * lambda_wrong[t]));
double factor = (lambda_correct[t] + lambda_wrong[t]) /
(2.0 * lambda_wrong[t]);
// Since the example has been misclassified, its weight
// should be increased, i.e., its multiplier should be
// greater than 1.0.
if (factor > 1.0)
{
lambda *= factor;
}
else
{
lambda *= 1.0 / (2.0 * exp(-1.0));
}
}
}
}
}
/* This version of train calculates the errors of each online-updated base model on
all the training examples seen earlier and returns these in one file per base model. This
is to see how "stable" the base models are.
*/
void onboostnn::traintest(long first, long last)
{
std::vector< std::vector<double> > bmc(num_base_models, std::vector<double>(last-first, 0.0));
std::vector< std::vector<double> > oberror(num_base_models, std::vector<double>(last-first, 0.0));
std::vector< std::vector<double> > onlineerror(num_base_models, std::vector<double>(last-first, 0.0));
for (int i = first; i < last; i++)
{
// cout << "Learning example: " << i << endl;
// Set initial weight.
double lambda = 1.0;
for (int t = 0; t < num_base_models; t++)
{
// cout << " Updating base model: " << t << endl;
// Number of times example is to be included.
long k = poisson(lambda);
for (int n = 0; n < k; n++)
{
// The next line is used for weighted training of the base
// models.
// basemodels[t].train((*training_examples)[i], lambda);
basemodels[t].train((*training_examples)[i]);
}
// Check if example is classified correctly.
Boolean correctp = (basemodels[t].test((*training_examples)[i]) ==
training_examples->TrueClass(i));
// Now update the lambda_correct and lambda_wrong. Also update
// the weight of the current example.
if (correctp == 1)
{
lambda_correct[t] += lambda;
// double factor = ((i + 1.0) / (2.0 * lambda_correct[t]));
double factor = (lambda_correct[t] + lambda_wrong[t]) /
(2.0 * lambda_correct[t]);
// Since the example has been correctly classified, its
// weight should be decreased, i.e., its multiplier should
// be less than 1.0
if (factor < 1.0)
{
lambda *= factor;
}
else
{
lambda *= 1.0 / (2.0 * (1.0 - exp(-1.0)));
}
}
else
{
lambda_wrong[t] += lambda;
// double factor = ((i + 1.0) / (2.0 * lambda_wrong[t]));
double factor = (lambda_correct[t] + lambda_wrong[t]) /
(2.0 * lambda_wrong[t]);
// Since the example has been misclassified, its weight
// should be increased, i.e., its multiplier should be
// greater than 1.0.
if (factor > 1.0)
{
lambda *= factor;
}
else
{
lambda *= 1.0 / (2.0 * exp(-1.0));
}
}
// We will calculate the "online-batch" error (the error on all past training
// examples of the latest online base model.
// We will also update the bmc (base model classification error) here.
// Now, go through the previously-seen examples and test the base model
// on each of them.
for (int j = first; j <= i; j++)
{
Boolean correctp = (basemodels[t].test((*training_examples)[j]) ==
training_examples->TrueClass(j));
if (correctp == 0)
{
oberror[t][i] += 1.0;
}
else
{
bmc[t][j] += 1.0;
}
}
// Now divide by the number of examples seen earlier.
oberror[t][i] /= (i+1)-first;
// Calculate the online error.
onlineerror[t][i] = lambda_wrong[t] / (lambda_correct[t] + lambda_wrong[t]);
}
}
// Normalize bmc by dividing by the number of base models that have been evaluated
// on example j.
for (int t = 0; t < num_base_models; t++)
{
for (int j = first; j < last; j++)
{
bmc[t][j] /= (last-j);
}
}
// Open the file where the classification results are to be placed.
char basemodelnum[100];
for (int t = 0; t < num_base_models; t++)
{
sprintf(basemodelnum, "%d\0", t+1);
std::string baseclassesfilename = "classifications";
baseclassesfilename = baseclassesfilename + basemodelnum;
// Stupid additional code required for this to work under GCC.
// GCC has an obviously incorrect implementation of the string library.
// I.e., the function string::data() is supposed to return a char* version of
// the string, but it instead nondeterministically returns some corrupted version
// of the string. For this reason, we have to create the char* versions manually.
char* bcfchars = new char[baseclassesfilename.size()+1];
for (int m = 0; m < baseclassesfilename.size(); m++)
{
bcfchars[m] = baseclassesfilename[m];
}
bcfchars[baseclassesfilename.size()] = '\0';
// End of code needed to spoonfeed GNU C++.
std::ofstream baseclasses(bcfchars, ios::app);
//baseclasses.seekp(0,ios::end);
delete [] bcfchars;
for (int j = first; j < last; j++)
{
baseclasses << bmc[t][j] << " " << oberror[t][j] << " " << onlineerror[t][j] << "\n";
}
baseclasses.close();
}
}
// Do online boosting on the training set in the datafile
// 'training_examples.' drawn one-at-a-time (from 'first' up to 'last,'
// but not including 'last.')
void onboostnn::train2(long first, long last)
{
for (int i = first; i < last; i++)
{
Description Item = training_examples->next_example();
// cout << "Learning example: " << i << endl;
// Set initial weight.
double lambda = 1.0;
for (int t = 0; t < num_base_models; t++)
{
// cout << " Updating base model: " << t << endl;
// Number of times example is to be included.
long k = poisson(lambda);
for (int n = 0; n < k; n++)
{
// The next line is used for weighted training of the base
// models.
// basemodels[t].train((*training_examples)[i], lambda);
basemodels[t].train(Item);
}
// Check if example is classified correctly.
Boolean correctp = (basemodels[t].test(Item) ==
training_examples->TrueClass(Item));
// Now update the lambda_correct and lambda_wrong. Also update
// the weight of the current example.
if (correctp == 1)
{
lambda_correct[t] += lambda;
// double factor = ((i + 1.0) / (2.0 * lambda_correct[t]));
double factor = (lambda_correct[t] + lambda_wrong[t]) /
(2.0 * lambda_correct[t]);
// Since the example has been correctly classified, its
// weight should be decreased, i.e., its multiplier should
// be less than 1.0
if (factor < 1.0)
{
lambda *= factor;
}
else
{
lambda *= 1.0 / (2.0 * (1.0 - exp(-1.0)));
}
}
else
{
lambda_wrong[t] += lambda;
// double factor = ((i + 1.0) / (2.0 * lambda_wrong[t]));
double factor = (lambda_correct[t] + lambda_wrong[t]) /
(2.0 * lambda_wrong[t]);
// Since the example has been misclassified, its weight
// should be increased, i.e., its multiplier should be
// greater than 1.0.
if (factor > 1.0)
{
lambda *= factor;
}
else
{
lambda *= 1.0 / (2.0 * exp(-1.0));
}
}
}
}
}
// Test the example 'instance' using the learned boosted ensemble.
ClassNo onboostnn::test(Description instance)
{
return test(instance, num_base_models);
}
// Test the example 'instance' using the first 'use_base_models' number
// of base models from the learned boosted ensemble.
ClassNo onboostnn::test(Description instance, long use_base_models)
{
// Classify the instance using each base model.
// Recall that 'classifications' contains each base model's
// classification of the instance.
for (int t = 0; t < use_base_models; t++)
{
classifications[t] = basemodels[t].test(instance);
}
// Initialize the weighted votes for each class.
// votes contains, for each class, the sum of log(1/beta) values
// by the base models that voted for that class.
for (int i = 0; i < training_examples->NumClasses(); i++)
{
votes[i] = 0.0;
}
// Calculate the epsilons and then beta values needed to weight the
// votes of each base model.
for (int t = 0; t < use_base_models; t++)
{
epsilons[t] = lambda_wrong[t] / (lambda_wrong[t] + lambda_correct[t]);
if (epsilons[t] == 1.0)
{
betas[t] = FLT_MAX; // If error is maximized, then maximize beta,
// thereby giving this base model very low weight.
}
else
{
betas[t] = epsilons[t] / (1.0 - epsilons[t]);
}
}
// The trigger is set up so that if the mth base model has an error of
// more than 0.5, we don't use it or any subsequent base models to
// classify new examples.
int trigger = 0;
// Add up the log(1/beta) values for each class.
for (int t = 0; t < use_base_models; t++)
{
// if (!((betas[t] >= 1.0) || (betas[t] == 0.0)))
// {
// votes[classifications[t]] += log(1.0 / betas[t]);
// }
// The following ifdef-endif combination was set up by Nikunj Oza
// 8-2-01 to test when the first base model's performance is < 0.5.
// #ifdef NO
if ( !((betas[t] >= 1.0) || (betas[t] == 0.0) || (trigger == 1)))
{
votes[classifications[t]] += log(1.0 / betas[t]);
}
if (betas[t] >= 1.0)
{
trigger = 1;
}
// #endif
}
int answer = argmax(votes, training_examples->NumClasses());
return answer;
}
/* create_sample:
Inputs: Array of indices (to be overwritten) into the training set, the
weights of each example (THE WEIGHTS ARE POISSON PARAMETERS, i.e., a
'sampleweight' of 1.0 corresponds to an AdaBoost weight of 1.0/n where 'n'
is the number of training examples), and the indices of the first and last
examples to be considered for sampling.
Output: Array of indices into the training set. These indices correspond to
example sampled with replacement according to the supplied weights.
*/
long* onboostnn::create_sample(long* sample, double* sampleweights,
long first, long last)
{
// First we find the sum of the weights---we want to choose a random value
// from 0 to this sum and choose a training example accordingly.
double weightssum = sampleweights[0];
for (int j = 1; j < last-first; j++)
{
weightssum += sampleweights[j];
}
// For each training example, choose a random example out of the
// entire set of examples.
for (int i = 0; i < last-first; i++)
{
double randdouble = double(rand()) / RAND_MAX * weightssum;
int j = first; // Index to example.
double sumsofar = sampleweights[0];
while ((randdouble > sumsofar) && (j < last))
{
j++;
sumsofar += sampleweights[j-first];
}
// In case, due to rounding error, the weights do not quite
// add up to 1 and the random number chosen happens to be
// greater than the weight sum...
if (j >= last)
{
j = last - 1;
}
// Example j is the one to be included.
sample[i] = j;
}
return sample;
}
// The following function returns the beta value for a given base model.
double onboostnn::return_beta(int modelnum)
{
if (modelnum <= num_base_models)
{
return betas[modelnum-1];
}
else
{
std::cout << "Error in onboostnn::return_beta: The model number entered ("
<< modelnum << ") is out of range. The range is 1 to " << num_base_models
<< "\n";
exit(1);
}
}
long onboostnn::return_num_base_models()
{
return num_base_models;
}
nirav bhatt
0
Newbie Poster
Recommended Answers
Jump to PostDamn, forum rules much...did you read?
I'd suggest that you don't post that many lines of code. You are refering to line numbers, yet you didnt show line numbers....[code=language] [/code] tags would have done the job, I suggest you shrink it down to a small example that has the …
All 2 Replies
Reply to this topic
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.