Skip to main content
Post Closed as "Not suitable for this site" by Snowhawk, Toby Speight, toolic
deleted 2 characters in body
Source Link
Jamal
  • 34.9k
  • 13
  • 133
  • 237

(I was brought here from stackexchange.com)

For my project, I'm required to create three training datasets from a set of about 45000 elements (32000 after cleaning incomplete elements). Each line looks like this:

38, Private, 215646, HS-grad, 9, Divorced, Handlers-cleaners, Not-in-family, White, Male, 0, 0, 40, United-States, <=50K

Each line looks like this:

38, Private, 215646, HS-grad, 9, Divorced, Handlers-cleaners, Not-in-family, White, Male, 0, 0, 40, United-States, <=50K

After that, I have to pick out 20 random data points in each testing dataset (for each training set) and implement my naive bayesian classifier on each one to determine if it's a positive value (iei.e., the salary is > 50k) or a negative (iei.e., the salary is <= 50k.

My implementation is here. Basically im asking how can I pretty up the code to make it run faster when stratify sampling it).

Also, how in god's name do I classify using Naive Bayesian? I'm thinking for each point I randomly chose from the testing dataset, for each attribute, I find the number of matching points that have that attribute value in the training dataset. Then count all points with that value that succeed and then count the ones that fail. Then compute probability for that class. After I do it for each attribute,basically asking how I multiplycan pretty up the probabilities together and see which one is closercode to the probability of failure or probability of failure. Then see if my guess matches the actual resultmake it run faster when stratify sampling it.

#include <iostream> //std::cout
#include <fstream> //std::ifstream
#include <string> //std::string
#include <sstream> //std::istringstream
#include <vector> //std::vector
#include <algorithm> //std::remove
#include <ctime> //std::time

struct Person{
    int age;
    std::string workclass;
    int fnlwgt;
    std::string education;
    int educationNum;
    std::string maritalStatus;
    std::string occupation;
    std::string relationship;
    std::string race;
    std::string sex;
    int capitalGain;
    int capitalLoss;
    int hoursPerWeek;
    std::string nativeCountry;
    std::string salary;
};

std::vector<Person> testData;

//Prints data of single person
void printPerson(Person person){
    std::cout << person.age << " " << person.workclass << 
        " " << person.fnlwgt << " " << person.education << 
        " " << person.educationNum << " " << person.maritalStatus <<
        " " << person.occupation << " " << person.relationship <<
        " " << person.race << " " << person.sex << 
        " " << person.capitalGain << " " << person.capitalLoss << 
        " " << person.hoursPerWeek << " " << person.nativeCountry <<
        std::endl;
}

//Converts int to string
std::string convertInt(int x){
    std::string result;
    std::ostringstream convert;
    
    convert << x;
    result = convert.str();
    return result;
}

//Generates
int randNumGenerator(int max){
    int num = (rand() % max);
    //std::cout << num << std::endl;
    return num;
}

//Sets up all persons in data set with complete values
void setData(Person person, std::string line){
        
        line.erase(std::remove(line.begin(), line.end(), ','), line.end());
        
        std::stringstream s(line);
        std::string str;
        
        //Nominal attributes
        std::string workclass;
        std::string education;
        std::string maritalStatus;
        std::string occupation;
        std::string relationship;
        std::string race;
        std::string sex;
        std::string nativeCountry;
        
        //class label
        std::string salary;
        
        //Continuous attributes
        int age;
        std::string ageStr;
        
        
        int fnlwgt;
        std::string fnlwgtStr;

        int educationNum;
        std::string educationNumStr;

        int capitalGain;
        std::string capitalGainStr;
        
        int capitalLoss;
        std::string capitalLossStr;
        
        int hoursPerWeek;
        std::string hoursPerWeekStr;
        
        //Read in values into stringstream
        if(s >> age >> workclass >> fnlwgt >> education >> educationNum >>
            maritalStatus >> occupation >> relationship >> race >> sex >> capitalGain >>
            capitalLoss >> hoursPerWeek >> nativeCountry >> salary){
                
                //Convert ints into strings
                ageStr = convertInt(age);
                fnlwgtStr = convertInt(fnlwgt);
                educationNumStr = convertInt(educationNum);
                capitalGainStr = convertInt(capitalGain);
                capitalLossStr = convertInt(capitalLoss);
                hoursPerWeekStr = convertInt(hoursPerWeek);
                
                //Check if values are missing
                if(ageStr == "?" || workclass == "?" ||
                    fnlwgtStr == "?" || education == "?" || 
                    educationNumStr == "?" || maritalStatus == "?" ||
                    occupation == "?" || relationship == "?" ||
                    race== "?" || sex == "?" || 
                    capitalGainStr == "?" || capitalLossStr == "?" ||
                    hoursPerWeekStr == "?" || nativeCountry == "?"){
                        
                }
                else{
                    person.age = age;
                    person.workclass = workclass;
                    person.fnlwgt = fnlwgt;
                    person.education = education;
                    person.educationNum = educationNum;
                    person.maritalStatus = maritalStatus;
                    person.occupation = occupation;
                    person.relationship = relationship;
                    person.race = race;
                    person.sex = sex;
                    person.capitalGain = capitalGain;
                    person.capitalLoss = capitalLoss;
                    person.hoursPerWeek = hoursPerWeek;
                    person.nativeCountry = nativeCountry;
                    person.salary = salary;
                    testData.push_back(person);
                }
        }
        
        //printPerson(person);
}

//Sets up strata for positive values
std::vector<Person> setPositive(std::vector<Person> data){
    for(int i = 0; i < testData.size(); i++){
        if(testData[i].salary == ">50K"){
            data.push_back(testData[i]);
        }
    }
    return data;
}

//Sets up strata for negative values
std::vector<Person> setNegative(std::vector<Person> data){
    for(int i = 0; i < testData.size(); i++){
        if(testData[i].salary == "<=50K"){
            data.push_back(testData[i]);
        }
    }
    return data;
}

std::vector<Person> sample(std::vector<Person> &wholeDataSet, int percentage){
    int wholeDataSize = wholeDataSet.size();
    
    std::vector<Person> stratifiedSet;
    
    int limit = (wholeDataSize * percentage) / 100;
    
    int randNum= 0;
    
    std::vector<bool> numsUsedAlready(wholeDataSize);

    for(int i = 0; i < limit; i++){
        randNum = randNumGenerator(wholeDataSize);
        while(numsUsedAlready[randNum]){
            randNum = randNumGenerator(wholeDataSize);
        }
        numsUsedAlready[randNum] = true;
        stratifiedSet.push_back(wholeDataSet[randNum]); 
        wholeDataSet.erase(wholeDataSet.begin() + randNum);
        //std::cout << i << std::endl;
    } 
    
    //delete numsUsedAlready
    return stratifiedSet;
}

std::vector<Person> concatVectors(std::vector<Person> a, std::vector<Person> b){
    std::vector<Person> ab;
    ab.reserve(a.size() + b.size());
    ab.insert(ab.end(), a.begin(), a.end()); //Add a
    ab.insert(ab.end(), b.begin(), b.end()); //Add b
    return ab;
}

bool classifier(Person person){
    
}

