<gh_stars>0
# Support Vector Machine

# importing the required libraries
import time
import argparse
import os
import sys
if sys.version_info >= (3, 0):
        import _pickle as cPickle
else:
        import cPickle
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
from data_loader import load_data 
from parameters import DATASET, TRAINING, HYPERPARAMS
from confusion_matrix import func_confusion_matrix
import matplotlib.pyplot as plt


def train(epochs=HYPERPARAMS.epochs, random_state=HYPERPARAMS.random_state, 
          kernel=HYPERPARAMS.kernel, decision_function=HYPERPARAMS.decision_function, gamma=HYPERPARAMS.gamma, train_model=True):

        print( "Loading the dataset: " + DATASET.name)
        if train_model:
                data, validation = load_data(validation=True)
        else:
                data, validation, test = load_data(validation=True, test=True)
                
        if train_model:
            # training phase
            print( "Building the model!")
            model = SVC(random_state=random_state, max_iter=epochs, kernel=kernel[0], decision_function_shape=decision_function, gamma=gamma[0])

            print( "Starting the training...")
            print( "--")
            print( "Kernel: {}".format(kernel))
            print( "Decision function: {}".format(decision_function))
            print( "Max epochs: {}".format(epochs))
            print( "Gamma: {}".format(gamma))
            print( "--")
            print( "Training samples: {}".format(len(data['Y'])))
            print( "Validation samples: {}".format(len(validation['Y'])))
            print( "--")
            
            start_time = time.time()
            model.fit(data['X'], data['Y'])
            training_time = time.time() - start_time
            print( "Training time: {0:.1f} sec".format(training_time))

            if TRAINING.save_model:
                print( "Saving the model.")
                with open(TRAINING.save_model_path, 'wb') as f:
                        cPickle.dump(model, f)

            print( "Evaluating the model!")
            svmc_error = []
            for c_value in gamma:
                model = SVC(kernel='linear', C=c_value)
                model.fit(X=data['X'], y=data['Y'])
                error = 1. - model.score(validation['X'], validation['Y'])
                svmc_error.append(error)

            plt.plot(gamma, svmc_error)
            plt.title('Best Model')
            plt.xlabel('c values')
            plt.ylabel('error')
            plt.show()
            
            print( "Evaluating the model!")
            validation_accuracy = evaluate(model, validation['X'], validation['Y'])
            print( "Validation accuracy: {0:.1f}".format(validation_accuracy*100))
            return validation_accuracy
        else:
            # Testing phase : load saved model and evaluate on test dataset
            print( "Starting the evaluation of the model...")
            print( "Loading the pretrained model.")
            if os.path.isfile(TRAINING.save_model_path):
                with open(TRAINING.save_model_path, 'rb') as f:
                        model = cPickle.load(f)
            else:
                print( "Error: File '{}' not found.".format(TRAINING.save_model_path))
                exit()

            print( "--")
            print( "Validation samples: {}".format(len(validation['Y'])))
            print( "Test samples: {}".format(len(test['Y'])))
            print( "--")
            print( "Evaluating the model!")
            start_time = time.time()
            validation_accuracy = evaluate(model, validation['X'],  validation['Y'])
            print( "Validation accuracy: {0:.1f}".format(validation_accuracy*100))
            test_accuracy = evaluate(model, test['X'], test['Y'])
            print( "Test accuracy: {0:.1f}".format(test_accuracy*100))
            print( "Evalution time: {0:.1f} sec".format(time.time() - start_time))
            return test_accuracy


def evaluate(model, X, Y):
        predicted_Y = model.predict(X)
        accuracy = accuracy_score(Y, predicted_Y)
        return accuracy


def evaluate_confusion(model, X, Y):
        predicted_Y = model.predict(X)
        conf_matrix, accuracy, recall_array, precision_array = func_confusion_matrix(Y, predicted_Y)
        return accuracy, conf_matrix


# parse arg to see if we need to launch training now or not yet
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--train", default="no", help="if 'yes', launch training from command line")
parser.add_argument("-e", "--evaluate", default="no", help="if 'yes', launch evaluation on test dataset")
parser.add_argument("-m", "--max_evals", help="Maximum number of evaluations during hyperparameters search")
args = parser.parse_args()
if args.train=="yes" or args.train=="Yes" or args.train=="YES":
        train()
if args.evaluate=="yes" or args.evaluate=="Yes" or args.evaluate=="YES":
        train(train_model=False)