
# import packages

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

import seaborn as sns
import re
from nltk.corpus import stopwords
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.multiclass import OneVsRestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score ,confusion_matrix


# Code starts here

# load data

news = pd.read_csv(path) 


# subset  data
# selecting required cols only from DF
news = news[['TITLE','CATEGORY']]


# distribution of classes

dist = news['CATEGORY'].value_counts()
print('class distribution of target var :',dist)

# display data
print('data head :',news.head())

# Code ends here


# --------------
# Code starts here

# stopwords 
import nltk
nltk.download('stopwords')
# list of en-us stop words
stop = set(stopwords.words('english'))


# retain only alphabets
# code to retain only alphabates and remove special chars
news['TITLE']=news['TITLE'].apply(lambda x:re.sub("[^a-zA-Z]", " ",x))

# convert to lowercase and tokenize
# for converting data to lower case & splitting to words
news['TITLE']=news['TITLE'].apply(lambda x:x.lower().split())

# remove stopwords
# removing the stop words
news['TITLE']=news['TITLE'].apply(lambda x:[i for i in x if i not in stop])

# join list elements
# join list elements using join method
news['TITLE']=news['TITLE'].apply(lambda x: ' '.join(x))


# split into training and test sets
# train/test split
X_train,X_test,Y_train,Y_test = train_test_split(news["TITLE"], news["CATEGORY"], test_size = 0.2,random_state=3)

# Code ends here


# --------------
# Code starts here

# initialize count vectorizer
count_vectorizer = CountVectorizer()

# initialize tfidf vectorizer
tfidf_vectorizer = TfidfVectorizer(ngram_range=(1,3))

# fit and transform with count vectorizer
X_train_count = count_vectorizer.fit_transform(X_train)
X_test_count = count_vectorizer.transform(X_test)

# fit and transform with tfidf vectorizer
X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)
X_test_tfidf = tfidf_vectorizer.transform(X_test)
# Code ends here


# --------------
# Code starts here

# initialize multinomial naive bayes
# create CountVectorizer & TfidfVectorizer models
count_vectorizer = CountVectorizer()
tfidf_vectorizer = TfidfVectorizer(ngram_range=(1,3))

# fit on count vectorizer training data
X_train_count = count_vectorizer.fit_transform(X_train)
X_test_count = count_vectorizer.transform(X_test)

# fit on tfidf vectorizer training data
X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)
X_test_tfidf = tfidf_vectorizer.transform(X_test)

#Create MultinomialNB models
nb_1  = MultinomialNB()
nb_2  = MultinomialNB() 

# fit both the models
nb_1.fit(X_train_count,Y_train)
nb_2.fit(X_train_tfidf,Y_train)


# accuracy with count vectorizer
acc_count_nb = accuracy_score(nb_1.predict(X_test_count), Y_test)

# accuracy with tfidf vectorizer
acc_tfidf_nb = accuracy_score(nb_2.predict(X_test_tfidf), Y_test)

# display accuracies
print ('acc_count_nb - Accuracy using CountVectorizer with NB classifier :' , acc_count_nb)
print ('acc_tfidf_nb - Accuracy using TfIdfVectorizer with NB classifier ::' , acc_tfidf_nb)

# Code ends here


# --------------
import warnings
warnings.filterwarnings('ignore')

'''NOTE :- Logistic Regression can be used for binary classification but when combined with   OneVsRest classifer, it can perform multiclass classification as well.'''


# initialize logistic regression
logreg_1 = OneVsRestClassifier(LogisticRegression(random_state=10))
logreg_2 = OneVsRestClassifier(LogisticRegression(random_state=10))

# fit on count vectorizer training data
logreg_1.fit(X_train_count,Y_train)


# fit on tfidf vectorizer training data
logreg_2.fit(X_train_tfidf,Y_train)


# accuracy with count vectorizer
acc_count_logreg = accuracy_score(logreg_1.predict(X_test_count), Y_test)

# accuracy with tfidf vectorizer
acc_tfidf_logreg = accuracy_score(logreg_2.predict(X_test_tfidf), Y_test)


# display accuracies
print ('acc_count_nb - Accuracy using CountVectorizer with OneVsRestClassifier(LogisticRegression(random_state=10)) classifier :' , acc_count_nb)
print ('acc_tfidf_nb - Accuracy using TfIdfVectorizer with OneVsRestClassifier(LogisticRegression(random_state=10)) classifier:' , acc_tfidf_nb)

# Code ends here