float naiveBayesian(std::vector<Person> trainingSet, std::vector<Person> testingSet){
    float accuracy = 0;
    int randNum = 0;
    
    std::vector<Person> sampleSet;
    std::vector<bool> numsUsedAlready(testingSet.size());
    
    for(int i = 0; i < 20; i++){
        randNum = randNumGenerator(testingSet.size());
        while(numsUsedAlready[randNum]){
            randNum = randNumGenerator(testingSet.size());
        }
        numsUsedAlready[randNum] = true;
        sampleSet.push_back(testingSet[randNum]);
    }
    
    float ageProb;
    float workclassProb;
    float fnlwgtProb;
    float educationProb;
    float educationNumProb;
    std::string maritalStatus;
    std::string occupation;
    std::string relationship;
    std::string race;
    std::string sex;
    int capitalGain;
    int capitalLoss;
    int hoursPerWeek;
    std::string nativeCountry;
    std::string salary;
    
    
    bool salaryGreaterThan50k = false;
    for(int i = 0; i < sampleSet.size(); i++){
        //salaryGreaterThan50k = classifier(sampleSet[i]);
    }
    
    return accuracy;
}

void stratifiedSample(){
    srand(time(NULL)); 
    
    std::vector<Person> positiveSamples;
    std::vector<Person> negativeSamples;
    positiveSamples = setPositive(positiveSamples);
    negativeSamples = setNegative(negativeSamples);
    
    std::vector<Person> posTestingSet10 = positiveSamples;
    std::vector<Person> posTestingSet30 = positiveSamples;
    std::vector<Person> posTestingSet50 = positiveSamples;
    
    std::vector<Person> negTestingSet10 = negativeSamples;
    std::vector<Person> negTestingSet30 = negativeSamples;
    std::vector<Person> negTestingSet50 = negativeSamples;
    
    std::vector<Person> posStratifiedSet_10;
    std::vector<Person> posTesting_10;
    std::vector<Person> negStratifiedSet_10;
    
    std::vector<Person> posStratifiedSet_30;
    std::vector<Person> negStratifiedSet_30;
    
    std::vector<Person> posStratifiedSet_50;
    std::vector<Person> negStratifiedSet_50;
    
    std::vector<Person> stratifiedSet_10;
    std::vector<Person> stratifiedSet_30;
    std::vector<Person> stratifiedSet_50;
    
    std::vector<Person> testingSet_10;
    std::vector<Person> testingSet_30;
    std::vector<Person> testingSet_50;
    

    posStratifiedSet_10 = sample(posTestingSet10, 10);
    //std::cout << "size of stratified " << posStratifiedSet_10.size() << " size of testing set10 " << posTestingSet10.size() << std::endl;
    
    negStratifiedSet_10 = sample(negTestingSet10, 10);
    std::cout << "Done w/ 10" << std::endl;
    
    posStratifiedSet_30 = sample(posTestingSet30, 30);
    negStratifiedSet_30 = sample(negTestingSet30, 30);
    std::cout << "Done w/ 30" << std::endl;
    
    posStratifiedSet_50 = sample(posTestingSet50, 50);
    negStratifiedSet_50 = sample(negTestingSet50, 50);
    std::cout << "Done w/ 50" << std::endl;

    stratifiedSet_10 = concatVectors(posStratifiedSet_10, negStratifiedSet_10);
    stratifiedSet_30 = concatVectors(posStratifiedSet_30, negStratifiedSet_30);
    stratifiedSet_50 = concatVectors(posStratifiedSet_50, negStratifiedSet_50);
    
    testingSet_10 = concatVectors(posTestingSet10, negTestingSet10);
    testingSet_30 = concatVectors(posTestingSet30, negTestingSet30);
    testingSet_50 = concatVectors(posTestingSet50, negTestingSet50);

    //std::cout << "size10: " << stratifiedSet_10.size() << " testingSet10: " << testingSet_10.size() << std::endl;
    float accuracy10 = 0;
    float accuracy30 = 0;
    float accuracy50 = 0;
    
    accuracy10 = naiveBayesian(stratifiedSet_10, testingSet_10);
 

}

//Reads the file
void readInputFile(std::ifstream &file){
    std::string line;
    while(getline(file,line)){
        Person person;
        setData(person, line);
    }
}

//Prints the usage string
void usageString(){
    std::cout << "Usage: myProgram.exe <input_file>" << std::endl;
}


int main(int argc, char** argv){
    const char *inputfile;
    
    if (argc < 2){
        usageString();
        return EXIT_FAILURE;
    }
    else{
        inputfile = argv[1];
    }
    
    std::ifstream input(inputfile);
    if(!input.is_open()){
        std::cerr << "Error: Data file doesn't exist" << std::endl;
        return EXIT_FAILURE;
    }
    
    readInputFile(input);
    stratifiedSample();
    return 1;
}

Also, how do I classify using Naive Bayesian? I'm thinking for each point I randomly chose from the testing dataset, and for each attribute, I find the number of matching points that have that attribute value in the training dataset. Then count all points with that value that succeed and then count the ones that fail. Then compute probability for that class. After I do it for each attribute, I multiply the probabilities together and see which one is closer to the probability of failure or probability of failure. Then see if my guess matches the actual result.

#include <iostream> //std::cout
#include <fstream> //std::ifstream
#include <string> //std::string
#include <sstream> //std::istringstream
#include <vector> //std::vector
#include <algorithm> //std::remove
#include <ctime> //std::time

struct Person{
    int age;
    std::string workclass;
    int fnlwgt;
    std::string education;
    int educationNum;
    std::string maritalStatus;
    std::string occupation;
    std::string relationship;
    std::string race;
    std::string sex;
    int capitalGain;
    int capitalLoss;
    int hoursPerWeek;
    std::string nativeCountry;
    std::string salary;
};

std::vector<Person> testData;

//Prints data of single person
void printPerson(Person person){
    std::cout << person.age << " " << person.workclass << 
        " " << person.fnlwgt << " " << person.education << 
        " " << person.educationNum << " " << person.maritalStatus <<
        " " << person.occupation << " " << person.relationship <<
        " " << person.race << " " << person.sex << 
        " " << person.capitalGain << " " << person.capitalLoss << 
        " " << person.hoursPerWeek << " " << person.nativeCountry <<
        std::endl;
}

//Converts int to string
std::string convertInt(int x){
    std::string result;
    std::ostringstream convert;
    
    convert << x;
    result = convert.str();
    return result;
}

//Generates
int randNumGenerator(int max){
    int num = (rand() % max);
    //std::cout << num << std::endl;
    return num;
}

