from evolutionary_search import EvolutionaryAlgorithmSearchCV
import sklearn.datasets
import numpy as np
import pandas as pd

data = sklearn.datasets.load_digits()
X = data["data"]
y = data["target"]

# make it a 2-class problem by only classifying the digit "5" vs the rest
y = np.array([1 if yy == 5 else 0 for yy in y])

X.shape, y.shape

from sklearn.model_selection import StratifiedKFold, GridSearchCV, RandomizedSearchCV
from sklearn.svm import SVC

"""
Explanation: Load the digits dataset and evolutionary_search
End of explanation
"""


paramgrid = {"kernel": ["rbf"],
             "C"     : np.logspace(-9, 9, num=25, base=10),
             "gamma" : np.logspace(-9, 9, num=25, base=10)}
print("Size: ", len(paramgrid["kernel"])*len(paramgrid["C"])*len(paramgrid["gamma"]))

cv = GridSearchCV(estimator=SVC(),
                  param_grid=paramgrid,
                  scoring="accuracy",
                  cv=StratifiedKFold(n_splits=2),
                  verbose=1)
%time cv.fit(X, y)

"""
Explanation: Train an SVM with RBF kernel
Using conventional GridSearchCV
Parameter grid: 625 parameter combinations
End of explanation
"""


cv.best_score_, cv.best_params_

"""
Explanation: Best score + params
End of explanation
"""


pd.DataFrame(cv.cv_results_).sort_values("mean_test_score", ascending=False).head()

"""
Explanation: An example of the "cannonical" cv_results_ table in sklearn:
End of explanation
"""


cv = RandomizedSearchCV(estimator=SVC(),
                        param_distributions=paramgrid,
                        n_iter=250,
                        scoring="accuracy",
                        cv=StratifiedKFold(n_splits=2),
                        verbose=1)
%time cv.fit(X, y)

"""
Explanation: Using RandomizedSearchCV
Same parameter space, but only test 250 random combinations.
End of explanation
"""


cv.best_score_, cv.best_params_

"""
Explanation: Best score + params
End of explanation
"""


pd.DataFrame(cv.cv_results_).sort_values("mean_test_score", ascending=False).head()

"""
Explanation: An example of the "cannonical" cv_results_ table in sklearn:
End of explanation
"""


if __name__=="__main__":
    #pool = Pool(4)
    cv = EvolutionaryAlgorithmSearchCV(estimator=SVC(),
                                       params=paramgrid,
                                       scoring="accuracy",
                                       cv=StratifiedKFold(n_splits=2),
                                       verbose=True,
                                       population_size=50,
                                       gene_mutation_prob=0.10,
                                       tournament_size=3,
                                       generations_number=10)
                                       #pmap = pool.map)
    %time cv.fit(X, y)

"""
Explanation: Using EvolutionaryAlgorithmSearchCV
Again same parameter space, optimize for 10 generations.
End of explanation
"""


cv.best_score_, cv.best_params_

"""
Explanation: Best score + params
End of explanation
"""


pd.DataFrame(cv.cv_results_).sort_values("mean_test_score", ascending=False).head()

"""
Explanation: Our cv_results_ table (note, includes all individuals with their mean, max, min, and std test score).
End of explanation
"""


