from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import MultinomialNB
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import AdaBoostClassifier
from sklearn.svm import SVC
from sklearn import metrics
from sklearn import preprocessing
from sklearn.decomposition import PCA
from sklearn.cross_validation import cross_val_score
from sklearn.grid_search import GridSearchCV
import numpy as np
import operator
import re


def BasicModels(train_features, train_target, test_features, test_target):

    """
        Basic model with out using and pre-processing and use all the feature as training 
    """
    print("accuracy of different model with using any feature pre-processing")
    
    accuracy_dict = {}

    """
       KNeighborsClassifier classifier
    """
    print(" Accuracy by KNeighborsClassifier ")
    knn = KNeighborsClassifier(n_neighbors=23)
    knn.fit(train_features, train_target)
    pred = knn.predict(test_features)
    kaccuracy = metrics.accuracy_score(test_target, pred)
    accuracy_dict["knn"]=kaccuracy
    print kaccuracy

    """
       RandomForestClassifier classifier
    """
    print(" Accuracy by RandomForestClassifier ")
    Rf = RandomForestClassifier(n_estimators=200)
    Rf.fit(train_features, train_target)
    pred = Rf.predict(test_features)
    Rfaccuracy = metrics.accuracy_score(test_target, pred)
    accuracy_dict["RF"] = Rfaccuracy
    print Rfaccuracy

    """
       LogisticRegression classifier
    """
    print(" Accuracy by LogisticRegression ")
    LR = LogisticRegression(C=1e5, tol=0.001, fit_intercept=True)
    LR.fit(train_features, train_target)
    pred = LR.predict(test_features)
    LRaccuracy = metrics.accuracy_score(test_target, pred)
    accuracy_dict["LR"] = LRaccuracy
    print LRaccuracy
    
    """
       DecisionTreeClassifier classifier
    """
    print(" Accuracy by DecisionTreeClassifier ")
    DT = DecisionTreeClassifier(min_samples_split=1, random_state=0)
    DT.fit(train_features, train_target)
    pred = DT.predict(test_features)
    DTaccuracy = metrics.accuracy_score(test_target, pred)
    accuracy_dict["DT"] = DTaccuracy
    print DTaccuracy
    
    """
       MultinomialNB classifier
    """
    print(" Accuracy by MultinomialNB")
    MNB = MultinomialNB()
    MNB.fit(train_features, train_target)
    pred = MNB.predict(test_features)
    MNBaccuracy = metrics.accuracy_score(test_target, pred)
    accuracy_dict["MNB"] = MNBaccuracy
    print MNBaccuracy

    """
       GaussianNB classifier
    """
    print(" Accuracy by GaussianNB")
    GNB =  GaussianNB()
    GNB.fit(train_features, train_target)
    pred = GNB.predict(test_features)
    GNBaccuracy = metrics.accuracy_score(test_target, pred)
    accuracy_dict["GNB"] = GNBaccuracy
    print GNBaccuracy

    """
       SVM classifier
    """
    print(" Accuracy by SVM")
    svm =  SVC(gamma=2, C=1)
    svm.fit(train_features, train_target)
    pred = svm.predict(test_features)
    svmaccuracy =  metrics.accuracy_score(test_target, pred)
    accuracy_dict["SVM"] = svmaccuracy
    print svmaccuracy

    """
       AdaBoostClassifier classifier
    """
    print(" Accuracy by AdaBoostClassifier")
    ada = AdaBoostClassifier(n_estimators=200)
    ada.fit(train_features, train_target)
    pred = ada.predict(test_features)
    adaccuracy =  metrics.accuracy_score(test_target, pred)
    accuracy_dict["AdaBoost"] = adaccuracy
    print adaccuracy

    print("Till Now Maximum accuracy By")

    """
       Overall classifier
    """
    maximum = max(accuracy_dict, key=accuracy_dict.get)
    print(maximum, accuracy_dict[maximum])

    return maximum, accuracy_dict[maximum]



def pca(X): # X is the input data
    
    """
        After applying normalize_features pca will applied on dataset
        apply pca on both train_features and test_features
    """
    sklearn_pca = PCA(n_components=2)
    X_transf = sklearn_pca.fit_transform(X)
    return X_transf