//Sets up all persons in data set with complete values
void setData(Person person, std::string line){
        
        line.erase(std::remove(line.begin(), line.end(), ','), line.end());
        
        std::stringstream s(line);
        std::string str;
        
        //Nominal attributes
        std::string workclass;
        std::string education;
        std::string maritalStatus;
        std::string occupation;
        std::string relationship;
        std::string race;
        std::string sex;
        std::string nativeCountry;
        
        //class label
        std::string salary;
        
        //Continuous attributes
        int age;
        std::string ageStr;
        
        
        int fnlwgt;
        std::string fnlwgtStr;

        int educationNum;
        std::string educationNumStr;

        int capitalGain;
        std::string capitalGainStr;
        
        int capitalLoss;
        std::string capitalLossStr;
        
        int hoursPerWeek;
        std::string hoursPerWeekStr;
        
        //Read in values into stringstream
        if(s >> age >> workclass >> fnlwgt >> education >> educationNum >>
            maritalStatus >> occupation >> relationship >> race >> sex >> capitalGain >>
            capitalLoss >> hoursPerWeek >> nativeCountry >> salary){
                
                //Convert ints into strings
                ageStr = convertInt(age);
                fnlwgtStr = convertInt(fnlwgt);
                educationNumStr = convertInt(educationNum);
                capitalGainStr = convertInt(capitalGain);
                capitalLossStr = convertInt(capitalLoss);
                hoursPerWeekStr = convertInt(hoursPerWeek);
                
                //Check if values are missing
                if(ageStr == "?" || workclass == "?" ||
                    fnlwgtStr == "?" || education == "?" || 
                    educationNumStr == "?" || maritalStatus == "?" ||
                    occupation == "?" || relationship == "?" ||
                    race== "?" || sex == "?" || 
                    capitalGainStr == "?" || capitalLossStr == "?" ||
                    hoursPerWeekStr == "?" || nativeCountry == "?"){
                        
                }
                else{
                    person.age = age;
                    person.workclass = workclass;
                    person.fnlwgt = fnlwgt;
                    person.education = education;
                    person.educationNum = educationNum;
                    person.maritalStatus = maritalStatus;
                    person.occupation = occupation;
                    person.relationship = relationship;
                    person.race = race;
                    person.sex = sex;
                    person.capitalGain = capitalGain;
                    person.capitalLoss = capitalLoss;
                    person.hoursPerWeek = hoursPerWeek;
                    person.nativeCountry = nativeCountry;
                    person.salary = salary;
                    testData.push_back(person);
                }
        }
        
        //printPerson(person);
}

//Sets up strata for positive values
std::vector<Person> setPositive(std::vector<Person> data){
    for(int i = 0; i < testData.size(); i++){
        if(testData[i].salary == ">50K"){
            data.push_back(testData[i]);
        }
    }
    return data;
}

//Sets up strata for negative values
std::vector<Person> setNegative(std::vector<Person> data){
    for(int i = 0; i < testData.size(); i++){
        if(testData[i].salary == "<=50K"){
            data.push_back(testData[i]);
        }
    }
    return data;
}

std::vector<Person> sample(std::vector<Person> &wholeDataSet, int percentage){
    int wholeDataSize = wholeDataSet.size();
    
    std::vector<Person> stratifiedSet;
    
    int limit = (wholeDataSize * percentage) / 100;
    
    int randNum= 0;
    
    std::vector<bool> numsUsedAlready(wholeDataSize);

    for(int i = 0; i < limit; i++){
        randNum = randNumGenerator(wholeDataSize);
        while(numsUsedAlready[randNum]){
            randNum = randNumGenerator(wholeDataSize);
        }
        numsUsedAlready[randNum] = true;
        stratifiedSet.push_back(wholeDataSet[randNum]); 
        wholeDataSet.erase(wholeDataSet.begin() + randNum);
        //std::cout << i << std::endl;
    } 
    
    //delete numsUsedAlready
    return stratifiedSet;
}

std::vector<Person> concatVectors(std::vector<Person> a, std::vector<Person> b){
    std::vector<Person> ab;
    ab.reserve(a.size() + b.size());
    ab.insert(ab.end(), a.begin(), a.end()); //Add a
    ab.insert(ab.end(), b.begin(), b.end()); //Add b
    return ab;
}

bool classifier(Person person){
    
}

float naiveBayesian(std::vector<Person> trainingSet, std::vector<Person> testingSet){
    float accuracy = 0;
    int randNum = 0;
    
    std::vector<Person> sampleSet;
    std::vector<bool> numsUsedAlready(testingSet.size());
    
    for(int i = 0; i < 20; i++){
        randNum = randNumGenerator(testingSet.size());
        while(numsUsedAlready[randNum]){
            randNum = randNumGenerator(testingSet.size());
        }
        numsUsedAlready[randNum] = true;
        sampleSet.push_back(testingSet[randNum]);
    }
    
    float ageProb;
    float workclassProb;
    float fnlwgtProb;
    float educationProb;
    float educationNumProb;
    std::string maritalStatus;
    std::string occupation;
    std::string relationship;
    std::string race;
    std::string sex;
    int capitalGain;
    int capitalLoss;
    int hoursPerWeek;
    std::string nativeCountry;
    std::string salary;
    
    
    bool salaryGreaterThan50k = false;
    for(int i = 0; i < sampleSet.size(); i++){
        //salaryGreaterThan50k = classifier(sampleSet[i]);
    }
    
    return accuracy;
}

void stratifiedSample(){
    srand(time(NULL)); 
    
    std::vector<Person> positiveSamples;
    std::vector<Person> negativeSamples;
    positiveSamples = setPositive(positiveSamples);
    negativeSamples = setNegative(negativeSamples);
    
    std::vector<Person> posTestingSet10 = positiveSamples;
    std::vector<Person> posTestingSet30 = positiveSamples;
    std::vector<Person> posTestingSet50 = positiveSamples;
    
    std::vector<Person> negTestingSet10 = negativeSamples;
    std::vector<Person> negTestingSet30 = negativeSamples;
    std::vector<Person> negTestingSet50 = negativeSamples;
    
    std::vector<Person> posStratifiedSet_10;
    std::vector<Person> posTesting_10;
    std::vector<Person> negStratifiedSet_10;
    
    std::vector<Person> posStratifiedSet_30;
    std::vector<Person> negStratifiedSet_30;
    
    std::vector<Person> posStratifiedSet_50;
    std::vector<Person> negStratifiedSet_50;
    
    std::vector<Person> stratifiedSet_10;
    std::vector<Person> stratifiedSet_30;
    std::vector<Person> stratifiedSet_50;
    
    std::vector<Person> testingSet_10;
    std::vector<Person> testingSet_30;
    std::vector<Person> testingSet_50;
    

    posStratifiedSet_10 = sample(posTestingSet10, 10);
    //std::cout << "size of stratified " << posStratifiedSet_10.size() << " size of testing set10 " << posTestingSet10.size() << std::endl;
    
    negStratifiedSet_10 = sample(negTestingSet10, 10);
    std::cout << "Done w/ 10" << std::endl;
    
    posStratifiedSet_30 = sample(posTestingSet30, 30);
    negStratifiedSet_30 = sample(negTestingSet30, 30);
    std::cout << "Done w/ 30" << std::endl;
    
    posStratifiedSet_50 = sample(posTestingSet50, 50);
    negStratifiedSet_50 = sample(negTestingSet50, 50);
    std::cout << "Done w/ 50" << std::endl;

    stratifiedSet_10 = concatVectors(posStratifiedSet_10, negStratifiedSet_10);
    stratifiedSet_30 = concatVectors(posStratifiedSet_30, negStratifiedSet_30);
    stratifiedSet_50 = concatVectors(posStratifiedSet_50, negStratifiedSet_50);
    
    testingSet_10 = concatVectors(posTestingSet10, negTestingSet10);
    testingSet_30 = concatVectors(posTestingSet30, negTestingSet30);
    testingSet_50 = concatVectors(posTestingSet50, negTestingSet50);

    //std::cout << "size10: " << stratifiedSet_10.size() << " testingSet10: " << testingSet_10.size() << std::endl;
    float accuracy10 = 0;
    float accuracy30 = 0;
    float accuracy50 = 0;
    
    accuracy10 = naiveBayesian(stratifiedSet_10, testingSet_10);
 

}

