# ---
# 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
# ---

# Libraries that will be used to build the model, train and deal with the dataset must be import to be used

import scipy
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import itertools
from pandas.plotting import scatter_matrix
from sklearn import model_selection
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.metrics import f1_score
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB, MultinomialNB
from sklearn.svm import LinearSVC
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer

# The dataset that will be used in the problem must be read, in order to do it the pandas library will be used to read the CSV file

#load data GPAM_Challenge dataset 
dataset = pd.read_csv('olist_order_reviews_dataset.csv') 

# The dataset contains many rows without comments, and it needs to be treated it before using it to train the model, if not there will be "Trash" information that will not help to predict the product's rating based in blank comment.

#take the blank comments row out
dataset = dataset.dropna(subset=['review_comment_message'])

# Print information of the datased. Such as it's shape, destribution, the first 10 rows and check about the rating distribution ( amount of 1, 2, 3, 4 and 5 stars) 

print(dataset.shape)
print(dataset.head(10))
print(dataset.describe())
print(dataset.groupby('review_score').size())

# An histogram is a good way to visualize the rating distribution. How many data there are in each class (1, 2, 3, 4, 5). As the data distribution is not uniform accuracy is not a very good metric to be used when we check the histogram.

#check data distribution
dataset.hist()
plt.show()

# Extract the values of the dataset to an array

array = dataset.values

# Slice the comments value into a single array

# split comments column
X = array[:,4] 

# The rating column will be split out of the dataset array and cast into int, just to be sure

#split rating column
Y = array[:,2]
Y = Y.astype(int)

# The dataset has to be split into train and also test data. the proportion used is 30% to the test set and 70 to the training set

validation_size = 0.3

# The dataset needs to have a seed to be used when splitting the data 5 was chosen randomly 

#random seed to split the dataset
seed = 5

# The text needs to be vectorized in order to be better understood by machines, to do so a vectorized will be created and the comments (X) will fit it.
#

# Vectorizer to split text
vectorizer = TfidfVectorizer(ngram_range=(1,2))
x_vectorized = vectorizer.fit_transform(X)

# Now the splitting of the dataset will be done between training set and validation set.
# The vectorized dataset will be used the validation size will be used (30%) and the seed to split(5)

#split the datset between train and validation
X_train, X_validation, Y_train, Y_validation = model_selection.train_test_split(x_vectorized,
                                                Y,
                                                test_size=validation_size,
                                                random_state=seed)

# Just to check the size of each dataset training and validation

print("Training set has {} samples.".format(X_train.shape[0]))
print("Test set has {} samples.".format(X_validation.shape[0]))

# The models to train will be created and tested to check which one will have better metrics on the dataset 

#Linear Classifier
linearClassificer = LinearSVC()
linearClassificer.fit(X_train, Y_train)
linearPrediction = linearClassificer.predict(X_validation)

# Check the linear classifier accuracy ( it is not the recommended metric, I've tried f1-score but I got some erros and I could solve them)

print("Accuracy")
print("LinearSVC:",accuracy_score(Y_validation,linearPrediction))

#KNeighbors Classifier
classifierKNN = KNeighborsClassifier(n_neighbors=2)
classifierKNN.fit(X_train, Y_train)
predictionKNN = classifierKNN.predict(X_validation)


print("Accuracy KNN:", accuracy_score(Y_validation, predictionKNN))

#MultinomialNB Classifier
multinomialClassifier = MultinomialNB()
multinomialClassifier.fit(X_train, Y_train)
predictionMUB = multinomialClassifier.predict(X_validation)

print("MultinomialNB:",accuracy_score(Y_validation, predictionMUB))


# Once the highest accuracy comes from the Liner Classifier, it was chosen to be used 

# A function the plot the confusion matrix of the classifier needs to be built

def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)

    if normalize:
        cm = np.around((cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]),decimals=2)
        print("Normalized confusion matrix")
    else:
        print('Confusion matrix, without normalization')

    print(cm)

    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, cm[i, j],
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')



# create confusion matrix with the best model 

confusionMatrixLSVC = confusion_matrix(Y_validation, linearPrediction)

# The plotted data will be able to be analysed

# +
classes = ['1', '2', '3', '4', '5']
plt.figure()

plot_confusion_matrix(confusionMatrixLSVC,
                      classes,
                      normalize=False,
                      title='Confusion Matrix - SVM')
plt.show()
# -

# As the confusion matrix picture shows, the main diagonal shows the amount of correct predicted values the  other values are the values that were wrongly predicted
#



StarcoderdataJupyterScriptsDedupFiltered