<jupyter_start><jupyter_text>POC - Automatic Classification Of Textual Occurrences With MultiClass Classification<NAME> | Data & B.I Analyst | Machine Learning Analyst | MCP<jupyter_code># Setup
!pip install -q wordcloud
import wordcloud

import nltk
nltk.download('stopwords')
# libraries
import pandas as pd
import numpy as np
import re

from nltk.corpus import stopwords
from unicodedata import normalize

from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import confusion_matrix,classification_report
from sklearn.feature_extraction.text import  TfidfTransformer

import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('white')
%matplotlib inline

# "error", "ignore", "always", "default", "module" or "once"
import warnings
warnings.filterwarnings('ignore', category=DeprecationWarning)<jupyter_output>/usr/local/lib/python3.6/dist-packages/statsmodels/tools/_testing.py:19: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.
  import pandas.util.testing as tm<jupyter_text>Informations:1.   The data for training, are occurrences of customers who were attended by the support team between the years 2018 and 20192.   The test data, are occurrences of customers who were attended by the support team in the year 2020<jupyter_code># Import training data with data between 2018 and 2019
df_training = pd.read_csv('sample_data/data_train.csv',
                          sep=';',
                          encoding='latin-1')

# Import for testing. These data are from the year 2020
df_test = pd.read_csv('sample_data/data_test.csv',
                      sep=';',
                      encoding='latin-1')
# rename columns
columnsName = ['OccurrenceNumber','Occurrence','Date','IdProcess','Process','IdSolicitation','Solicitation']
df_training.columns=columnsName
# show structure from dataframe
df_training.shape
# Checking the dataframe index
df_training.index
# Checking the data types
df_training.dtypes
# Checking the dataframe info
df_training.info()
# Checking null values
df_training.isna().sum()
# Checking the dataframe structure 
df_training.head(2)
# Create of a new column to add the total character of each occurrence
df_training['CharacterQtd'] = df_training['Occurrence'].apply(len)
# Checks the maximum character values
df_training[['CharacterQtd']].max()
# Show data
df_training[df_training['CharacterQtd'] == 2298][['OccurrenceNumber','Process','Solicitation']].iloc[0]<jupyter_output><empty_output><jupyter_text>Graph Showing The Quantity Of Character Per Process<jupyter_code># Data per Process
df_process = df_training[['Process','CharacterQtd']].drop_duplicates().groupby(
    ['Process','CharacterQtd']).head()

# Dataframe organization 
df_process = df_process.groupby(['Process']).sum().sort_values(
    by='CharacterQtd'
    ,ascending=False).reset_index()
plt.figure(figsize=(14, 5))
sns.set(style="whitegrid")
ax_process = sns.barplot(x="CharacterQtd",
                 y="Process",
                 data=df_process)
ax_process.set_title('Process Per Character Quantity');<jupyter_output><empty_output><jupyter_text>Handling Text<jupyter_code># Function to perform data cleaning
def func_HandlingText(txt):
    
    listWords = ['boa','tarde','bom','dia','noite','cliente','apólice','é',
                     'pra','att','solicita','favor','yahoo','mail','br']
    
    txt = normalize('NFKD',
                    txt.lower()).encode('ASCII','ignore').decode('ASCII')
    
    # Remove accentuation from words
    handling_text = re.sub(r'[^\w\*]',' ',str(txt))
    
    # Remove numbers
    handling_text = list([num for num in handling_text
                          if not str.isnumeric(num)])
    
    # Join to re-form the string
    handling_text = ''.join(handling_text)
    
    # Remove multiple spaces
    handling_text = re.sub(r'\s+', ' ', str(handling_text), flags=re.I)
    
    # Remove all unique characters
    handling_text = re.sub(r'\s+[a-zA-Z]\s+',' ',str(handling_text))
    
    # Remove unique characters from the beginning
    handling_text = re.sub(r'\^[a-zA-Z]\s+', ' ', str(handling_text))
    
    # Remove other unnecessary words 
    handling_text = [lst for lst in handling_text.split()
                     if lst not in listWords]
    # Remove as stopwords
    handling_text = [palavra for palavra in handling_text
                     if palavra not in stopwords.words('portuguese')]
    
    return handling_text