//Reads the file
void readInputFile(std::ifstream &file){
    std::string line;
    while(getline(file,line)){
        Person person;
        setData(person, line);
    }
}

//Prints the usage string
void usageString(){
    std::cout << "Usage: myProgram.exe <input_file>" << std::endl;
}


int main(int argc, char** argv){
    const char *inputfile;
    
    if (argc < 2){
        usageString();
        return EXIT_FAILURE;
    }
    else{
        inputfile = argv[1];
    }
    
    std::ifstream input(inputfile);
    if(!input.is_open()){
        std::cerr << "Error: Data file doesn't exist" << std::endl;
        return EXIT_FAILURE;
    }
    
    readInputFile(input);
    stratifiedSample();
    return 1;
}

(I was brought here from stackexchange.com)

For my project, I'm required to create three training datasets from a set of about 45000 elements (32000 after cleaning incomplete elements). Each line looks like this:

38, Private, 215646, HS-grad, 9, Divorced, Handlers-cleaners, Not-in-family, White, Male, 0, 0, 40, United-States, <=50K

After that, I have to pick out 20 random data points in each testing dataset (for each training set) and implement my naive bayesian classifier on each one to determine if it's a positive value (ie, the salary is > 50k) or a negative (ie, the salary is <= 50k.

My implementation is here. Basically im asking how can I pretty up the code to make it run faster when stratify sampling it.

Also, how in god's name do I classify using Naive Bayesian? I'm thinking for each point I randomly chose from the testing dataset, for each attribute, I find the number of matching points that have that attribute value in the training dataset. Then count all points with that value that succeed and then count the ones that fail. Then compute probability for that class. After I do it for each attribute, I multiply the probabilities together and see which one is closer to the probability of failure or probability of failure. Then see if my guess matches the actual result.

#include <iostream> //std::cout
#include <fstream> //std::ifstream
#include <string> //std::string
#include <sstream> //std::istringstream
#include <vector> //std::vector
#include <algorithm> //std::remove
#include <ctime> //std::time

struct Person{
    int age;
    std::string workclass;
    int fnlwgt;
    std::string education;
    int educationNum;
    std::string maritalStatus;
    std::string occupation;
    std::string relationship;
    std::string race;
    std::string sex;
    int capitalGain;
    int capitalLoss;
    int hoursPerWeek;
    std::string nativeCountry;
    std::string salary;
};

std::vector<Person> testData;

//Prints data of single person
void printPerson(Person person){
    std::cout << person.age << " " << person.workclass << 
        " " << person.fnlwgt << " " << person.education << 
        " " << person.educationNum << " " << person.maritalStatus <<
        " " << person.occupation << " " << person.relationship <<
        " " << person.race << " " << person.sex << 
        " " << person.capitalGain << " " << person.capitalLoss << 
        " " << person.hoursPerWeek << " " << person.nativeCountry <<
        std::endl;
}

//Converts int to string
std::string convertInt(int x){
    std::string result;
    std::ostringstream convert;
    
    convert << x;
    result = convert.str();
    return result;
}

//Generates
int randNumGenerator(int max){
    int num = (rand() % max);
    //std::cout << num << std::endl;
    return num;
}

//Sets up all persons in data set with complete values
void setData(Person person, std::string line){
        
        line.erase(std::remove(line.begin(), line.end(), ','), line.end());
        
        std::stringstream s(line);
        std::string str;
        
        //Nominal attributes
        std::string workclass;
        std::string education;
        std::string maritalStatus;
        std::string occupation;
        std::string relationship;
        std::string race;
        std::string sex;
        std::string nativeCountry;
        
        //class label
        std::string salary;
        
        //Continuous attributes
        int age;
        std::string ageStr;
        
        
        int fnlwgt;
        std::string fnlwgtStr;

        int educationNum;
        std::string educationNumStr;

        int capitalGain;
        std::string capitalGainStr;
        
        int capitalLoss;
        std::string capitalLossStr;
        
        int hoursPerWeek;
        std::string hoursPerWeekStr;
        
        //Read in values into stringstream
        if(s >> age >> workclass >> fnlwgt >> education >> educationNum >>
            maritalStatus >> occupation >> relationship >> race >> sex >> capitalGain >>
            capitalLoss >> hoursPerWeek >> nativeCountry >> salary){
                
                //Convert ints into strings
                ageStr = convertInt(age);
                fnlwgtStr = convertInt(fnlwgt);
                educationNumStr = convertInt(educationNum);
                capitalGainStr = convertInt(capitalGain);
                capitalLossStr = convertInt(capitalLoss);
                hoursPerWeekStr = convertInt(hoursPerWeek);
                
                //Check if values are missing
                if(ageStr == "?" || workclass == "?" ||
                    fnlwgtStr == "?" || education == "?" || 
                    educationNumStr == "?" || maritalStatus == "?" ||
                    occupation == "?" || relationship == "?" ||
                    race== "?" || sex == "?" || 
                    capitalGainStr == "?" || capitalLossStr == "?" ||
                    hoursPerWeekStr == "?" || nativeCountry == "?"){
                        
                }
                else{
                    person.age = age;
                    person.workclass = workclass;
                    person.fnlwgt = fnlwgt;
                    person.education = education;
                    person.educationNum = educationNum;
                    person.maritalStatus = maritalStatus;
                    person.occupation = occupation;
                    person.relationship = relationship;
                    person.race = race;
                    person.sex = sex;
                    person.capitalGain = capitalGain;
                    person.capitalLoss = capitalLoss;
                    person.hoursPerWeek = hoursPerWeek;
                    person.nativeCountry = nativeCountry;
                    person.salary = salary;
                    testData.push_back(person);
                }
        }
        
        //printPerson(person);
}

//Sets up strata for positive values
std::vector<Person> setPositive(std::vector<Person> data){
    for(int i = 0; i < testData.size(); i++){
        if(testData[i].salary == ">50K"){
            data.push_back(testData[i]);
        }
    }
    return data;
}

//Sets up strata for negative values
std::vector<Person> setNegative(std::vector<Person> data){
    for(int i = 0; i < testData.size(); i++){
        if(testData[i].salary == "<=50K"){
            data.push_back(testData[i]);
        }
    }
    return data;
}

std::vector<Person> sample(std::vector<Person> &wholeDataSet, int percentage){
    int wholeDataSize = wholeDataSet.size();
    
    std::vector<Person> stratifiedSet;
    
    int limit = (wholeDataSize * percentage) / 100;
    
    int randNum= 0;
    
    std::vector<bool> numsUsedAlready(wholeDataSize);

    for(int i = 0; i < limit; i++){
        randNum = randNumGenerator(wholeDataSize);
        while(numsUsedAlready[randNum]){
            randNum = randNumGenerator(wholeDataSize);
        }
        numsUsedAlready[randNum] = true;
        stratifiedSet.push_back(wholeDataSet[randNum]); 
        wholeDataSet.erase(wholeDataSet.begin() + randNum);
        //std::cout << i << std::endl;
    } 
    
    //delete numsUsedAlready
    return stratifiedSet;
}

