from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X = cancer.data
y = cancer.target


"""
Explanation: Title: Boosting a Weak Learner
Slug: weak-learners
Summary: From boosting a decision stump, it will be possible to create a strong learner
Date: 2018-02-5 13:32
Category: Machine Learning
Tags: Ensemble
Authors: Thomas Pinder
Load the data
End of explanation
"""


from sklearn.tree import DecisionTreeClassifier

def decision_stump(features, labels):
    clf = DecisionTreeClassifier(max_depth=1, random_state=123)
    clf.fit(features, labels)
    predictions = clf.predict(features)
    return predictions


"""
Explanation: Build the Decision Stump
End of explanation
"""


import numpy as np 

def get_accuracy(predictions, ground_truth):
    equality = (predictions==ground_truth)
    accuracy = np.mean(equality)
    return accuracy*100

"""
Explanation: Get an Accuracy Result
This can be done using the accuracy() function in sklearn, however, it's defined verbose here using NumPy just for completeness.
End of explanation
"""


prediction = decision_stump(X, y)
accuracy = get_accuracy(prediction, y)
print(accuracy)


"""
Explanation: Demonstrate for a single iteration
End of explanation
"""


def mistakes(predictions, ground_truth):
    equality = (prediction==ground_truth)
    misclass = np.where(equality==False)
    correct = np.where(equality==True)
    return misclass, correct

def easy_hard_split(features, labels, predictions):
    hard_index, easy_index = mistakes(predictions, labels)
    hard_X, hard_y = features[hard_index], labels[hard_index]
    easy_X, easy_y = features[easy_index], labels[easy_index]
    return hard_X, easy_X, hard_y, easy_y

hard_X, easy_X, hard_y, easy_y = easy_hard_split(X, y, prediction)


"""
Explanation: Extract Incorrect Classifications
End of explanation
"""


iterations = 1000
for i in range(iterations):
    stump = decision_stump(X, y)
    predictions = get_accuracy(stump, y)
    

"""
Explanation: Apply Boosting
End of explanation
"""


