# For numerical stuff
import pandas as pd

# Plotting
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline
plt.rcParams['figure.figsize'] = (7.0, 7.0)

# Some preprocessing utilities
from sklearn.cross_validation import train_test_split # Data splitting
from sklearn.utils import shuffle

# The different classifiers
from sklearn.neighbors import KNeighborsClassifier # Nearest Neighbor  - Analogizer
from sklearn.naive_bayes import GaussianNB # Bayesian Classifier - Bayesian
from sklearn.neural_network import MLPClassifier # Neural Network - Connectionist

# Model result function
from sklearn.metrics import classification_report,accuracy_score



"""
Explanation: Build simple models to predict pulsar candidates
In this notebook we will look at building machine learning models to predict Pulsar Candidate. The data comes from Rob Lyon at Manchester. This data is publically available. For more information check out https://figshare.com/articles/HTRU2/3080389/1
Lets start with the basic imports
End of explanation
"""


data = pd.read_csv('Data/pulsar.csv')

# Show some information
print ('Dataset has %d rows and %d columns including features and labels'%(data.shape[0],data.shape[1]))

"""
Explanation: Load dataset


Data is a csv file with each column as features and rows as samples of positive and negative candidates


Class label is the last column where "1" correspondes to true pulsar candidate and "0" a false candidate
End of explanation
"""


print (data.columns.values[0:-1])

"""
Explanation: Lets print the feature names
End of explanation
"""


ax = plt.figure().gca(projection='3d')
ax.scatter3D(data['std_pf'], data['mean_dm'], data['mean_int_pf'],c=data['class'],alpha=.25)
ax.set_xlabel('std_pf')
ax.set_ylabel('mean_dm')
ax.set_zlabel('mean_int_pf')

"""
Explanation: Do a scatter plot
End of explanation
"""


# Lets shuffle the rows of the data 10 times
for i in range(10):
    data = shuffle(data)

# Now split the dataset into seperate variabels for features and labels
features = data.ix[:,data.columns != 'class'].values # All columns except class
labels = data['class'].values # Class labels

"""
Explanation: Get the features and labels
End of explanation
"""


# Do a 70 - 30 split of the whole data for training and testing
# The last argument specifies the fraction of samples for testing
train_data,test_data,train_labels,test_labels = train_test_split(features,labels,test_size=.3)
#Print some info
print ('Number of training data points : %d'%(train_data.shape[0]))
print ('Number of testing data points : %d'%(test_data.shape[0]))


"""
Explanation: Split data to training and validation sets
End of explanation
"""


# K nearest neighbor
knn = KNeighborsClassifier()
knn.fit(train_data,train_labels)

"""
Explanation: Lets do the training on different algorithms
We will be using the following algorithms


k-Nearest Neighbours (KNN) [ https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm ]


Naive Bayes Classifier [ https://en.wikipedia.org/wiki/Naive_Bayes_classifier ]


Multilayer Neural Network [ https://en.wikipedia.org/wiki/Multilayer_perceptron ] 


Lets start with default model parameters for each classifier.
Check the link above each block for function definition

Scikit KNN

http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html
End of explanation
"""


# Naive Bayes
nb = GaussianNB()
nb.fit(train_data,train_labels)

"""
Explanation: Scikit Naive Bayes

http://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.GaussianNB.html
End of explanation
"""


# MLP
mlp =  MLPClassifier(solver='sgd',hidden_layer_sizes=(5, 1))
mlp.fit(train_data,train_labels)


"""
Explanation: Scikit MLP

https://en.wikipedia.org/wiki/Multilayer_perceptron
End of explanation
"""


# Pretty function to test  a model and print accuracy score
def evaluate(model,modelname,test_data,test_labels):
    predictions = model.predict(test_data) # Do the actual prediction
    print('====================================================')
    print('Classification Report for %s'%modelname)
    print('===================================================')
    print(classification_report(test_labels,predictions,target_names=['Non Pulsar','Pulsar']))
    
    print('\n The model is %f accurate' %(accuracy_score(test_labels,predictions)*100))
    print('====================================================\n\n')
    
    
   

# Making some stuff easy
models =[knn,nb,mlp]
model_names =['KNN','Naive Bayes','Neural Network']

"""
Explanation: Fancy function to print results for model evaluation
End of explanation
"""


for i in range(0,3):
    evaluate(models[i],model_names[i],test_data,test_labels)

"""
Explanation: Now Lets test each classifier and disply their accuracy
End of explanation
"""