std::vector<Person> concatVectors(std::vector<Person> a, std::vector<Person> b){
    std::vector<Person> ab;
    ab.reserve(a.size() + b.size());
    ab.insert(ab.end(), a.begin(), a.end()); //Add a
    ab.insert(ab.end(), b.begin(), b.end()); //Add b
    return ab;
}

bool classifier(Person person){
    
}

float naiveBayesian(std::vector<Person> trainingSet, std::vector<Person> testingSet){
    float accuracy = 0;
    int randNum = 0;
    
    std::vector<Person> sampleSet;
    std::vector<bool> numsUsedAlready(testingSet.size());
    
    for(int i = 0; i < 20; i++){
        randNum = randNumGenerator(testingSet.size());
        while(numsUsedAlready[randNum]){
            randNum = randNumGenerator(testingSet.size());
        }
        numsUsedAlready[randNum] = true;
        sampleSet.push_back(testingSet[randNum]);
    }
    
    float ageProb;
    float workclassProb;
    float fnlwgtProb;
    float educationProb;
    float educationNumProb;
    std::string maritalStatus;
    std::string occupation;
    std::string relationship;
    std::string race;
    std::string sex;
    int capitalGain;
    int capitalLoss;
    int hoursPerWeek;
    std::string nativeCountry;
    std::string salary;
    
    
    bool salaryGreaterThan50k = false;
    for(int i = 0; i < sampleSet.size(); i++){
        //salaryGreaterThan50k = classifier(sampleSet[i]);
    }
    
    return accuracy;
}

void stratifiedSample(){
    srand(time(NULL)); 
    
    std::vector<Person> positiveSamples;
    std::vector<Person> negativeSamples;
    positiveSamples = setPositive(positiveSamples);
    negativeSamples = setNegative(negativeSamples);
    
    std::vector<Person> posTestingSet10 = positiveSamples;
    std::vector<Person> posTestingSet30 = positiveSamples;
    std::vector<Person> posTestingSet50 = positiveSamples;
    
    std::vector<Person> negTestingSet10 = negativeSamples;
    std::vector<Person> negTestingSet30 = negativeSamples;
    std::vector<Person> negTestingSet50 = negativeSamples;
    
    std::vector<Person> posStratifiedSet_10;
    std::vector<Person> posTesting_10;
    std::vector<Person> negStratifiedSet_10;
    
    std::vector<Person> posStratifiedSet_30;
    std::vector<Person> negStratifiedSet_30;
    
    std::vector<Person> posStratifiedSet_50;
    std::vector<Person> negStratifiedSet_50;
    
    std::vector<Person> stratifiedSet_10;
    std::vector<Person> stratifiedSet_30;
    std::vector<Person> stratifiedSet_50;
    
    std::vector<Person> testingSet_10;
    std::vector<Person> testingSet_30;
    std::vector<Person> testingSet_50;
    

    posStratifiedSet_10 = sample(posTestingSet10, 10);
    //std::cout << "size of stratified " << posStratifiedSet_10.size() << " size of testing set10 " << posTestingSet10.size() << std::endl;
    
    negStratifiedSet_10 = sample(negTestingSet10, 10);
    std::cout << "Done w/ 10" << std::endl;
    
    posStratifiedSet_30 = sample(posTestingSet30, 30);
    negStratifiedSet_30 = sample(negTestingSet30, 30);
    std::cout << "Done w/ 30" << std::endl;
    
    posStratifiedSet_50 = sample(posTestingSet50, 50);
    negStratifiedSet_50 = sample(negTestingSet50, 50);
    std::cout << "Done w/ 50" << std::endl;

    stratifiedSet_10 = concatVectors(posStratifiedSet_10, negStratifiedSet_10);
    stratifiedSet_30 = concatVectors(posStratifiedSet_30, negStratifiedSet_30);
    stratifiedSet_50 = concatVectors(posStratifiedSet_50, negStratifiedSet_50);
    
    testingSet_10 = concatVectors(posTestingSet10, negTestingSet10);
    testingSet_30 = concatVectors(posTestingSet30, negTestingSet30);
    testingSet_50 = concatVectors(posTestingSet50, negTestingSet50);

    //std::cout << "size10: " << stratifiedSet_10.size() << " testingSet10: " << testingSet_10.size() << std::endl;
    float accuracy10 = 0;
    float accuracy30 = 0;
    float accuracy50 = 0;
    
    accuracy10 = naiveBayesian(stratifiedSet_10, testingSet_10);
 

}

//Reads the file
void readInputFile(std::ifstream &file){
    std::string line;
    while(getline(file,line)){
        Person person;
        setData(person, line);
    }
}

//Prints the usage string
void usageString(){
    std::cout << "Usage: myProgram.exe <input_file>" << std::endl;
}


int main(int argc, char** argv){
    const char *inputfile;
    
    if (argc < 2){
        usageString();
        return EXIT_FAILURE;
    }
    else{
        inputfile = argv[1];
    }
    
    std::ifstream input(inputfile);
    if(!input.is_open()){
        std::cerr << "Error: Data file doesn't exist" << std::endl;
        return EXIT_FAILURE;
    }
    
    readInputFile(input);
    stratifiedSample();
    return 1;
}

For my project, I'm required to create three training datasets from a set of about 45000 elements (32000 after cleaning incomplete elements).

Each line looks like this:

38, Private, 215646, HS-grad, 9, Divorced, Handlers-cleaners, Not-in-family, White, Male, 0, 0, 40, United-States, <=50K

After that, I have to pick out 20 random data points in each testing dataset (for each training set) and implement my naive bayesian classifier on each one to determine if it's a positive value (i.e., the salary is > 50k) or a negative (i.e., the salary is <= 50k).

I'm basically asking how I can pretty up the code to make it run faster when stratify sampling it.

Also, how do I classify using Naive Bayesian? I'm thinking for each point I randomly chose from the testing dataset, and for each attribute, I find the number of matching points that have that attribute value in the training dataset. Then count all points with that value that succeed and then count the ones that fail. Then compute probability for that class. After I do it for each attribute, I multiply the probabilities together and see which one is closer to the probability of failure or probability of failure. Then see if my guess matches the actual result.

#include <iostream> //std::cout
#include <fstream> //std::ifstream
#include <string> //std::string
#include <sstream> //std::istringstream
#include <vector> //std::vector
#include <algorithm> //std::remove
#include <ctime> //std::time

struct Person{
    int age;
    std::string workclass;
    int fnlwgt;
    std::string education;
    int educationNum;
    std::string maritalStatus;
    std::string occupation;
    std::string relationship;
    std::string race;
    std::string sex;
    int capitalGain;
    int capitalLoss;
    int hoursPerWeek;
    std::string nativeCountry;
    std::string salary;
};

std::vector<Person> testData;