# Creates word column with data already processed
df_training['Words'] = df_training['Occurrence'].apply(func_HandlingText)
# Checks returns
df_training['Words'].head(2)<jupyter_output><empty_output><jupyter_text>Process textCreating a pipeline with the following steps: CountVectorizer (), TfidfTransformer (), MultinomialNB ()<jupyter_code>pipeline = Pipeline([
                     ('cv', CountVectorizer(analyzer=func_HandlingText,
                           max_df=.6,
                           min_df=5,)),  # strings to token integer counts
                     ('tfidf', TfidfTransformer()),   # integer counts to weighted TF-IDF scores
                     ('classifier', MultinomialNB()) # train on TF-IDF vectors w/ Naive Bayes classifier
                     ])<jupyter_output><empty_output><jupyter_text>Division of training and test data<jupyter_code># Division of training and test data
X = df_training['Occurrence']
y = df_training['IdProcess']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=101)
pipeline.fit(X_train,y_train)<jupyter_output><empty_output><jupyter_text>Evaluation<jupyter_code># Predictions arrays
predictions = pipeline.predict(X_test);
# Checking Confusion Matrix
print(confusion_matrix(y_test,predictions))
# Checking Classifications
print(classification_report(y_test,predictions))<jupyter_output>precision    recall  f1-score   support

           1       0.79      0.78      0.79      7435
           2       0.92      0.93      0.92     11233
           3       0.94      0.90      0.92      9302
           4       0.00      0.00      0.00        51
           5       0.86      0.91      0.89      8903

    accuracy                           0.89     36924
   macro avg       0.70      0.70      0.70     36924
weighted avg       0.89      0.89      0.89     36924<jupyter_text>Prediction with Data Test<jupyter_code># Rename columns
df_test.columns=columnsName

# Remove columns
df_test.drop(columns=['Date', 'IdSolicitation', 'Solicitation'], inplace=True)
# Performing the Analysis on All Occurrence Descriptions
x_prediction = pipeline.predict(df_test['Occurrence'])
# Column creation with the prediction result
df_test = df_test.join(pd.DataFrame(x_prediction))

# Rename Column
df_test.rename(columns={0: 'PredictionResult'}, inplace=True)

# Drop Column Occurrence
df_test.drop('Occurrence', axis=1, inplace=True)<jupyter_output><empty_output><jupyter_text>Results Validations<jupyter_code># Add the "equal" column to compare the prediction result with the value of the IdProcess column
df_test['Equals'] = np.where((df_test['IdProcess'] == df_test['PredictionResult']) , 1, 0)
# Return total rows
total_rows = df_test.shape[0]
df_test['Total'] = 1

# Sums aggregated values
agreg = df_test.groupby(['Process']).agg(sum)

# Checking hit percentage
agreg["Hit"] = round((agreg['Equals'] * 100) / agreg['Total'],2)

# Checking Percentage of error
value_error = agreg['Total'] - agreg['Equals']
agreg['Error'] = round((value_error * 100) / agreg['Total'],2)

# Dataframe organization
agreg['Process'] = agreg.index
# Initialize the matplotlib figure
f, ax = plt.subplots(figsize=(14, 5))

# Plot the agreg to correct answers
sns.set_color_codes("pastel")
sns.barplot(x="Hit", y="Process", data=agreg,
            label="Correct %", color="b")

# Plot the agreg to wrong answers
sns.set_color_codes("muted")
sns.barplot(x="Error", y="Process", data=agreg,
            label="Error %", color="b")

# Add a legend and informative axis label
ax.legend(ncol=2, loc="lower right", frameon=True)
ax.set(xlim=(0, 100), ylabel="",
       xlabel="Hit vs Error")
sns.despine(left=True, bottom=True)
ax.set_title('Percentage values between correct answers and wrong answers');<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11374182034503272, 'fraction_numerical': 0.021058893515764426, 'mean_word_length': 3.9157894736842107, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 7, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '290242', 'license': 'MIT', 'n_tokens_mistral': 2744, 'n_tokens_neox': 2585, 'n_words': 642, 'path': 'poc_nlp_multiclass_classification.ipynb', 'repo_name': 'mr-dnl/nlp-multiclass-classification', 'size': '8420'}