# -*- coding: utf-8 -*-
"""
Created on Sun Aug 12 21:54:40 2018

@author: Code from Neighbour
"""

import numpy as np
import pandas as pd
import seaborn as sns
from io import StringIO
import matplotlib.pyplot as plt

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_extraction.text import TfidfTransformer

from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_selection import chi2


data = pd.read_csv('data.csv', header = 0);
data.head();

# select text and author column from data 
col = ['text', 'author']
df = data[col]

# assign numbers to authors [0,1,2]
df['category_id'] = df['author'].factorize()[0]
category_id_df = df[['author', 'category_id']].drop_duplicates().sort_values('category_id')
category_to_id = dict(category_id_df.values)
id_to_category = dict(category_id_df[['category_id','author']].values)
df.head
# check the doucment occurance of each other by ploting the count of document with respect to authors provided.
fig = plt.figure(figsize = (8,6))
data.groupby('author').text.count().plot.bar(ylim=0)
plt.show()

# Features genation using Term_frequency inverse document frequency calculation 
# tfidf vectorizer is calculated removing the stopwards and ngram values (1,2) which is unigram to bigram range combiniation.
# normaized to ridge regression using l2 
tfidf = TfidfVectorizer(sublinear_tf=True, min_df=5, norm='l2', encoding='latin-1', ngram_range=(1, 2), stop_words='english')
features = tfidf.fit_transform(data.text).toarray()
labels = data.author
features.shape

# features generated after performing Tf_idf which is the occurance of each word 
features
# commonly used unigram and bigram of each author
N = 2
for author, category_id in sorted(category_to_id.items()):
  features_chi2 = chi2(features, labels == category_id)
  indices = np.argsort(features_chi2[0])
  feature_names = np.array(tfidf.get_feature_names())[indices]
  unigrams = [v for v in feature_names if len(v.split(' ')) == 1]
  bigrams = [v for v in feature_names if len(v.split(' ')) == 2]
#  print("# {}:\", .format(author))
#  print("  . Most correlated unigrams:\\n. {}\".format('\\n. '.join(unigrams[-N:])))
#  print("  . Most correlated bigrams:\\n. {}\".format('\\n. '.join(bigrams[-N:])))
X_train, X_test, y_train, y_test = train_test_split(df['text'], df['author'], random_state = 0)
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(X_train)
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
clf = MultinomialNB().fit(X_train_tfidf, y_train)

# predict the text writing style 
print(clf.predict(count_vect.transform(["It never once occurred to me that the fumbling might be a mere mistake.\"])))
print(clf.predict(count_vect.transform(["How lovely is spring As we looked from Windsor Terrace on the sixteen fertile counties spread beneath, speckled by happy cottages and wealthier towns, all looked as in former years, heart cheering and fair.\"])))
print(clf.predict(count_vect.transform([\"Herbert West needed fresh bodies because his life work was the reanimation of the dead.\"])))

model = MultinomialNB()
X_train, X_test, y_train, y_test, indices_train, indices_test = train_test_split(features, labels, df.index, test_size=0.33, random_state=0)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
from sklearn.metrics import confusion_matrix
conf_mat = confusion_matrix(y_test, y_pred)
fig, ax = plt.subplots(figsize=(10,10))
sns.heatmap(conf_mat, annot=True, fmt='d',
            xticklabels=category_id_df.author.values, yticklabels=category_id_df.author.values)
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.title('Confusion Metric for Multinomial Nieve Bayes Classifer \\n')
plt.show()