//Prints data of single person
void printPerson(Person person){
    std::cout << person.age << " " << person.workclass << 
        " " << person.fnlwgt << " " << person.education << 
        " " << person.educationNum << " " << person.maritalStatus <<
        " " << person.occupation << " " << person.relationship <<
        " " << person.race << " " << person.sex << 
        " " << person.capitalGain << " " << person.capitalLoss << 
        " " << person.hoursPerWeek << " " << person.nativeCountry <<
        std::endl;
}

//Converts int to string
std::string convertInt(int x){
    std::string result;
    std::ostringstream convert;
    
    convert << x;
    result = convert.str();
    return result;
}

//Generates
int randNumGenerator(int max){
    int num = (rand() % max);
    //std::cout << num << std::endl;
    return num;
}

//Sets up all persons in data set with complete values
void setData(Person person, std::string line){
        
        line.erase(std::remove(line.begin(), line.end(), ','), line.end());
        
        std::stringstream s(line);
        std::string str;
        
        //Nominal attributes
        std::string workclass;
        std::string education;
        std::string maritalStatus;
        std::string occupation;
        std::string relationship;
        std::string race;
        std::string sex;
        std::string nativeCountry;
        
        //class label
        std::string salary;
        
        //Continuous attributes
        int age;
        std::string ageStr;
        
        
        int fnlwgt;
        std::string fnlwgtStr;

        int educationNum;
        std::string educationNumStr;

        int capitalGain;
        std::string capitalGainStr;
        
        int capitalLoss;
        std::string capitalLossStr;
        
        int hoursPerWeek;
        std::string hoursPerWeekStr;
        
        //Read in values into stringstream
        if(s >> age >> workclass >> fnlwgt >> education >> educationNum >>
            maritalStatus >> occupation >> relationship >> race >> sex >> capitalGain >>
            capitalLoss >> hoursPerWeek >> nativeCountry >> salary){
                
                //Convert ints into strings
                ageStr = convertInt(age);
                fnlwgtStr = convertInt(fnlwgt);
                educationNumStr = convertInt(educationNum);
                capitalGainStr = convertInt(capitalGain);
                capitalLossStr = convertInt(capitalLoss);
                hoursPerWeekStr = convertInt(hoursPerWeek);
                
                //Check if values are missing
                if(ageStr == "?" || workclass == "?" ||
                    fnlwgtStr == "?" || education == "?" || 
                    educationNumStr == "?" || maritalStatus == "?" ||
                    occupation == "?" || relationship == "?" ||
                    race== "?" || sex == "?" || 
                    capitalGainStr == "?" || capitalLossStr == "?" ||
                    hoursPerWeekStr == "?" || nativeCountry == "?"){
                        
                }
                else{
                    person.age = age;
                    person.workclass = workclass;
                    person.fnlwgt = fnlwgt;
                    person.education = education;
                    person.educationNum = educationNum;
                    person.maritalStatus = maritalStatus;
                    person.occupation = occupation;
                    person.relationship = relationship;
                    person.race = race;
                    person.sex = sex;
                    person.capitalGain = capitalGain;
                    person.capitalLoss = capitalLoss;
                    person.hoursPerWeek = hoursPerWeek;
                    person.nativeCountry = nativeCountry;
                    person.salary = salary;
                    testData.push_back(person);
                }
        }
        
        //printPerson(person);
}

//Sets up strata for positive values
std::vector<Person> setPositive(std::vector<Person> data){
    for(int i = 0; i < testData.size(); i++){
        if(testData[i].salary == ">50K"){
            data.push_back(testData[i]);
        }
    }
    return data;
}

//Sets up strata for negative values
std::vector<Person> setNegative(std::vector<Person> data){
    for(int i = 0; i < testData.size(); i++){
        if(testData[i].salary == "<=50K"){
            data.push_back(testData[i]);
        }
    }
    return data;
}

std::vector<Person> sample(std::vector<Person> &wholeDataSet, int percentage){
    int wholeDataSize = wholeDataSet.size();
    
    std::vector<Person> stratifiedSet;
    
    int limit = (wholeDataSize * percentage) / 100;
    
    int randNum= 0;
    
    std::vector<bool> numsUsedAlready(wholeDataSize);

    for(int i = 0; i < limit; i++){
        randNum = randNumGenerator(wholeDataSize);
        while(numsUsedAlready[randNum]){
            randNum = randNumGenerator(wholeDataSize);
        }
        numsUsedAlready[randNum] = true;
        stratifiedSet.push_back(wholeDataSet[randNum]); 
        wholeDataSet.erase(wholeDataSet.begin() + randNum);
        //std::cout << i << std::endl;
    } 
    
    //delete numsUsedAlready
    return stratifiedSet;
}

std::vector<Person> concatVectors(std::vector<Person> a, std::vector<Person> b){
    std::vector<Person> ab;
    ab.reserve(a.size() + b.size());
    ab.insert(ab.end(), a.begin(), a.end()); //Add a
    ab.insert(ab.end(), b.begin(), b.end()); //Add b
    return ab;
}

bool classifier(Person person){
    
}

float naiveBayesian(std::vector<Person> trainingSet, std::vector<Person> testingSet){
    float accuracy = 0;
    int randNum = 0;
    
    std::vector<Person> sampleSet;
    std::vector<bool> numsUsedAlready(testingSet.size());
    
    for(int i = 0; i < 20; i++){
        randNum = randNumGenerator(testingSet.size());
        while(numsUsedAlready[randNum]){
            randNum = randNumGenerator(testingSet.size());
        }
        numsUsedAlready[randNum] = true;
        sampleSet.push_back(testingSet[randNum]);
    }
    
    float ageProb;
    float workclassProb;
    float fnlwgtProb;
    float educationProb;
    float educationNumProb;
    std::string maritalStatus;
    std::string occupation;
    std::string relationship;
    std::string race;
    std::string sex;
    int capitalGain;
    int capitalLoss;
    int hoursPerWeek;
    std::string nativeCountry;
    std::string salary;
    
    
    bool salaryGreaterThan50k = false;
    for(int i = 0; i < sampleSet.size(); i++){
        //salaryGreaterThan50k = classifier(sampleSet[i]);
    }
    
    return accuracy;
}

