<jupyter_start><jupyter_text>Naive Bayes Classifier  Setup<jupyter_code># Data handling
import pandas as pd

# Modules for feature engineering and modelling
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.decomposition import PCA
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import plot_confusion_matrix
from sklearn.naive_bayes import BernoulliNB

# Plot
import matplotlib.pyplot as plt
plt.style.use('ggplot')<jupyter_output><empty_output><jupyter_text>Load data and merge<jupyter_code># Characters powers
powers = pd.read_csv("drive/MyDrive/Datasets/super_hero_powers.csv")

# Characters information
info = pd.read_csv(
    "drive/MyDrive/Datasets/heroes_information.csv",
    index_col=0, 
    na_values=['-', -99.0]
)

# Merge databases
data = info.merge(right=powers, how='inner', left_on='name', right_on='hero_names')
data.drop('hero_names', axis=1, inplace=True)

# Removed characters without aligment or neutral value
data = data[data['Alignment'].isin(['bad', 'good'])]<jupyter_output><empty_output><jupyter_text>Feature Engineering  Class for variable selection<jupyter_code>class ColumnSelector(BaseEstimator, TransformerMixin):
    def __init__(self, columns):
        self.columns = columns
        
    def fit(self, X, y=None):
        return self
    
    def transform(self, X):
        return X[self.columns]<jupyter_output><empty_output><jupyter_text>Define columns according to each<jupyter_code># Categorical columns name
categorical = list(info.select_dtypes('object').columns)[1:-1]

# Boolean columns name
boolean = list(powers.select_dtypes('bool').columns)<jupyter_output><empty_output><jupyter_text>Construct feature engineering graph<jupyter_code># Define categorical pipeline
cat_pipe = Pipeline(
    [('selector', ColumnSelector(categorical)),
     ('imputer', SimpleImputer(strategy='constant', fill_value='missing')),
     ('encoder', OneHotEncoder(handle_unknown='ignore', sparse=False))])

# Define boolean pipeline
bool_pipe = Pipeline(
    [('selector', ColumnSelector(boolean)),
     ('pca', PCA(n_components=0.95))])

# Fit column transformer to training data
preprocessor = FeatureUnion(
    [('categorical', cat_pipe),
     ('boolean', bool_pipe)])<jupyter_output><empty_output><jupyter_text>Transform the targetUnfornately, Sklearn pipeline doen't have support to add a transformation in the target variable like the ReshapeEndpoint in Tensorflow.<jupyter_code># Format the target variable
y = data['Alignment']
y.replace({'bad': 0, 'good': 1}, inplace=True)<jupyter_output><empty_output><jupyter_text>Model<jupyter_code># Combine categorical and numerical pipeline with the model
model = Pipeline([
    ('preprocessor', preprocessor),
    ('model', BernoulliNB(alpha=1))
])<jupyter_output><empty_output><jupyter_text>Fit and predictThe function cross_val_predict already has stratify the target variable, in other words, the function balance the target variable between the Kfolds.<jupyter_code>model.fit(data, y)
y_pred = cross_val_predict(model, data, y, cv=10)<jupyter_output><empty_output><jupyter_text>Metrics<jupyter_code># Plot confusition matrix with the results
title = 'Confusion Matrix NB Classifier'

disp = plot_confusion_matrix(
    model,
    data,
    y,
    display_labels=['good', 'bad'],
    cmap=plt.cm.Blues,
    normalize='true'
)

disp.ax_.set_title(title)

print(title)
print(disp.confusion_matrix)<jupyter_output>Confusion Matrix NB Classifier
[[0.54123711 0.45876289]
 [0.12183908 0.87816092]]
{'fraction_non_alphanumeric': 0.10947712418300654, 'fraction_numerical': 0.013888888888888888, 'mean_word_length': 6.588842975206612, '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': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '79220', 'license': 'MIT', 'n_tokens_mistral': 1223, 'n_tokens_neox': 1164, 'n_words': 270, 'path': 'notebooks/NB_Classifier.ipynb', 'repo_name': 'fernandofsilva/desafio-alelo', 'size': '3672'}