# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# ### Multi Class Text Classification for Yapı Kredi FAQs

import pandas as pd
import requests

# +
df = pd.read_csv("labeled_qnas.csv",index_col = 0)

df.head(10)
# -

col = ['Categories', 'Q&A']
df = df[col]
df.head()

df.columns = ['Category', 'QnA']
df["Category_Id"] = df['Category'].factorize()[0]

category_id_df = df[['Category', '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', 'Category']].values)

category_id_df

category_id_df.to_csv('categories.csv', index= False)

category_to_id

#df.to_csv('dfQuestions.csv', index= False)
df.head()

import matplotlib.pyplot as plt
fig = plt.figure(figsize=(15,9))
df.groupby('Category').QnA.count().plot.bar(ylim=0)
plt.show()

df.shape


# label = Q&A<br>
# target = CATEGORY

# ## Text Representation
#

def processInput(raw_inp):
    
    emptyList = []
    
    PARAMS = {'rawInput':raw_inp} 

    response = requests.get("http://localhost:8080/nlpPipeLine/singleInput", params = PARAMS)
    
    #print("Response Code: ", response.status_code,"\n")

    if response.status_code == requests.codes.ok:
        text = response.text
        input_tokens = text.rstrip("]").lstrip("[").replace('"','').split(",")
        
        return input_tokens
        
    else:
        raise Exception("WARNING EXCEPTION OCCURED processInput()")


qnas = df["QnA"]
processed_qnas = []
for q in qnas:
    temp = q.split("\n")
    raw_qna = " ".join(temp)
    processed_tokens = processInput(raw_qna)
    processed_qna = " ".join(processed_tokens)
    processed_qnas.append(processed_qna)


#Tf idf vectors bag of words model
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(sublinear_tf=True, ngram_range=(1, 2), max_df=1.0, min_df = 0, use_idf = True)
bow = vectorizer.fit_transform(processed_qnas)


bow.toarray().shape

freqs = [(word, bow.getcol(idx).sum()) for word, idx in vectorizer.vocabulary_.items()]
results = sorted (freqs, key = lambda x: -x[1])
print("Number of unique words (unigrams + bigrams) (size of dictionary):", len(vectorizer.vocabulary_.items()))

# +
feature_names = vectorizer.get_feature_names()
corpus_index = [n for n in processed_qnas]

df_tfidf = pd.DataFrame(bow.todense(), columns=feature_names)

#( num of questions , size of vocab)
print(df_tfidf.shape)

df_tfidf.head()
# -

features = bow.toarray()
labels = df.Category_Id

#The training input samples
#[n_samples, n_features]
print(features.shape)


#The target values (class labels in classification)
#[n_samples]
labels.shape

# ## Machine Learning Models

# +
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer

from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import MultinomialNB
from sklearn.svm import LinearSVC

#The fit time scales at least quadratically with the number of samples and may be impractical beyond tens of thousands of samples
from sklearn.svm import SVC

from sklearn.model_selection import cross_val_score

models = [
    RandomForestClassifier(n_estimators=200, max_depth=3, random_state=0),
    LinearSVC(),
    MultinomialNB(),
    LogisticRegression(random_state=0),
]

CV = 5
cv_df = pd.DataFrame(index=range(CV * len(models)))
entries = []
for model in models:
    model_name = model.__class__.__name__
    accuracies = cross_val_score(model, features, labels, scoring='accuracy', cv=CV)
    for fold_idx, accuracy in enumerate(accuracies):
        entries.append((model_name, fold_idx, accuracy))
        
cv_df = pd.DataFrame(entries, columns=['model_name', 'fold_idx', 'accuracy'])
# -

cv_df

# ### Accuracy Scores

cv_df.groupby('model_name').accuracy.mean()

# ### Support Vector Machines

# +
model = LinearSVC()

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=2)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
# -

import seaborn as sns

# +
from sklearn.metrics import confusion_matrix

conf_mat = confusion_matrix(y_test, y_pred)
fig, ax = plt.subplots(figsize=(15,9))
sns.heatmap(conf_mat, annot=True, fmt='d',
            xticklabels=category_id_df.Category.values, yticklabels=category_id_df.Category.values)
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.show()
# -

conf_mat

category_id_df

# +
from IPython.display import display

for predicted in category_id_df.Category_Id:
    for actual in category_id_df.Category_Id:
        if conf_mat[0].size > actual  and conf_mat[0].size > predicted:
            if predicted != actual and conf_mat[actual, predicted] >= 3:
                print("'{}' predicted as '{}' : {} examples.".format(id_to_category[actual], id_to_category[predicted], conf_mat[actual, predicted]))
                display(df.loc[indices_test[(y_test == actual) & (y_pred == predicted)]][['Category', 'QnA']])
                print('')
# -

from sklearn import metrics
##Last 2 category did not appear in the test 
print(metrics.classification_report(y_test, y_pred, target_names=df['Category'].unique()[:conf_mat[0].size]))

# ## Feature Selection <br> 

from sklearn.feature_selection import chi2
from sklearn.feature_selection import SelectKBest
import numpy as np

## Before selection
features.shape

N = 3
for category, 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(vectorizer.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(category))
    print("  . Most correlated unigrams:\n       . {}".format('\n       . '.join(unigrams[-N:])))
    print("  . Most correlated bigrams:\n       . {}".format('\n       . '.join(bigrams[-N:])))

# +
#Compare Chi-Squared Statistics
#Select 5 features with highest chi-squared statistics

chi2_selector = SelectKBest(chi2, k=150)
X_kbest = chi2_selector.fit_transform(features, labels)

# Show results
print('Original number of features:', features.shape)
print('Reduced number of features:', X_kbest.shape)
# -

# <NAME> 
# <EMAIL>
# 21.08.2019
# İstanbul/Turkey

StarcoderdataJupyterScriptsDedupFiltered