void stratifiedSample(){
    srand(time(NULL)); 
    
    std::vector<Person> positiveSamples;
    std::vector<Person> negativeSamples;
    positiveSamples = setPositive(positiveSamples);
    negativeSamples = setNegative(negativeSamples);
    
    std::vector<Person> posTestingSet10 = positiveSamples;
    std::vector<Person> posTestingSet30 = positiveSamples;
    std::vector<Person> posTestingSet50 = positiveSamples;
    
    std::vector<Person> negTestingSet10 = negativeSamples;
    std::vector<Person> negTestingSet30 = negativeSamples;
    std::vector<Person> negTestingSet50 = negativeSamples;
    
    std::vector<Person> posStratifiedSet_10;
    std::vector<Person> posTesting_10;
    std::vector<Person> negStratifiedSet_10;
    
    std::vector<Person> posStratifiedSet_30;
    std::vector<Person> negStratifiedSet_30;
    
    std::vector<Person> posStratifiedSet_50;
    std::vector<Person> negStratifiedSet_50;
    
    std::vector<Person> stratifiedSet_10;
    std::vector<Person> stratifiedSet_30;
    std::vector<Person> stratifiedSet_50;
    
    std::vector<Person> testingSet_10;
    std::vector<Person> testingSet_30;
    std::vector<Person> testingSet_50;
    

    posStratifiedSet_10 = sample(posTestingSet10, 10);
    //std::cout << "size of stratified " << posStratifiedSet_10.size() << " size of testing set10 " << posTestingSet10.size() << std::endl;
    
    negStratifiedSet_10 = sample(negTestingSet10, 10);
    std::cout << "Done w/ 10" << std::endl;
    
    posStratifiedSet_30 = sample(posTestingSet30, 30);
    negStratifiedSet_30 = sample(negTestingSet30, 30);
    std::cout << "Done w/ 30" << std::endl;
    
    posStratifiedSet_50 = sample(posTestingSet50, 50);
    negStratifiedSet_50 = sample(negTestingSet50, 50);
    std::cout << "Done w/ 50" << std::endl;

    stratifiedSet_10 = concatVectors(posStratifiedSet_10, negStratifiedSet_10);
    stratifiedSet_30 = concatVectors(posStratifiedSet_30, negStratifiedSet_30);
    stratifiedSet_50 = concatVectors(posStratifiedSet_50, negStratifiedSet_50);
    
    testingSet_10 = concatVectors(posTestingSet10, negTestingSet10);
    testingSet_30 = concatVectors(posTestingSet30, negTestingSet30);
    testingSet_50 = concatVectors(posTestingSet50, negTestingSet50);

    //std::cout << "size10: " << stratifiedSet_10.size() << " testingSet10: " << testingSet_10.size() << std::endl;
    float accuracy10 = 0;
    float accuracy30 = 0;
    float accuracy50 = 0;
    
    accuracy10 = naiveBayesian(stratifiedSet_10, testingSet_10);
 

}

//Reads the file
void readInputFile(std::ifstream &file){
    std::string line;
    while(getline(file,line)){
        Person person;
        setData(person, line);
    }
}

//Prints the usage string
void usageString(){
    std::cout << "Usage: myProgram.exe <input_file>" << std::endl;
}


int main(int argc, char** argv){
    const char *inputfile;
    
    if (argc < 2){
        usageString();
        return EXIT_FAILURE;
    }
    else{
        inputfile = argv[1];
    }
    
    std::ifstream input(inputfile);
    if(!input.is_open()){
        std::cerr << "Error: Data file doesn't exist" << std::endl;
        return EXIT_FAILURE;
    }
    
    readInputFile(input);
    stratifiedSample();
    return 1;
}
Tweeted twitter.com/StackCodeReview/status/664104539147104256
Source Link

Stratified Sampling/Naive Bayesian C++

(I was brought here from stackexchange.com)

For my project, I'm required to create three training datasets from a set of about 45000 elements (32000 after cleaning incomplete elements). Each line looks like this:

38, Private, 215646, HS-grad, 9, Divorced, Handlers-cleaners, Not-in-family, White, Male, 0, 0, 40, United-States, <=50K

I'm supposed to sample them with stratified sampling and I believe my implementation is correct, however it is quite slow since it takes over 30 secs to finish just the stratified sampling part.

After that, I have to pick out 20 random data points in each testing dataset (for each training set) and implement my naive bayesian classifier on each one to determine if it's a positive value (ie, the salary is > 50k) or a negative (ie, the salary is <= 50k.

My implementation is here. Basically im asking how can I pretty up the code to make it run faster when stratify sampling it.

Also, how in god's name do I classify using Naive Bayesian? I'm thinking for each point I randomly chose from the testing dataset, for each attribute, I find the number of matching points that have that attribute value in the training dataset. Then count all points with that value that succeed and then count the ones that fail. Then compute probability for that class. After I do it for each attribute, I multiply the probabilities together and see which one is closer to the probability of failure or probability of failure. Then see if my guess matches the actual result.

#include <iostream> //std::cout
#include <fstream> //std::ifstream
#include <string> //std::string
#include <sstream> //std::istringstream
#include <vector> //std::vector
#include <algorithm> //std::remove
#include <ctime> //std::time

struct Person{
    int age;
    std::string workclass;
    int fnlwgt;
    std::string education;
    int educationNum;
    std::string maritalStatus;
    std::string occupation;
    std::string relationship;
    std::string race;
    std::string sex;
    int capitalGain;
    int capitalLoss;
    int hoursPerWeek;
    std::string nativeCountry;
    std::string salary;
};

std::vector<Person> testData;

//Prints data of single person
void printPerson(Person person){
    std::cout << person.age << " " << person.workclass << 
        " " << person.fnlwgt << " " << person.education << 
        " " << person.educationNum << " " << person.maritalStatus <<
        " " << person.occupation << " " << person.relationship <<
        " " << person.race << " " << person.sex << 
        " " << person.capitalGain << " " << person.capitalLoss << 
        " " << person.hoursPerWeek << " " << person.nativeCountry <<
        std::endl;
}

//Converts int to string
std::string convertInt(int x){
    std::string result;
    std::ostringstream convert;
    
    convert << x;
    result = convert.str();
    return result;
}

//Generates
int randNumGenerator(int max){
    int num = (rand() % max);
    //std::cout << num << std::endl;
    return num;
}

//Sets up all persons in data set with complete values
void setData(Person person, std::string line){
        
        line.erase(std::remove(line.begin(), line.end(), ','), line.end());
        
        std::stringstream s(line);
        std::string str;
        
        //Nominal attributes
        std::string workclass;
        std::string education;
        std::string maritalStatus;
        std::string occupation;
        std::string relationship;
        std::string race;
        std::string sex;
        std::string nativeCountry;
        
        //class label
        std::string salary;
        
        //Continuous attributes
        int age;
        std::string ageStr;
        
        
        int fnlwgt;
        std::string fnlwgtStr;

        int educationNum;
        std::string educationNumStr;

        int capitalGain;
        std::string capitalGainStr;
        
        int capitalLoss;
        std::string capitalLossStr;
        
        int hoursPerWeek;
        std::string hoursPerWeekStr;
        
        //Read in values into stringstream
        if(s >> age >> workclass >> fnlwgt >> education >> educationNum >>
            maritalStatus >> occupation >> relationship >> race >> sex >> capitalGain >>
            capitalLoss >> hoursPerWeek >> nativeCountry >> salary){
                
                //Convert ints into strings
                ageStr = convertInt(age);
                fnlwgtStr = convertInt(fnlwgt);
                educationNumStr = convertInt(educationNum);
                capitalGainStr = convertInt(capitalGain);
                capitalLossStr = convertInt(capitalLoss);
                hoursPerWeekStr = convertInt(hoursPerWeek);
                
                //Check if values are missing
                if(ageStr == "?" || workclass == "?" ||
                    fnlwgtStr == "?" || education == "?" || 
                    educationNumStr == "?" || maritalStatus == "?" ||
                    occupation == "?" || relationship == "?" ||
                    race== "?" || sex == "?" || 
                    capitalGainStr == "?" || capitalLossStr == "?" ||
                    hoursPerWeekStr == "?" || nativeCountry == "?"){
                        
                }
                else{
                    person.age = age;
                    person.workclass = workclass;
                    person.fnlwgt = fnlwgt;
                    person.education = education;
                    person.educationNum = educationNum;
                    person.maritalStatus = maritalStatus;
                    person.occupation = occupation;
                    person.relationship = relationship;
                    person.race = race;
                    person.sex = sex;
                    person.capitalGain = capitalGain;
                    person.capitalLoss = capitalLoss;
                    person.hoursPerWeek = hoursPerWeek;
                    person.nativeCountry = nativeCountry;
                    person.salary = salary;
                    testData.push_back(person);
                }
        }
        
        //printPerson(person);
}