def normalize_features_SD(train, test):
    
    """
        Normalizes train set features to a standard normal distribution
        (zero mean and unit variance). The same procedure is then applied
        to the test set features.
    """

    train_mean = train.mean(axis=0)
    # +0.1 to avoid division by zero in this specific case
    train_std = train.std(axis=0) + 0.1
    
    train = (train - train_mean) / train_std
    test = (test - train_mean) / train_std
    return train, test

def normalize_features(matrix_features):
    
    """
    Perform dataset normalization.
    """

    max_features = matrix_features.max(axis = 0)
    max_features = (max_features + (max_features == 0))

    return matrix_features / max_features

def Apply_Normalization(train_features, train_target, test_features, test_target):
    
    """
        Before applying pca apply some Apply_Normalization 
    """
    train_features_normal = normalize_features(train_features)
    test_features_normal = normalize_features(test_features)
    train_features_pca = pca(train_features_normal)
    test_features_pca = pca(test_features_normal)

    return (train_features_pca, train_target, test_features_pca, test_target)

def Normalizes_Featured_Model(train_features_normal, train_target, test_features_normal, test_target):

    """
        model with Normalizes feature some of the model are not work 
        as after normalize_features some data become negative
    """

    print(" Accuracy of different model with using any feature pre-processing")
    
    accuracy_dict = {}
    
    """
        KNeighborsClassifier classifier
    """
    print(" Accuracy by KNeighborsClassifier")
    knn = KNeighborsClassifier(n_neighbors=23)
    knn.fit(train_features, train_target)
    pred = knn.predict(test_features)
    kaccuracy = metrics.accuracy_score(test_target, pred)
    accuracy_dict["knn"]=kaccuracy
    print kaccuracy
    
    """
        RandomForestClassifier classifier
    """
    print(" Accuracy by RandomForestClassifier")
    Rf = RandomForestClassifier(n_estimators=200)
    Rf.fit(train_features, train_target)
    pred = Rf.predict(test_features)
    Rfaccuracy = metrics.accuracy_score(test_target, pred)
    accuracy_dict["RF"] = Rfaccuracy
    print Rfaccuracy
    
    """
        LogisticRegression classifier
    """
    print(" Accuracy by LogisticRegression")
    LR = LogisticRegression(C=1e5, tol=0.001, fit_intercept=True)
    LR.fit(train_features, train_target)
    pred = LR.predict(test_features)
    LRaccuracy = metrics.accuracy_score(test_target, pred)
    accuracy_dict["LR"] = LRaccuracy
    print LRaccuracy
    
    """
        DecisionTreeClassifier classifier
    """
    print(" Accuracy by DecisionTreeClassifier")
    DT = DecisionTreeClassifier(min_samples_split=1, random_state=0)
    DT.fit(train_features, train_target)
    pred = DT.predict(test_features)
    DTaccuracy = metrics.accuracy_score(test_target, pred)
    accuracy_dict["DT"] = DTaccuracy
    print DTaccuracy
    
    """
        SVM classifier
    """
    print(" Accuracy by SVM")
    svm =  SVC(gamma=2, C=1)
    svm.fit(train_features, train_target)
    pred = svm.predict(test_features)
    svmaccuracy =  metrics.accuracy_score(test_target, pred)
    accuracy_dict["SVM"] = svmaccuracy
    print svmaccuracy

    print("Till Now Maximum accuracy By")
    
    """
        Overall Accuracy
    """
    maximum = max(accuracy_dict, key=accuracy_dict.get)
    print(maximum, accuracy_dict[maximum])
    return maximum, accuracy_dict[maximum]


def PreprocessData(train_features,test_features):
    
    """
        Apply some preprocessing
    """
    scaler = preproc
essing.StandardScaler().fit
(train_features)
    Transformed_feature = scaler.transform(train_features)
    X_test_transformed = scaler.transform(test_features)
    return (Transformed_feature,X_test_transformed)

def Model_After_Preprocessing(train_features,train_target,test_features,test_target):
    
    """
        Model after applying some preprocessing steps