# Path: implement/decisiontreemodel.py
# class DecisionTreeModel(BaseModel):
#     def __init__(self):
#         BaseModel.__init__(self)
#         self.save_final_model = False
#         self.do_cross_val = False
#         return
#     def setClf(self):
#         min_samples_split = 10
#         self.clf = DecisionTreeRegressor(random_state=0, min_samples_split= min_samples_split)
#         return
#     def after_test(self):
#         plt.show()
#         return
#     def getTunedParamterOptions(self):
# #         tuned_parameters = [{'min_samples_split': np.arange(2, 10, 1)}]
# #         tuned_parameters = [{'min_samples_split': [5, 8,10,12]}]
#         tuned_parameters = [{'min_samples_split': [10]}]
#         return tuned_parameters
# 
# Path: evaluation/sklearnmape.py
# def mean_absolute_percentage_error_scoring(estimator, X, y):
#     y_pred = estimator.predict(X)
#     return -mean_absolute_percentage_error(y, y_pred)
# 
# Path: utility/logger_tool.py
# class Logger:
#     def __init__(self, **kwargs):
#         logging.basicConfig(**kwargs)
# 
#         root = logging.getLogger()
#         ch = logging.StreamHandler(sys.stdout)
#         root.addHandler(ch)
#         return


import sys
import os
import logging
import numpy as np
from implement.decisiontreemodel import DecisionTreeModel
from sklearn.grid_search import GridSearchCV, RandomizedSearchCV
from evaluation.sklearnmape import mean_absolute_percentage_error_scoring
from utility.logger_tool import Logger
from datetime import datetime
from knnmodel import KNNModel
from utility.duration import Duration
from svmregressionmodel import SVMRegressionModel
from randomforestmodel import RandomForestModel
from gradientboostingmodel import GrientBoostingModel
from xgboost_sklearnmodel import XGBoostSklearnModel


class TuneModel:
    """Grid search best paramers for sklearn based learning model
       Both exhaustive and random search are supported
       at the end ot he search, it will also save the model, predict on the test dataset.
    """
    def __init__(self):
        self.application_start_time = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
        logfile_name = r'logs/tunealgorithm_' +self.application_start_time + '.txt'
        _=Logger(filename=logfile_name,filemode='w',level=logging.DEBUG)
        self.durationtool = Duration()
        self.do_random_gridsearch = False
        self.n_iter_randomsearch = 2
        self.n_jobs = 1
        return
    def runGridSearch(self, model):
        logging.debug("run grid search on model: {}".format(model.__class__.__name__))
        logging.debug("cross validation strategy: {}".format(model.holdout_split))
        logging.debug("used features: {}".format(model.usedFeatures))
        logging.debug("tuned parameters: {}".format(model.getTunedParamterOptions()))
        
        features,labels,cv = model.getFeaturesLabel()
        # do grid search
        if self.do_random_gridsearch:
            estimator = RandomizedSearchCV(model.clf, model.getTunedParamterOptions(), cv=cv, n_jobs=self.n_jobs,
                       scoring=mean_absolute_percentage_error_scoring, verbose = 500, n_iter=self.n_iter_randomsearch)
        else:
            estimator = GridSearchCV(model.clf, model.getTunedParamterOptions(), cv=cv,n_jobs=-self.n_jobs, 
                                     fit_params=model.get_fit_params(),

# Path: implement/decisiontreemodel.py
# class DecisionTreeModel(BaseModel):
#     def __init__(self):
#         BaseModel.__init__(self)
#         self.save_final_model = False
#         self.do_cross_val = False
#         return
#     def setClf(self):
#         min_samples_split = 10
#         self.clf = DecisionTreeRegressor(random_state=0, min_samples_split= min_samples_split)
#         return
#     def after_test(self):
#         plt.show()
#         return
#     def getTunedParamterOptions(self):
# #         tuned_parameters = [{'min_samples_split': np.arange(2, 10, 1)}]
# #         tuned_parameters = [{'min_samples_split': [5, 8,10,12]}]
#         tuned_parameters = [{'min_samples_split': [10]}]
#         return tuned_parameters
# 
# Path: evaluation/sklearnmape.py
# def mean_absolute_percentage_error_scoring(estimator, X, y):
#     y_pred = estimator.predict(X)
#     return -mean_absolute_percentage_error(y, y_pred)
# 
# Path: utility/logger_tool.py
# class Logger:
#     def __init__(self, **kwargs):
#         logging.basicConfig(**kwargs)
# 
#         root = logging.getLogger()
#         ch = logging.StreamHandler(sys.stdout)
#         root.addHandler(ch)
#         return


# Path: implement/tunemodels.py
import sys
import os
import logging
import numpy as np
from implement.decisiontreemodel import DecisionTreeModel
from sklearn.grid_search import GridSearchCV, RandomizedSearchCV
from evaluation.sklearnmape import mean_absolute_percentage_error_scoring
from utility.logger_tool import Logger
from datetime import datetime
from knnmodel import KNNModel
from utility.duration import Duration
from svmregressionmodel import SVMRegressionModel
from randomforestmodel import RandomForestModel
from gradientboostingmodel import GrientBoostingModel
from xgboost_sklearnmodel import XGBoostSklearnModel



class TuneModel:
    """Grid search best paramers for sklearn based learning model
       Both exhaustive and random search are supported
       at the end ot he search, it will also save the model, predict on the test dataset.
    """
    def __init__(self):
        self.application_start_time = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
        logfile_name = r'logs/tunealgorithm_' +self.application_start_time + '.txt'
        _=Logger(filename=logfile_name,filemode='w',level=logging.DEBUG)
        self.durationtool = Duration()
        self.do_random_gridsearch = False
        self.n_iter_randomsearch = 2
        self.n_jobs = 1
        return
    def runGridSearch(self, model):
        logging.debug("run grid search on model: {}".format(model.__class__.__name__))
        logging.debug("cross validation strategy: {}".format(model.holdout_split))
        logging.debug("used features: {}".format(model.usedFeatures))
        logging.debug("tuned parameters: {}".format(model.getTunedParamterOptions()))
        
        features,labels,cv = model.getFeaturesLabel()
        # do grid search
        if self.do_random_gridsearch:
            estimator = RandomizedSearchCV(model.clf, model.getTunedParamterOptions(), cv=cv, n_jobs=self.n_jobs,
                       scoring=mean_absolute_percentage_error_scoring, verbose = 500, n_iter=self.n_iter_randomsearch)
        else:
            estimator = GridSearchCV(model.clf, model.getTunedParamterOptions(), cv=cv,n_jobs=-self.n_jobs, 
                                     fit_params=model.get_fit_params(),

                       scoring=mean_absolute_percentage_error_scoring, verbose = 500)