//Sets up strata for positive values
std::vector<Person> setPositive(std::vector<Person> data){
    for(int i = 0; i < testData.size(); i++){
        if(testData[i].salary == ">50K"){
            data.push_back(testData[i]);
        }
    }
    return data;
}

//Sets up strata for negative values
std::vector<Person> setNegative(std::vector<Person> data){
    for(int i = 0; i < testData.size(); i++){
        if(testData[i].salary == "<=50K"){
            data.push_back(testData[i]);
        }
    }
    return data;
}

std::vector<Person> sample(std::vector<Person> &wholeDataSet, int percentage){
    int wholeDataSize = wholeDataSet.size();
    
    std::vector<Person> stratifiedSet;
    
    int limit = (wholeDataSize * percentage) / 100;
    
    int randNum= 0;
    
    std::vector<bool> numsUsedAlready(wholeDataSize);

    for(int i = 0; i < limit; i++){
        randNum = randNumGenerator(wholeDataSize);
        while(numsUsedAlready[randNum]){
            randNum = randNumGenerator(wholeDataSize);
        }
        numsUsedAlready[randNum] = true;
        stratifiedSet.push_back(wholeDataSet[randNum]); 
        wholeDataSet.erase(wholeDataSet.begin() + randNum);
        //std::cout << i << std::endl;
    } 
    
    //delete numsUsedAlready
    return stratifiedSet;
}

std::vector<Person> concatVectors(std::vector<Person> a, std::vector<Person> b){
    std::vector<Person> ab;
    ab.reserve(a.size() + b.size());
    ab.insert(ab.end(), a.begin(), a.end()); //Add a
    ab.insert(ab.end(), b.begin(), b.end()); //Add b
    return ab;
}

bool classifier(Person person){
    
}

float naiveBayesian(std::vector<Person> trainingSet, std::vector<Person> testingSet){
    float accuracy = 0;
    int randNum = 0;
    
    std::vector<Person> sampleSet;
    std::vector<bool> numsUsedAlready(testingSet.size());
    
    for(int i = 0; i < 20; i++){
        randNum = randNumGenerator(testingSet.size());
        while(numsUsedAlready[randNum]){
            randNum = randNumGenerator(testingSet.size());
        }
        numsUsedAlready[randNum] = true;
        sampleSet.push_back(testingSet[randNum]);
    }
    
    float ageProb;
    float workclassProb;
    float fnlwgtProb;
    float educationProb;
    float educationNumProb;
    std::string maritalStatus;
    std::string occupation;
    std::string relationship;
    std::string race;
    std::string sex;
    int capitalGain;
    int capitalLoss;
    int hoursPerWeek;
    std::string nativeCountry;
    std::string salary;
    
    
    bool salaryGreaterThan50k = false;
    for(int i = 0; i < sampleSet.size(); i++){
        //salaryGreaterThan50k = classifier(sampleSet[i]);
    }
    
    return accuracy;
}

void stratifiedSample(){
    srand(time(NULL)); 
    
    std::vector<Person> positiveSamples;
    std::vector<Person> negativeSamples;
    positiveSamples = setPositive(positiveSamples);
    negativeSamples = setNegative(negativeSamples);
    
    std::vector<Person> posTestingSet10 = positiveSamples;
    std::vector<Person> posTestingSet30 = positiveSamples;
    std::vector<Person> posTestingSet50 = positiveSamples;
    
    std::vector<Person> negTestingSet10 = negativeSamples;
    std::vector<Person> negTestingSet30 = negativeSamples;
    std::vector<Person> negTestingSet50 = negativeSamples;
    
    std::vector<Person> posStratifiedSet_10;
    std::vector<Person> posTesting_10;
    std::vector<Person> negStratifiedSet_10;
    
    std::vector<Person> posStratifiedSet_30;
    std::vector<Person> negStratifiedSet_30;
    
    std::vector<Person> posStratifiedSet_50;
    std::vector<Person> negStratifiedSet_50;
    
    std::vector<Person> stratifiedSet_10;
    std::vector<Person> stratifiedSet_30;
    std::vector<Person> stratifiedSet_50;
    
    std::vector<Person> testingSet_10;
    std::vector<Person> testingSet_30;
    std::vector<Person> testingSet_50;
    

    posStratifiedSet_10 = sample(posTestingSet10, 10);
    //std::cout << "size of stratified " << posStratifiedSet_10.size() << " size of testing set10 " << posTestingSet10.size() << std::endl;
    
    negStratifiedSet_10 = sample(negTestingSet10, 10);
    std::cout << "Done w/ 10" << std::endl;
    
    posStratifiedSet_30 = sample(posTestingSet30, 30);
    negStratifiedSet_30 = sample(negTestingSet30, 30);
    std::cout << "Done w/ 30" << std::endl;
    
    posStratifiedSet_50 = sample(posTestingSet50, 50);
    negStratifiedSet_50 = sample(negTestingSet50, 50);
    std::cout << "Done w/ 50" << std::endl;

    stratifiedSet_10 = concatVectors(posStratifiedSet_10, negStratifiedSet_10);
    stratifiedSet_30 = concatVectors(posStratifiedSet_30, negStratifiedSet_30);
    stratifiedSet_50 = concatVectors(posStratifiedSet_50, negStratifiedSet_50);
    
    testingSet_10 = concatVectors(posTestingSet10, negTestingSet10);
    testingSet_30 = concatVectors(posTestingSet30, negTestingSet30);
    testingSet_50 = concatVectors(posTestingSet50, negTestingSet50);

    //std::cout << "size10: " << stratifiedSet_10.size() << " testingSet10: " << testingSet_10.size() << std::endl;
    float accuracy10 = 0;
    float accuracy30 = 0;
    float accuracy50 = 0;
    
    accuracy10 = naiveBayesian(stratifiedSet_10, testingSet_10);
 

}

//Reads the file
void readInputFile(std::ifstream &file){
    std::string line;
    while(getline(file,line)){
        Person person;
        setData(person, line);
    }
}

//Prints the usage string
void usageString(){
    std::cout << "Usage: myProgram.exe <input_file>" << std::endl;
}


int main(int argc, char** argv){
    const char *inputfile;
    
    if (argc < 2){
        usageString();
        return EXIT_FAILURE;
    }
    else{
        inputfile = argv[1];
    }
    
    std::ifstream input(inputfile);
    if(!input.is_open()){
        std::cerr << "Error: Data file doesn't exist" << std::endl;
        return EXIT_FAILURE;
    }
    
    readInputFile(input);
    stratifiedSample();
    return 1;
}