From f01553051dc6e1e95924f068239c19eb03f6bfa2 Mon Sep 17 00:00:00 2001 From: Yichi Zhang Date: Mon, 2 Dec 2024 15:30:34 -0800 Subject: [PATCH 1/3] create fit_mushroom_classifier.py --- fit_mushroom_classifier.py | 112 +++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 fit_mushroom_classifier.py diff --git a/fit_mushroom_classifier.py b/fit_mushroom_classifier.py new file mode 100644 index 0000000..0b9c813 --- /dev/null +++ b/fit_mushroom_classifier.py @@ -0,0 +1,112 @@ +# fit_mushroom_classifier.py +# author: Yichi Zhang +# date: 2024-12-07 + +import click +import os +import pickle +import json +import logging +from ucimlrepo import fetch_ucirepo +import pandas as pd +import numpy as np +import pandera as pa +from pandera import Check +from deepchecks import Dataset +import matplotlib.pyplot as plt +from scipy.stats import loguniform, randint +from sklearn import set_config +from sklearn.model_selection import train_test_split +from sklearn.neighbors import KNeighborsClassifier +from sklearn.svm import SVC +from sklearn.linear_model import LogisticRegression +from sklearn.impute import SimpleImputer +from sklearn.preprocessing import QuantileTransformer,OneHotEncoder +from sklearn.compose import make_column_transformer +from sklearn.pipeline import make_pipeline +from sklearn.metrics import ConfusionMatrixDisplay, make_scorer, fbeta_score, accuracy_score, precision_score, recall_score +from sklearn.model_selection import cross_validate, cross_val_predict, GridSearchCV, RandomizedSearchCV +import warnings +warnings.filterwarnings("ignore", category=FutureWarning, module="deepchecks") + + +@click.command() +@click.option('--training-data', type=str, help="Path to training data") +@click.option('--preprocessor', type=str, help="Path to preprocessor object") +@click.option('--columns-to-drop', type=str, help="Optional: columns to drop") +@click.option('--pipeline-to', type=str, help="Path to directory where the pipeline object will be written to") +@click.option('--plot-to', type=str, help="Path to directory where the plot will be written to") +@click.option('--seed', type=int, help="Random seed", default=123) +def main(training_data, preprocessor, columns_to_drop, pipeline_to, plot_to, seed): + '''Fits a breast cancer classifier to the training data + and saves the pipeline object.''' + np.random.seed(seed) + set_config(transform_output="pandas") + + # read in data & preprocessor + mushroom_train = pd.read_csv(training_data) + mushroom_preprocessor = pickle.load(open(preprocessor, "rb")) + + if columns_to_drop: + to_drop = pd.read_csv(columns_to_drop).feats_to_drop.tolist() + mushroom_train = mushroom_train.drop(columns=to_drop) + + # create metrics + scoring_metrics = { + 'accuracy':make_scorer(accuracy_score), + 'f2_score':make_scorer(fbeta_score, beta=2, pos_label='p',average='binary') + } + cv_results = dict() + + # tune model and save results + # knn model + knn = make_pipeline(mushroom_preprocessor, KNeighborsClassifier()) + knn_grid = {'kneighborsclassifier__n_neighbors':randint(5,1000)} + cv_results['knn'] = RandomizedSearchCV( + knn, knn_grid, n_iter=5, n_jobs=-1, cv=3, + scoring=scoring_metrics, random_state=seed, + refit='f2_score' + ).fit(mushroom_train.drop(columns=["target"]), + mushroom_train["target"]) + + # logistic regression model + logreg = make_pipeline(preprocessor,LogisticRegression(max_iter=5000,random_state=seed)) + logreg_grid = {'logisticregression__C':loguniform(1e-3,1e3)} + cv_results['logreg'] = RandomizedSearchCV( + logreg,logreg_grid,n_iter=30,n_jobs=-1, + scoring=scoring_metrics,random_state=seed, + refit='f2_score' + ).fit(mushroom_train.drop(columns=["target"]), + mushroom_train["target"]) + + # svc model + svc = make_pipeline(preprocessor,SVC(random_state=seed)) + svc_grid = {'svc__C':loguniform(1e-3,1e3), + 'svc__gamma':loguniform(1e-3,1e3)} + cv_results['svc'] = RandomizedSearchCV( + svc,svc_grid,n_iter=3,n_jobs=-1,cv=3, + scoring=scoring_metrics,random_state=seed, + refit='f2_score' + ).fit(mushroom_train.drop(columns=["target"]), + mushroom_train["target"]) + + # compilng hyperparameters and scores of best models into one dataframe + cols = ['params','mean_fit_time','mean_test_accuracy','std_test_accuracy','mean_test_f2_score','std_test_f2_score'] + final_results = pd.concat( + [pd.DataFrame(result.cv_results_).query('rank_test_f2_score == 1')[cols] for _,result in cv_results.items()] + ) + final_results.index = ['KNN','Logisic Regression','SVC'] + + with open("table.pkl", "wb") as f: + pickle.dump(final_results, f) + + # save the best model + best_model = cv_results['svc'].best_estimator_ + best_model.fit(mushroom_train.drop(columns=["target"]), mushroom_train["target"]) + + with open(os.path.join(pipeline_to, "mushroom_pipeline.pickle"), 'wb') as f: + pickle.dump(best_model, f) + + +if __name__ == '__main__': + main() \ No newline at end of file From f46ae74af29ec11fa302f41adc8287f5c35b829a Mon Sep 17 00:00:00 2001 From: Yichi Zhang Date: Thu, 5 Dec 2024 21:37:50 -0800 Subject: [PATCH 2/3] create eda.py --- eda.py | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 eda.py diff --git a/eda.py b/eda.py new file mode 100644 index 0000000..095cf18 --- /dev/null +++ b/eda.py @@ -0,0 +1,71 @@ +# eda.py +# author: Yichi Zhang +# date: 2024-12-07 + +import click +import os +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + +@click.command() +@click.option('--processed-training-data', type=str, help="Path to processed training data") +@click.option('--plot-to', type=str, help="Path to directory where the plot will be written to") +def main(processed_training_data, plot_to): + '''Plots the densities of each feature in the processed training data + by class and displays them as a grid of plots. Also saves the plot.''' + + mushroom_train = pd.read_csv(processed_training_data) + + numeric_columns = mushroom_train.select_dtypes(include='number') # Select only numeric columns + + for column in numeric_columns.columns: + plt.figure(figsize=(5,5)) + plt.hist(mushroom_train[column], bins=15, edgecolor='black', alpha=0.7) + plt.title(f'Histogram of {column}') + plt.xlabel(column) + plt.ylabel('Frequency') + + plt.savefig(os.path.join(plot_to, "figures", f"histogram_{column}.png"), + dpi=300) + + + categorical_columns = mushroom_train.select_dtypes(include='object') # Select only categorical columns + + for column in categorical_columns.columns: + frequency = mushroom_train[column].value_counts() + percentage = round(mushroom_train[column].value_counts(normalize=True) * 100, 2) + freq_percent_df = pd.DataFrame({ + "Frequency": frequency, + "Percentage": percentage + }) + styled_df = freq_percent_df.style.format( + precision=2 + ).background_gradient( + subset=['Percentage'], + cmap='YlOrRd' + ) + fig, ax = plt.subplots(figsize=(6, 2)) # Adjust the figure size as needed + ax.axis('off') # Turn off the axes + + # Create a table from the DataFrame + table = ax.table( + cellText=freq_percent_df.values, + colLabels=freq_percent_df.columns, + rowLabels=freq_percent_df.index, + loc='center', + cellLoc='center' + ) + + # Style adjustments for readability + table.auto_set_font_size(False) + table.set_fontsize(10) + table.auto_set_column_width(col=list(range(len(freq_percent_df.columns)))) + + file_path = os.path.join(plot_to, "figures", f"{column}_frequency_table.png") + plt.savefig(file_path, dpi=300, bbox_inches='tight') + print(f"Saved styled table for '{column}'") + + +if __name__ == '__main__': + main() \ No newline at end of file From 997b18dd36459de19ce5131c44bc1ab7419c6727 Mon Sep 17 00:00:00 2001 From: Yichi Zhang Date: Thu, 5 Dec 2024 21:39:18 -0800 Subject: [PATCH 3/3] create scripts --- evaluate_mushroom_predictor.py | 82 + fit_mushroom_classifier.py | 42 +- .../Load_Data_and_EDA-checkpoint.html | 10308 ++++++++++++++++ .../Load_Data_and_EDA-checkpoint.ipynb | 3289 +++++ 4 files changed, 13705 insertions(+), 16 deletions(-) create mode 100644 evaluate_mushroom_predictor.py create mode 100644 notebooks/.ipynb_checkpoints/Load_Data_and_EDA-checkpoint.html create mode 100644 notebooks/.ipynb_checkpoints/Load_Data_and_EDA-checkpoint.ipynb diff --git a/evaluate_mushroom_predictor.py b/evaluate_mushroom_predictor.py new file mode 100644 index 0000000..d1ba1da --- /dev/null +++ b/evaluate_mushroom_predictor.py @@ -0,0 +1,82 @@ +# fit_mushroom_classifier.py +# author: Yichi Zhang +# date: 2024-12-07 + +import click +import os +import pickle +import json +import logging +from ucimlrepo import fetch_ucirepo +import pandas as pd +import numpy as np +import pandera as pa +from pandera import Check +from deepchecks import Dataset +import matplotlib.pyplot as plt +from scipy.stats import loguniform, randint +from sklearn import set_config +from sklearn.model_selection import train_test_split +from sklearn.neighbors import KNeighborsClassifier +from sklearn.svm import SVC +from sklearn.linear_model import LogisticRegression +from sklearn.impute import SimpleImputer +from sklearn.preprocessing import QuantileTransformer,OneHotEncoder +from sklearn.compose import make_column_transformer +from sklearn.pipeline import make_pipeline +from sklearn.metrics import ConfusionMatrixDisplay, make_scorer, fbeta_score, accuracy_score, precision_score, recall_score +from sklearn.model_selection import cross_validate, cross_val_predict, GridSearchCV, RandomizedSearchCV + +@click.command() +@click.option('--scaled-test-data', type=str, help="Path to scaled test data") +@click.option('--pipeline-from', type=str, help="Path to directory where the fit pipeline object lives") +@click.option('--results-to', type=str, help="Path to directory where the plot will be written to") +@click.option('--seed', type=int, help="Random seed", default=123) +def main(scaled_test_data, pipeline_from, results_to, seed): + '''Evaluates the breast cancer classifier on the test data + and saves the evaluation results.''' + np.random.seed(seed) + set_config(transform_output="pandas") + + mushroom_test = pd.read_csv(scaled_test_data) + + with open(pipeline_from, 'rb') as f: + mushroom_fit = pickle.load(f) + + # Compute accuracy + accuracy = mushroom_fit.score( + mushroom_test.drop(columns=["target"]), + mushroom_test["target"] + ) + + # Compute F2 score (beta = 2) + mushroom_preds = mushroom_test.assign( + predicted=mushroom_fit.predict(mushroom_test) + ) + f2_beta_2_score = fbeta_score( + mushroom_preds['target'], + mushroom_preds['predicted'], + beta=2, + pos_label='p' + ) + + test_scores = pd.DataFrame({'accuracy': [accuracy], + 'F2 score (beta = 2)': [f2_beta_2_score]}) + test_scores.to_csv(os.path.join(results_to, "test_scores.csv"), index=False) + + confusion_matrix = pd.crosstab( + mushroom_preds["target"], + mushroom_preds["predicted"] + ) + confusion_matrix.to_csv(os.path.join(results_to, "tables", "confusion_matrix.csv")) + + disp = ConfusionMatrixDisplay.from_predictions( + mushroom_preds["target"], + mushroom_preds["predicted"] + ) + disp.plot() + plt.savefig(os.path.join(results_to, "figures", "confusion_matrix.png"), dpi=300) + + +if __name__ == '__main__': + main() diff --git a/fit_mushroom_classifier.py b/fit_mushroom_classifier.py index 0b9c813..109838f 100644 --- a/fit_mushroom_classifier.py +++ b/fit_mushroom_classifier.py @@ -26,31 +26,25 @@ from sklearn.pipeline import make_pipeline from sklearn.metrics import ConfusionMatrixDisplay, make_scorer, fbeta_score, accuracy_score, precision_score, recall_score from sklearn.model_selection import cross_validate, cross_val_predict, GridSearchCV, RandomizedSearchCV -import warnings -warnings.filterwarnings("ignore", category=FutureWarning, module="deepchecks") @click.command() -@click.option('--training-data', type=str, help="Path to training data") +@click.option('--processed-training-data', type=str, help="Path to processed training data") @click.option('--preprocessor', type=str, help="Path to preprocessor object") -@click.option('--columns-to-drop', type=str, help="Optional: columns to drop") @click.option('--pipeline-to', type=str, help="Path to directory where the pipeline object will be written to") @click.option('--plot-to', type=str, help="Path to directory where the plot will be written to") +@click.option('--results-to', type=str, help="Path to directory where the plot will be written to") @click.option('--seed', type=int, help="Random seed", default=123) -def main(training_data, preprocessor, columns_to_drop, pipeline_to, plot_to, seed): +def main(processed_training_data, preprocessor, pipeline_to, plot_to, results_to, seed): '''Fits a breast cancer classifier to the training data and saves the pipeline object.''' np.random.seed(seed) set_config(transform_output="pandas") # read in data & preprocessor - mushroom_train = pd.read_csv(training_data) + mushroom_train = pd.read_csv(processed_training_data) mushroom_preprocessor = pickle.load(open(preprocessor, "rb")) - if columns_to_drop: - to_drop = pd.read_csv(columns_to_drop).feats_to_drop.tolist() - mushroom_train = mushroom_train.drop(columns=to_drop) - # create metrics scoring_metrics = { 'accuracy':make_scorer(accuracy_score), @@ -91,22 +85,38 @@ def main(training_data, preprocessor, columns_to_drop, pipeline_to, plot_to, see mushroom_train["target"]) # compilng hyperparameters and scores of best models into one dataframe - cols = ['params','mean_fit_time','mean_test_accuracy','std_test_accuracy','mean_test_f2_score','std_test_f2_score'] + cols = ['params', + 'mean_fit_time', + 'mean_test_accuracy', + 'std_test_accuracy', + 'mean_test_f2_score', + 'std_test_f2_score'] final_results = pd.concat( [pd.DataFrame(result.cv_results_).query('rank_test_f2_score == 1')[cols] for _,result in cv_results.items()] ) final_results.index = ['KNN','Logisic Regression','SVC'] - - with open("table.pkl", "wb") as f: - pickle.dump(final_results, f) + final_results.to_csv( + os.path.join(results_to, "tables", "numeric_correlation_matrix.csv") + ) # save the best model best_model = cv_results['svc'].best_estimator_ - best_model.fit(mushroom_train.drop(columns=["target"]), mushroom_train["target"]) + best_model.fit( + mushroom_train.drop(columns=["target"]), + mushroom_train["target"] + ) - with open(os.path.join(pipeline_to, "mushroom_pipeline.pickle"), 'wb') as f: + with open(os.path.join(pipeline_to, "mushroom_best_model.pickle"), 'wb') as f: pickle.dump(best_model, f) + disp = ConfusionMatrixDisplay.from_estimator( + best_model, + mushroom_train.drop(columns=["target"]), + mushroom_train["target"] + ) + disp.plot() + plt.savefig(os.path.join(results_to, "figures", "confusion_matrix.png"), dpi=300) + if __name__ == '__main__': main() \ No newline at end of file diff --git a/notebooks/.ipynb_checkpoints/Load_Data_and_EDA-checkpoint.html b/notebooks/.ipynb_checkpoints/Load_Data_and_EDA-checkpoint.html new file mode 100644 index 0000000..4986c35 --- /dev/null +++ b/notebooks/.ipynb_checkpoints/Load_Data_and_EDA-checkpoint.html @@ -0,0 +1,10308 @@ + + + + + +Load_Data_and_EDA + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/notebooks/.ipynb_checkpoints/Load_Data_and_EDA-checkpoint.ipynb b/notebooks/.ipynb_checkpoints/Load_Data_and_EDA-checkpoint.ipynb new file mode 100644 index 0000000..c1c34a3 --- /dev/null +++ b/notebooks/.ipynb_checkpoints/Load_Data_and_EDA-checkpoint.ipynb @@ -0,0 +1,3289 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1b40693f-6d55-4951-96a5-48a10ccb6773", + "metadata": {}, + "source": [ + "# Mushroom Edibility Classification Using Feature-Based Machine Learning Approach" + ] + }, + { + "cell_type": "markdown", + "id": "18590e2e-138a-4ed1-821b-8a1850fdce9b", + "metadata": {}, + "source": [ + "by Benjamin Frizzell, Hankun Xiao, Essie Zhang, Mason Zhang 2024/11/23" + ] + }, + { + "cell_type": "markdown", + "id": "81a65442-e81c-4e9d-9755-885bb2aebac9", + "metadata": {}, + "source": [ + "#### Import Library" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0d2500b5-022e-4ff0-818c-ad1013efb69d", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "from ucimlrepo import fetch_ucirepo \n", + "import pandas as pd\n", + "import numpy as np\n", + "import pandera as pa\n", + "from pandera import Check\n", + "from deepchecks import Dataset\n", + "import json\n", + "import logging\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split" + ] + }, + { + "cell_type": "markdown", + "id": "f49175e2-5eab-4b03-816c-f20995c50c96", + "metadata": {}, + "source": [ + "## Summary" + ] + }, + { + "cell_type": "markdown", + "id": "a1f39a05-24c5-4a5e-a34c-830e8efeee78", + "metadata": {}, + "source": [ + "In this project, a Support Vector Classifier was built and tuned to identify mushrooms edibility. A mushroom is classified as edible or poisonous with given color, habitat, class, and others. The final classifier performed quite well on unseen test data, with a final overall accuracy of 0.99 and $F_{\\beta}$ score with $\\beta = 2$ of 0.99. Furthermore, we use confusion matrix to show the accuracy of classification poisonous or edible mushroom. The model makes 12174 correct predictions out of 12214 test observations. 17 mistakes were predicting a poisonous mushroom as edible (false negative), while 23 mistakes were predicting a edible mushroom as poisonous (false positive). The model’s performance shows promise for implementation, prioritizing safety by minimizing false negatives that could result in consuming poisonous mushrooms. While false positives may lead to unnecessarily discarding safe mushrooms, they pose no safety risk. Further development is needed to make this model useful. Research should focus on improving performance and analyzing cases of incorrect predictions." + ] + }, + { + "cell_type": "markdown", + "id": "5626172b-fdbc-486d-ba3d-550432375290", + "metadata": {}, + "source": [ + "## Introduction" + ] + }, + { + "cell_type": "markdown", + "id": "d6ca1f13-3cd2-4bc6-bfae-4d0d6440e1b7", + "metadata": {}, + "source": [ + "Mushrooms are the most common food which is rich in vitamins and minerals. However, not all mushrooms can be consumed directly, most of them are poisonous and identifying edible or poisonous mushroom through the naked eye is quite difficult. Our aim is to using machine learning to identify mushrooms edibility. In this project, three methods are used to detect the edibility of mushrooms: Support Vector Classifier (SVC), K-Nearest Neighbors (KNN), and Logistic Regression. " + ] + }, + { + "cell_type": "markdown", + "id": "921597ef-c12e-4c4c-b8bf-b1eb20e90814", + "metadata": {}, + "source": [ + "## Methods" + ] + }, + { + "cell_type": "markdown", + "id": "a0920cdf-10c1-4151-bbf3-a689486257dd", + "metadata": {}, + "source": [ + "### Data" + ] + }, + { + "cell_type": "markdown", + "id": "549db552-150b-4744-ba90-497604b5b601", + "metadata": {}, + "source": [ + "The dataset used in this project is the Secondary Mushroom Dataset created by Wagner, D., Heider, D., & Hattab, G. from UCI Machine Learning Repository. This dataset contains 61069 hypothetical mushrooms with caps based on 173 species (353 mushrooms per species). Each mushroom is identified as definitely edible, definitely poisonous, or of unknown edibility and not recommended (the latter class was combined with the poisonous class)." + ] + }, + { + "cell_type": "markdown", + "id": "809c0908-7030-437e-bb4c-56bdf0066119", + "metadata": {}, + "source": [ + "### Analysis" + ] + }, + { + "cell_type": "markdown", + "id": "614cbeca-8401-49b3-8eed-cce9dc41d292", + "metadata": {}, + "source": [ + "The mushroom dataset is balanced with 56% of poisonous mushroom and 44% of edible mushroom. All variables were standardized and variables with more than 15% missing values are dropped, because imputing a variable that has a significant proportion of missing data might introduce too much noise or bias, making it unreliable. Data was splitted with 80% being partitioned into the training set and 20% being partitioned into the test set. Three classification models including Support Vector Classifier (SVC), K-Nearest Neighbors (KNN), and Logistic Regression are used to predict whether a mushroom is edible or poisonous. The fine tuned Support Vector Classifier has the best overall performance. The hyperparameter was chosen using 5-fold cross validation with $F_{\\beta}$ score as the classification metric. $\\beta$ was chosen to be set to 2 for the $F_{\\beta}$ score to increase the weight on recall during fitting because predicting a mushroom to be edible when it is in fact poisonous could have severe health consequences. Therefore the goal is to prioritize the minimization of false negatives. The Python programming language (Van Rossum and Drake 2009) and the following Python packages were used to perform the analysis: Matplotlib (Hunter, 2007), Pandas (McKinney, 2010), Scikit-learn (Pedregosa et al., 2011), NumPy (Harris et al., 2020), SciPy (Virtanen et al., 2020), UCIMLRepo." + ] + }, + { + "cell_type": "markdown", + "id": "58647071-18ff-44cb-9f2d-fd243555cff0", + "metadata": {}, + "source": [ + "## Results & Discussion" + ] + }, + { + "cell_type": "markdown", + "id": "f94469b3-143e-4a67-8c22-5bfa73baeccc", + "metadata": {}, + "source": [ + "The EDA shows that all numeric columns in the mushroom dataset are nearly normal with some skewness. A robust preprocessing scheme `QuantileTransformer` is used because it can transform skewed data or heavy-tailed distributions into a more Gaussian-like shape and reduce the impact of outliers.\n", + "`OneHotEncoder` is applied for categorical features in the mushroom dataset, because each feature does not contains much categories and they are not ordered. It is critical to keep all important information in the features. Since ring type feature has many missing values, it was filled in with a \"Missing\" class. Treating missing values as a distinct category provides a way to model the absence of data directly. This can be valuable because missingness itself might carry information." + ] + }, + { + "cell_type": "markdown", + "id": "7558f2ed-854e-492b-8a71-7e37cdecf1f3", + "metadata": {}, + "source": [ + "#### Load Data" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "20a3d74b-174b-420e-9745-6d68f9d7da5f", + "metadata": {}, + "outputs": [], + "source": [ + "# fetch dataset as pandas DataFrames\n", + "secondary_mushroom = fetch_ucirepo(id=848) \n", + "X = secondary_mushroom.data.features \n", + "y = secondary_mushroom.data.targets " + ] + }, + { + "cell_type": "markdown", + "id": "e4fa6da5-7876-43ba-b5ff-e12a66c78c75", + "metadata": {}, + "source": [ + "##### Before splitting the data into test and training sets, we want to check for missing values in each column to determine whether they can be used in our model." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "eeee4dd9-6fa9-47d3-b86f-e128e791a96e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Missing Values by Column
 ColumnMissing Count
0cap-diameter0
1cap-shape0
2cap-surface14120
3cap-color0
4does-bruise-or-bleed0
5gill-attachment9884
6gill-spacing25063
7gill-color0
8stem-height0
9stem-width0
10stem-root51538
11stem-surface38124
12stem-color0
13veil-type57892
14veil-color53656
15has-ring0
16ring-type2471
17spore-print-color54715
18habitat0
19season0
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Check the missing values\n", + "missing_values = X.isnull().sum().reset_index()\n", + "missing_values.columns = ['Column', 'Missing Count']\n", + "\n", + "# Highlight values with a gradient\n", + "styled_missing = missing_values.style.format(\n", + " precision=0\n", + ").background_gradient(\n", + " subset=['Missing Count'],\n", + " cmap='YlOrRd'\n", + ").set_caption(\"Missing Values by Column\")\n", + "\n", + "# Display the styled DataFrame\n", + "display(styled_missing)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d362597a-3f05-4907-8fc6-2063d4579fa8", + "metadata": {}, + "outputs": [], + "source": [ + "colunms_to_drop = ['cap-surface', 'gill-attachment', 'gill-spacing', \n", + " 'stem-root', 'stem-surface', 'veil-type', 'veil-color', \n", + " 'spore-print-color']\n", + "X = X.drop(columns = colunms_to_drop)" + ] + }, + { + "cell_type": "markdown", + "id": "f997158b-7b42-4367-8be8-41683c425650", + "metadata": {}, + "source": [ + "After examining the data set, we decided to drop columns with a high proportion of missing values (over 15%), which include `cap-surface`, `gill-attachment`, `gill-spacing`, `stem-root`, `stem-surface`, `veil-type`, `veil-color`, and `spore-print-color`." + ] + }, + { + "cell_type": "markdown", + "id": "401edb8d-0321-43a2-9ada-fc4700368211", + "metadata": {}, + "source": [ + "#### Data Validation" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b3fec04e-ecc7-4af2-becf-eafa8b55b696", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cap-diametercap-shapecap-colordoes-bruise-or-bleedgill-colorstem-heightstem-widthstem-colorhas-ringring-typehabitatseasontarget
015.26xofw16.9517.09wtgdwp
116.60xofw17.9918.19wtgdup
214.07xofw17.8017.74wtgdwp
314.17fefw15.7715.98wtpdwp
414.64xofw16.5317.20wtpdwp
..........................................
610641.18syff3.936.22yffdap
610651.27fyff3.185.43yffdap
610661.27syff3.866.37yffdup
610671.24fyff3.565.44yffdup
610681.17syff3.255.45yffdup
\n", + "

60903 rows × 13 columns

\n", + "
" + ], + "text/plain": [ + " cap-diameter cap-shape cap-color does-bruise-or-bleed gill-color \\\n", + "0 15.26 x o f w \n", + "1 16.60 x o f w \n", + "2 14.07 x o f w \n", + "3 14.17 f e f w \n", + "4 14.64 x o f w \n", + "... ... ... ... ... ... \n", + "61064 1.18 s y f f \n", + "61065 1.27 f y f f \n", + "61066 1.27 s y f f \n", + "61067 1.24 f y f f \n", + "61068 1.17 s y f f \n", + "\n", + " stem-height stem-width stem-color has-ring ring-type habitat season \\\n", + "0 16.95 17.09 w t g d w \n", + "1 17.99 18.19 w t g d u \n", + "2 17.80 17.74 w t g d w \n", + "3 15.77 15.98 w t p d w \n", + "4 16.53 17.20 w t p d w \n", + "... ... ... ... ... ... ... ... \n", + "61064 3.93 6.22 y f f d a \n", + "61065 3.18 5.43 y f f d a \n", + "61066 3.86 6.37 y f f d u \n", + "61067 3.56 5.44 y f f d u \n", + "61068 3.25 5.45 y f f d u \n", + "\n", + " target \n", + "0 p \n", + "1 p \n", + "2 p \n", + "3 p \n", + "4 p \n", + "... ... \n", + "61064 p \n", + "61065 p \n", + "61066 p \n", + "61067 p \n", + "61068 p \n", + "\n", + "[60903 rows x 13 columns]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# combine features and target to the same dataframe named mushroom\n", + "mushroom = X.copy()\n", + "mushroom['target'] = y\n", + "\n", + "schema = pa.DataFrameSchema(\n", + " \n", + " {\n", + " \"target\": pa.Column(str, pa.Check.isin(['e', 'p'])),\n", + " # check missing value proportion (threshold=15%) AND value ranges for all features\n", + " \"cap-diameter\": pa.Column(float, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'cap-diameter' column.\"), \n", + " pa.Check.between(0, 100)],\n", + " nullable=True), \n", + " \"cap-shape\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'cap-shape' column.\"), \n", + " pa.Check.isin(['x', 'f', 'p', 'b', 'c', 's', 'o'])],\n", + " nullable=True), \n", + " \"cap-color\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'cap-color' column.\"), \n", + " pa.Check.isin(['o', 'e', 'n', 'g', 'r', 'w', 'y', 'p', 'u', 'b', 'l', 'k'])],\n", + " nullable=True),\n", + " \"does-bruise-or-bleed\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'does-bruise-or-bleed' column.\"), \n", + " pa.Check.isin(['f', 't'])],\n", + " nullable=True),\n", + " \"gill-color\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'gill-color' column.\"), \n", + " pa.Check.isin(['w', 'n', 'p', 'u', 'b', 'g', 'y', 'r', 'e', 'o', 'k', 'l', 'f'])],\n", + " nullable=True),\n", + " \"stem-height\": pa.Column(float, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'stem-height' column.\"), \n", + " pa.Check.between(0, 100)],\n", + " nullable=True),\n", + " \"stem-width\": pa.Column(float, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'stem-width' column.\"), \n", + " pa.Check.between(0, 150)],\n", + " nullable=True),\n", + " \"stem-color\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'stem-color' column.\"), \n", + " pa.Check.isin(['o', 'e', 'n', 'g', 'r', 'w', 'y', 'p', 'u', 'b', 'l', 'k', 'f'])],\n", + " nullable=True),\n", + " \"has-ring\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'has-ring' column.\"), \n", + " pa.Check.isin(['t', 'f'])],\n", + " nullable=True),\n", + " \"ring-type\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'ring-type' column.\"), \n", + " pa.Check.isin(['c', 'e', 'r', 'g', 'l', 'p', 's', 'z', 'y', 'm', 'f'])],\n", + " nullable=True),\n", + " \"habitat\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'habitat' column.\"), \n", + " pa.Check.isin(['g', 'l', 'm', 'p', 'h', 'u', 'w', 'd'])],\n", + " nullable=True),\n", + " \"season\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'season' column.\"),\n", + " pa.Check.isin(['s', 'u', 'a', 'w'])],\n", + " nullable=True)\n", + " \n", + " },\n", + " checks=[\n", + " pa.Check(lambda df: ~mushroom.duplicated().any(), error=\"Duplicate rows found.\"),\n", + " pa.Check(lambda df: ~(mushroom.isna().all(axis=1)).any(), error=\"Empty rows found.\")\n", + " ],\n", + " drop_invalid_rows=True\n", + ")\n", + "\n", + "schema.validate(mushroom, lazy=True).drop_duplicates().dropna(how=\"all\")" + ] + }, + { + "cell_type": "markdown", + "id": "5b05535a-7bae-42ca-ae5d-aa42e3e95adc", + "metadata": {}, + "source": [ + "##### create validation_error.log file" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "1ccb0cfd-78eb-4f53-8d0e-4cf62b9e821d", + "metadata": {}, + "outputs": [], + "source": [ + "# create validation_error.log file\n", + "\n", + "# Configure logging\n", + "logging.basicConfig(\n", + " filename=\"validation_errors.log\",\n", + " filemode=\"w\",\n", + " format=\"%(asctime)s - %(message)s\",\n", + " level=logging.INFO,\n", + ")\n", + "\n", + "# Define the schema\n", + "schema = pa.DataFrameSchema(\n", + " \n", + " {\n", + " \"target\": pa.Column(str, pa.Check.isin(['e', 'p'])),\n", + " \n", + " \"cap-diameter\": pa.Column(float, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'cap-diameter' column.\"), \n", + " pa.Check.between(0, 100)],\n", + " nullable=True),\n", + " \"cap-shape\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'cap-shape' column.\"), \n", + " pa.Check.isin(['x', 'f', 'p', 'b', 'c', 's', 'o'])],\n", + " nullable=True), \n", + " \"cap-color\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'cap-color' column.\"), \n", + " pa.Check.isin(['o', 'e', 'n', 'g', 'r', 'w', 'y', 'p', 'u', 'b', 'l', 'k'])],\n", + " nullable=True),\n", + " \"does-bruise-or-bleed\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'does-bruise-or-bleed' column.\"), \n", + " pa.Check.isin(['f', 't'])],\n", + " nullable=True),\n", + " \"gill-color\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'gill-color' column.\"), \n", + " pa.Check.isin(['w', 'n', 'p', 'u', 'b', 'g', 'y', 'r', 'e', 'o', 'k', 'l', 'f'])],\n", + " nullable=True),\n", + " \"stem-height\": pa.Column(float, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'stem-height' column.\"), \n", + " pa.Check.between(0, 100)],\n", + " nullable=True),\n", + " \"stem-width\": pa.Column(float, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'stem-width' column.\"), \n", + " pa.Check.between(0, 150)],\n", + " nullable=True),\n", + " \"stem-color\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'stem-color' column.\"), \n", + " pa.Check.isin(['o', 'e', 'n', 'g', 'r', 'w', 'y', 'p', 'u', 'b', 'l', 'k', 'f'])],\n", + " nullable=True),\n", + " \"has-ring\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'has-ring' column.\"), \n", + " pa.Check.isin(['t', 'f'])],\n", + " nullable=True),\n", + " \"ring-type\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'ring-type' column.\"), \n", + " pa.Check.isin(['c', 'e', 'r', 'g', 'l', 'p', 's', 'z', 'y', 'm', 'f'])],\n", + " nullable=True),\n", + " \"habitat\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'habitat' column.\"), \n", + " pa.Check.isin(['g', 'l', 'm', 'p', 'h', 'u', 'w', 'd'])],\n", + " nullable=True),\n", + " \"season\": pa.Column(str, checks = [pa.Check(lambda s: s.isna().mean() <= 0.15, \n", + " element_wise=False, \n", + " error=\"Too many null values in 'season' column.\"),\n", + " pa.Check.isin(['s', 'u', 'a', 'w'])],\n", + " nullable=True)\n", + " \n", + " },\n", + " checks=[\n", + " pa.Check(lambda df: ~mushroom.duplicated().any(), error=\"Duplicate rows found.\"),\n", + " pa.Check(lambda df: ~(mushroom.isna().all(axis=1)).any(), error=\"Empty rows found.\")\n", + " ],\n", + " drop_invalid_rows = False\n", + ")\n", + "\n", + "# Initialize error cases DataFrame\n", + "error_cases = pd.DataFrame()\n", + "data = mushroom.copy()\n", + "\n", + "# Validate data and handle errors\n", + "try:\n", + " validated_data = schema.validate(data, lazy=True)\n", + "except pa.errors.SchemaErrors as e:\n", + " error_cases = e.failure_cases\n", + "\n", + " # Convert the error message to a JSON string\n", + " error_message = json.dumps(e.message, indent=2)\n", + " logging.error(\"\\n\" + error_message)\n", + "\n", + "# Filter out invalid rows based on the error cases\n", + "if not error_cases.empty:\n", + " invalid_indices = error_cases[\"index\"].dropna().unique()\n", + " validated_data = (\n", + " data.drop(index=invalid_indices)\n", + " .reset_index(drop=True)\n", + " .drop_duplicates()\n", + " .dropna(how=\"all\")\n", + " )\n", + "else:\n", + " validated_data = data" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "66437bbd-1394-4685-8901-474bff89f28a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(60903, 13)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "validated_data.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "58de532e-c52c-46a6-876b-8d1f62a4e35b", + "metadata": {}, + "outputs": [], + "source": [ + "X = validated_data.drop(['target'], axis=1)\n", + "y = validated_data['target']" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "8f810d3b-d836-4679-9c5d-68563375c888", + "metadata": {}, + "outputs": [], + "source": [ + "# Split the data test and training set\n", + "\n", + "X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.2, random_state=123\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "208ef84f-8ef1-4022-8d69-edd4bbf9a534", + "metadata": {}, + "outputs": [], + "source": [ + "mushroom_train = X_train.copy()\n", + "mushroom_train['target'] = y_train" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "95fa0221-e522-4f53-826b-d375a3a5c6db", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cap-diameterstem-heightstem-width
cap-diameter1.0000000.4200870.692574
stem-height0.4200871.0000000.431192
stem-width0.6925740.4311921.000000
\n", + "
" + ], + "text/plain": [ + " cap-diameter stem-height stem-width\n", + "cap-diameter 1.000000 0.420087 0.692574\n", + "stem-height 0.420087 1.000000 0.431192\n", + "stem-width 0.692574 0.431192 1.000000" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# check anomalous correlations\n", + "numeric_columns = mushroom_train.select_dtypes(include='number')\n", + "corr_matrix = numeric_columns.corr()\n", + "corr_matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "7fd37ab8-281b-45f4-a30e-0b07ce76a767", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAk4AAAHECAYAAADPmqXWAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABC+klEQVR4nO3deVxWdf7//+cVywUiXIrIlqBUwmiopZailTtoLrlMOjFD6hiW65gy3tIWsVwmy8y0HMdMcylrJlvUIi2X8iNqUlouuZQLKogL4hIByvn90Y/z9WLRI6IX1uN+u123m9f7vM45r3O40Kdnu2yGYRgCAADAFd3i6gYAAABuFgQnAAAAiwhOAAAAFhGcAAAALCI4AQAAWERwAgAAsIjgBAAAYBHBCQAAwCKCEwAAgEUEJ8CitWvXymazKTk52SXrr1OnjurUqeM0lpycLJvNprVr17qkpwMHDshms6lfv34uWX9FyMnJ0dChQ1W7dm25u7vLZrPpwIEDrm4LFthsNrVu3fqaltG6dWvZbDbL9a7+ewCuR3DCH0rRP/SXvqpUqaLQ0FC1a9dOzz33nH766afrsu6r/Qu6sigtsP2e/POf/9Trr7+uu+66S2PHjtW4ceNUrVq1EnWlfXYu97qZ9lm/fv2uKjB+/vnnstls6tix4xVre/XqJZvNpqVLl15jl0Dl4O7qBgBXuP322/W3v/1NkpSXl6esrCxt3rxZL7zwgiZNmqTRo0dr4sSJTkHn3nvv1a5duxQQEOCSnr/88kuXrPdybr31Vu3atUsOh8PVrZTbp59+qqioKH388ceXratWrZrGjRvnNHb69GlNnz5dtWvXLnHUrbTw9XvRoUMHhYeHa9WqVTp8+LBq1apVat2JEye0bNky1axZU127dq3wPnbt2qUqVapU+HKByyE44Q/pjjvuKPVQ+9dff61HH31UkydPlpubm1544QVzWpUqVfSnP/3pBnbp7Pbbb3fZusvi4eHh0n1SEY4ePaoHHnjginXVqlUr8Zk5cOCApk+frjp16vyhTt3ccsst6tevn55//nm9/fbbevrpp0utW7hwoQoKCvToo4/Kw8Ojwvu42T97uDlxqg64xP3336/PP/9cdrtdU6ZMUXp6ujmtrGsb9u7dq/79+ysiIkJeXl4KCAhQ48aNNWrUKLPGZrNp3bp15p+LXkVHKS69VujHH39Uz549FRAQ4HT65EqnzObMmaM777xTXl5eCg8P15gxY/Trr7861Vzu+ozi1ysVvT948KAOHjzo1HfR/Je7xunQoUMaMGCAbr31Vnl6eqpWrVoaMGCA0z4tUnQa88KFC3rhhRcUEREhu92uyMhIvfHGG2Vuc2kuXLigadOmqVGjRvL29pbD4VCbNm20YsUKp7qi01OGYWjdunUlfibXYs+ePRo9erQaN26sGjVqyMvLS5GRkXrqqad07ty5EvVF25+Xl6fnnntOd9xxhzw8PJx+TkuXLlXTpk3l7e2toKAgJSYmKjs7u8zPRX5+vl555RU1btxYPj4+8vX11f33369PPvnEqa5OnTp6++23JUkRERHmfrjStUP9+/eXzWbT/Pnzy6yZN2+eJOnvf/+7JOmtt97SQw89pDp16sjLy0v+/v6Ki4vTmjVrSsx76Wc1NTVVcXFxqlatmtNR4NL6vNp9X+TXX3/V6NGjFRYWJi8vLzVo0EBvvfXWZfdBcVlZWXryySd1xx13yG63KyAgQL169dL27duvajmo3DjiBBQTGRmpPn36aMGCBfroo480bNiwMmuPHj2qe++9V+fPn1fnzp3Vp08fnTt3Tnv37tWMGTM0depUSdK4ceM0f/58HTx40Ol0z1133eW0vH379ql58+a688471bdvX506dUqenp5X7Hnq1Klau3at+vTpoy5duujTTz/Vv/71L3333Xf67LPPynVtVdGpqVdffVWSNGLECHPalf5R3bt3r+677z5lZWWpa9euuvPOO7Vjxw699dZbWr58uf7v//5Pd9xxR4n5HnnkEW3atEmdOnWSm5ub3n//fQ0ZMkQeHh5KTEy8Ys+GYahPnz5aunSpIiMjNWTIEJ0/f17vv/++unTpounTp2v48OGSpO7du6tOnToaP36806m24j+T8li6dKnmzp2rNm3aqHXr1iosLNTGjRv14osvat26dfrqq69KPQLTs2dPbdu2TXFxcfL399dtt90m6bfAMWDAAFWrVk2PPvqoHA6HPv30U3Xo0EEFBQUllpWXl6eOHTtq7dq1uvvuuzVgwAAVFBRoxYoVeuihhzRjxgwNHTpU0m8/1/nz52vbtm36xz/+YZ5ivNI1WnXq1FG7du30xRdf6Kuvvipx1G7Lli364YcfFBMTo/r160uShgwZokaNGql9+/aqWbOmjhw5oo8++kjt27fX0qVL9dBDD5VYz4YNGzRp0iS1adNGAwcO1KFDh67Lvn/44Yf1/fff6+GHH1ZBQYHef/99DRgwQMeOHdOYMWMuu05J+umnn9S6dWsdOXJEsbGx6t69u7KysvTBBx/o888/15dffqlmzZpdcTm4CRjAH8j+/fsNSUZcXNxl6+bOnWtIMhISEsyxNWvWGJKMcePGmWOvvfaaIcmYPn16iWUcP37c6X2rVq2Msn7livqSZDz77LOl1tSuXduoXbu209i4ceMMSYaXl5exfft2c7ygoMDo0KGDIclYsGDBZbeheA99+/a94nqvNE/btm0NScbs2bOdxmfPnm1IMtq1a+c0XrRvmjVrZuTk5JjjP/74o+Hu7m5ERUWVuv7iFixYYEgyWrVqZeTl5Znj6enpRmBgoOHh4WH8/PPPTvMU1ZdH0fYXn//w4cNO6y8yfvx4Q5KxaNEip/Gi7b/rrruMkydPOk3Lzs42qlatavj6+ho//fSTOV5QUGC0b9/ekFTi5zN27FhDkpGcnGwUFhaa42fOnDGaNm1qeHp6GkeOHDHH+/bta0gy9u/ff1Xb/+677xqSjH79+pWYNmjQIEOS8eabb5pjxfe9YRjG0aNHjdDQUKNu3bpO40WfVUnG3LlzS11/Re77+vXrG2fOnDHHMzIyjJCQEMPd3d1pv5f1O9SiRQvD3d3dWLlypdP47t27DV9fX6NBgwalbgNuPpyqA0oRGhoq6beLW63w9vYuMVaei8iDg4P1zDPPXPV8CQkJuvPOO8337u7umjRpkiSZp2FulPT0dK1evVr169cvcZQoMTFR9erV05dfflnqKbvJkyfLz8/PfB8VFaWWLVtq9+7dOnv27BXXXXTaaMqUKU5H6mrVqqUnn3xSBQUFWrx4cTm3zLqi05PFFR3l+eKLL0qdb/z48fL393ca+/jjj3Xu3Dk99thj5hEo6bef8aXX4BUpLCzUrFmzdMcdd+i5555zOtro6+ur5557Tvn5+RVyl1uPHj1UvXp1/fe//3U6Dfbrr7/q3XfflY+Pj/r06WOOR0RElFhGSEiIevXqpb179+rgwYMlpt99993mqT4ryrvvn376afn6+prvg4ODNXLkSF24cEHvvPPOZdf53XffacOGDerbt686dOjgNC0yMlKJiYn64YcfOGX3O8GpOqAUhmFYquvSpYueeuopDRkyRKtWrVLHjh113333KTIyslzrbdSokaVTc8Xdf//9JcaKrofZunVruXopr++++06S1KpVqxKnCG02mx544AHt2rVL27ZtU1hYmNP0xo0bl1he0R1bp0+fdvqHrax1e3t769577y0xrej04o3YH4ZhaN68eZo/f762b9+unJwcFRYWmtOPHj1a6nyl9b1t2zZJUosWLUqtd3d3/mt89+7dys7OVmhoqMaPH19inuPHj0uSfvzxR+sbVAa73a6//vWvmjlzpt5//30z4CxdulSnT59W//79VbVqVbP+559/1uTJk7V69WodOXJEeXl5Tss7evSoateuXWIbr0Z5931pv0NFY1f6zGzcuFGSlJmZWer1g0X7+scff1R0dLSVzUAlRnACSpGRkSFJqlmz5mXrIiIilJqaqvHjx+uzzz7Tf//7X0m/HSl54YUX9PDDD1/VeoOCgsrVb2BgYJnjR44cKdcyy+vMmTOSyt6W4OBgSb89eLK40h5rUBQMLl68aGndxcOYlfVWtOHDh2vmzJkKCwtTt27dFBISIrvdLum3o0rFA0OR0vZZ0f4s7bN4yy23lDiyeerUKUnSjh07tGPHjjJ7PH/+vLWNuYIBAwZo5syZmjdvntNF4EXTiuzbt0/33nuvzpw5ozZt2qhr167y8/PTLbfcorVr12rdunWl7per/Z0o774v7XeoaN1X+swU7fMVK1aUuAnhUhW1z+FaBCegFEVP4r7nnnuuWNuwYUN98MEHKigoUFpamj777DO99tpr6tOnj0JDQ9WyZUvL6y3vAzKzsrLKHL80jNxyy29n5y9cuFCitqICRdGptmPHjpU6vWj80lNyFcXPz88l671UVlaWXn/9dTVs2FCpqalOzxnKzMws9ShQkdJ+/kX9Fh0pulRhYaFOnDihW2+9tUR9r1699L///a/c22HVXXfdpcaNG2v9+vXas2ePvLy8tHr1avM0a5Fp06YpOztbixYt0l//+lenZTzxxBPmXafFXc3vxLXs+6ysrBKhu+gzc6XnlBXt80svusfvF9c4AcXs2bNH77//vux2u3r06GF5Pg8PDzVv3lzjx4/Xa6+9JsMwtHz5cnO6m5ubJGtHTq7W119/XWJsy5Ytys3NdbpLrHr16pJU6lGoolNsxbm5uV1Vz0Xr++qrr0qc8jQMw+y1Iu5eK+7uu+9Wbm6uNm/eXGJa0T/M12O9l/r5559lGIbat29f4uGMpf2crqRRo0aSfru7rLjNmzeXCMH16tWTn5+ftmzZooKCAkvruNbPZtGRpfnz52vevHkyDMPpaJMk84n83bp1cxovLCzU//3f/5VrvcVdy74vbbrVz2rR3XKpqalX0S1uVgQn4BLr169XXFyc8vLyNGbMGKf/yZfmm2++KfVoT9H/VC+9aLzoot/Dhw9XYMe/WbhwodNpmQsXLmjs2LGSpL59+5rjUVFRqlq1qj755BPz9EJRvxMmTCh12f7+/jpx4kSJZ0KVJTw8XG3atDEfP3Cpt956Szt27FDbtm3LPKV2LYq2dcyYMU6h4ciRI3rllVfk7u5e4mhHRSu6RmfDhg1O19YcPnxYTz311FUv76GHHlLVqlX15ptvav/+/eb4hQsX9Oyzz5aod3d316BBg3Tw4EElJSWVGp62b9/u9Lm91s9mfHy8vLy8tGDBAs2fP1/u7u569NFHnWqK9sv69eudxl988cUKu2j6Wvb9xIkTnW5AOHbsmPmZiY+Pv+y89957r5o1a6Z3331X7733XonphYWFZR5Rw82HU3X4Q9q3b595EWd+fr6ysrK0adMmbd++XW5ubnrmmWf03HPPXXE5ixcv1htvvKHWrVvrjjvukJ+fn3bu3KlPP/1UAQEBTncDtW3bVv/73//08MMP68EHHzQfste5c+dr3p727durefPm+stf/iJ/f399+umn2r59u+Li4syvlpEkT09PDR06VP/617/UuHFjPfTQQzp79qyWLVumVq1alfo9fW3bttWWLVvUtWtX3X///fL09NR9992n++67r8x+Zs2apfvuu0+JiYlatmyZ6tevr507d+qTTz5RzZo1NWvWrGve5tIkJCRo6dKl+vjjj9WwYUN16dLFfI7TyZMnNXXqVKc7066HorvEPvjgAzVt2lTt2rXTsWPHtHz5crVt21Y///zzVS2vWrVqeuWVVzRw4EA1btxYffr0MZ/jZLfbFRoaap6CLTJ+/Hh9++23eu2117RixQq1atXKfG7SDz/8oG3btik1NdW8rqdt27Z6+eWX9fjjj+vhhx+Wj4+PwsPDrxgYLu2xV69e5h2L3bt3L3Ft0hNPPKF58+apZ8+e6tOnj2rUqKGNGzfq22+/VefOnS97bZBV17Lvb7vtNkVHR6tXr17mc5yysrI0ceJE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IXrnnXf08ccfy9fX1zzi43A45O3tLZvNphEjRmjSpEmqW7eu6tatq0mTJqlKlSqKj483awcMGKBRo0apRo0a8vf3V1JSkho0aGDeZVevXj117NhRiYmJmj17tiRp4MCB6tKli6KioiRJsbGxql+/vhISEvTSSy/p1KlTSkpKUmJiIkeSAACA64PTrFmzJEmtW7d2Gp83b5769esnSRo9erRyc3M1ePBgZWdnq1mzZlq5cqV8fX3N+mnTpsnd3V29e/dWbm6u2rVrp/nz58vNzc2sWbx4sYYPH27efdetWzfNnDnTnO7m5qYVK1Zo8ODBatmypby9vRUfH6+XX375Om09AAC4mbg8OBmGccUam82m5ORkJScnl1nj5eWlGTNmaMaMGWXW+Pv7a9GiRZddV3h4uJYvX37FngAAwB+Py69xAgAAuFkQnAAAACwiOAEAAFhEcAIAALCI4AQAAGARwQkAAMAighMAAIBFBCcAAACLCE4AAAAWEZwAAAAsIjgBAABYRHACAACwiOAEAABgEcEJAADAIoITAACARQQnAAAAiwhOAAAAFhGcAAAALCI4AQAAWERwAgAAsIjgBAAAYBHBCQAAwCKCEwAAgEUEJwAAAIsITgAAABYRnAAAACwiOAEAAFhEcAIAALCI4AQAAGARwQkAAMAighMAAIBFBCcAAACLCE4AAAAWEZwAAAAsIjgBAABYRHACAACwiOAEAABgEcEJAADAIoITAACARQQnAAAAiwhOAAAAFhGcAAAALCI4AQAAWERwAgAAsIjgBAAAYBHBCQAAwCKCEwAAgEXlCk5ubm7avHlzqdPS0tLk5uZ2TU0BAABURuUKToZhlDmtsLBQNput3A0BAABUVuU+VVdWOEpLS5PD4Sh3QwAAAJWVu9XC6dOna/r06ZJ+C03du3eX3W53qsnNzVVWVpb+/Oc/V2yXAAAAlYDl4BQYGKg777xTknTgwAHddtttqlatmlON3W5XgwYN9I9//KNCmwQAAKgMLAenRx55RI888ogkqU2bNpo1a5b+9Kc/XbfGAAAAKhvLwelSa9asqeg+AAAAKr1yXxxuGIY2b96s//73v1qwYEGJl1VfffWVunbtqtDQUNlsNn300UdO0/v16yebzeb0at68uVNNXl6ehg0bpoCAAPn4+Khbt246fPiwU012drYSEhLkcDjkcDiUkJCg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WSJMSVJoaKjTsooUnTK8nJMnT+rChQuaMWOGZsyYUWrNiRMnJEljxoyRj4+PFi1apH//+99yc3PTAw88oBdffFFNmza94roAWEdwAuBSbm5uateunT777DMdPnxYtWrVKrN29erVOnr0qNauXWseZZJ0VdfyBAQEyGaz6euvvy71QvSisRo1akj6LWgVl5mZ6RSUatSooYyMjBJ1R48eNdd5KZvNdsU+q1evLjc3NyUkJGjIkCGl1kREREiS3N3dNXLkSI0cOVKnT5/WF198obFjxyouLk7p6emqUqXKFdcHwBpO1QFwuTFjxsgwDCUmJio/P7/E9IKCAi1btswMHMUDz+zZs0vMU1RT/ChUly5dZBiGjhw5oqZNm5Z4NWjQQJLUrFkz2e12vffee07zb9y4UQcPHnQaa9eunXbu3Klvv/3WaXzBggWy2Wxq06aNld3gpEqVKmrTpo2+++47NWzYsNRei8LdpapVq6Y///nPGjJkiE6dOmXeSQigYnDECYDLxcTEaNasWRo8eLCaNGmiQYMG6c4771RBQYG+++47/ec//1F0dLTefPNNVa9eXU888YTGjRsnDw8PLV68WNu2bSuxzKIA9OKLL6pTp05yc3NTw4YN1bJlSw0cOFD9+/fXli1b9MADD8jHx0cZGRlav369GjRooEGDBsnf318jR47U5MmTVb16dfXo0UOHDx/W+PHjFRISoltu+X//73zyySe1YMECde7cWc8//7xq166tFStW6I033tCgQYOc7sC7GtOnT9d9992n+++/X4MGDVKdOnV09uxZ7du3T8uWLTOvneratauio6PVtGlT1axZUwcPHtSrr76q2rVrl3nHHoBycu216QDw/2zdutXo27evER4ebnh6eho+Pj7G3XffbTz33HNGVlaWYRiGsWHDBiMmJsaoUqWKUbNmTeOxxx4zvv322xJ3pOXl5RmPPfaYUbNmTcNmsxmSjP3795vT33rrLaNZs2aGj4+P4e3tbdx+++3Go48+amzZssWsKSwsNCZMmGDUqlXL8PT0NBo2bGgsX77caNSokdGjRw+n3g8ePGjEx8cbNWrUMDw8PIyoqCjjpZdeMi5evGjWFN0599JLL5XY9tLuqisa//vf/27ceuuthoeHh1GzZk2jRYsWxoQJE8yaqVOnGi1atDACAgIMT09PIzw83BgwYIBx4MCB8vwYAFwGX7kCAFdh//79+tOf/qRx48Zp7Nixrm4HwA1GcAKAMmzbtk3vvvuuWrRoIT8/P+3evVtTpkzRmTNntH379jLvzAPw+8U1TgBQBh8fH23ZskVz587V6dOn5XA41Lp1a02cOJHQBPxBccQJAADAIh5HAAAAYBHBCQAAwCKCEwAAgEUEJwAAAIsITgAAABYRnAAAACwiOAEAAFhEcAIAALCI4AQAAGDR/wcj/Qm8YDngfwAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# check the distribution of target variable\n", + "category_counts = y_train.value_counts()\n", + "\n", + "# Plotting the bar chart\n", + "category_counts.plot(kind='bar', color='skyblue', edgecolor='black')\n", + "\n", + "# Adding labels and title\n", + "plt.title('Distribution of Target Variable', fontsize=14)\n", + "plt.xlabel('Categories', fontsize=12)\n", + "plt.ylabel('Count', fontsize=12)\n", + "\n", + "# Show the plot\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "1b334cbb-673a-4019-9d88-1bb80c957ad7", + "metadata": {}, + "source": [ + "#### EDA" + ] + }, + { + "cell_type": "markdown", + "id": "01b21f83-3fcc-4e0c-a7e6-8b9e0cd0c4ec", + "metadata": {}, + "source": [ + "##### Part 1: Missing Values" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "565a884a-16fc-4538-9e7e-535021dfdcf1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Missing Values by Column
 ColumnMissing Count
0cap-diameter0
1cap-shape0
2cap-color0
3does-bruise-or-bleed0
4gill-color0
5stem-height0
6stem-width0
7stem-color0
8has-ring0
9ring-type2471
10habitat0
11season0
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Check the missing values\n", + "missing_values = X.isnull().sum().reset_index()\n", + "missing_values.columns = ['Column', 'Missing Count']\n", + "\n", + "# Highlight values with a gradient\n", + "styled_missing = missing_values.style.format(\n", + " precision=0\n", + ").background_gradient(\n", + " subset=['Missing Count'],\n", + " cmap='YlOrRd'\n", + ").set_caption(\"Missing Values by Column\")\n", + "\n", + "# Display the styled DataFrame\n", + "display(styled_missing)" + ] + }, + { + "cell_type": "markdown", + "id": "302deb34-f082-41b2-bd10-7b20ba0b3dbd", + "metadata": {}, + "source": [ + "The initial `X_train` assessment has demonstrated no missing values within remaining features except for the `ring-type` . However, the proportion of missing values in this feature is reasonable, and simply dropping this column could result in loss of potentially valuable information, introduction of biases etc., which might reduce the overall accuracy of the classifier. Therefore, we decided to retain this column and perform imputation on `ring-type` in the data preprocessing phase. " + ] + }, + { + "cell_type": "markdown", + "id": "9dd6a42f-b507-4d81-aa68-1274d20872c1", + "metadata": {}, + "source": [ + "##### Part 2: The distribution of numeric features" + ] + }, + { + "cell_type": "markdown", + "id": "dc6a5a2b-84f8-402a-ac8c-0bb727ec5c13", + "metadata": {}, + "source": [ + "To understand the numeric features in the data set, we plotted histograms for each numeric column in `X_train`, which helps identify the distribution patterns as well as detecting any skewness or outliers. The numeric columns being plotted are `cap-diameter`, `stem-height`, and `stem-width`." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "c7c4cb2e-0f89-44fd-8faa-11088dd290e2", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAeEAAAHUCAYAAAAN/ZAQAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABKMUlEQVR4nO3deVhV1f4G8PfIcBiEI4OHw1FErgMOoKIUgpY4oShyE7tqGE6EmVNeIQu7XrFSTHMozSEzHKCwcsgycdYyRXHAnCJNRFQQUmb1gLB+f3TdP4+AIkKb4f08z37yrPXd66wF6NseOFshhBAgIiKiv10DuSdARERUXzGEiYiIZMIQJiIikglDmIiISCYMYSIiIpkwhImIiGTCECYiIpIJQ5iIiEgmDGEiIiKZMISpRlq7di0UCgWOHz9eZr+fnx+aN2+u19a8eXOMHj36qd7n8OHDiIiIQHZ2duUmWg9t3LgR7du3h6mpKRQKBRITE+We0jM5cOAAFAoFDhw4ILWNHj261M9XTXPjxg1ERETU+q9/fccQpjpjy5YtmDlz5lPtc/jwYcyePZshXEGZmZkICgpCixYtEBcXhyNHjqB169ZyT6vKzZw5E1u2bJF7Go9148YNzJ49myFcyxnKPQGiquLm5ib3FJ5aUVERFAoFDA1rx1/F33//HUVFRXj11VfRo0cPuadTbVq0aCH3FGRz9+5dmJiYQKFQyD2VeoFHwlRnPHo6uqSkBB988AGcnZ1hamqKRo0aoUOHDvj4448BABEREXjrrbcAAE5OTlAoFHqnJUtKSjB//ny0adMGSqUSarUaI0eOxLVr1/TeVwiBuXPnwtHRESYmJnB3d8fu3bvh7e0Nb29vqe7Bac8NGzYgNDQUTZo0gVKpxKVLl5CZmYkJEyagXbt2aNiwIdRqNXr16oWff/5Z772uXLkChUKBBQsW4MMPP0Tz5s1hamoKb29vKSDfeecdaLVaqFQqDB48GBkZGRX6+m3btg2enp4wMzODhYUF+vbtiyNHjkj9o0ePRvfu3QEAw4YNg0Kh0FtfWa5fv45x48bBwcEBxsbG0Gq1ePnll3Hz5k0AwL179xAaGopOnTpBpVLB2toanp6e+O6770qNpVAoMGnSJKxatQqtW7eGUqlEu3btEBsbW6H1AcBvv/2G/v37w8zMDLa2thg/fjzy8vJK1ZV1OvrTTz/Fiy++CLVaDXNzc7i6umL+/PkoKirSq/P29oaLiwuOHDkCLy8vmJqaonnz5oiKigIAbN++HZ07d4aZmRlcXV0RFxdX6v0vXryIwMBAqNVqKJVKtG3bFp9++qnUf+DAATz33HMAgDFjxkg/uxEREVLN8ePH4e/vD2tra5iYmMDNzQ1ff/213vs8uOyza9cujB07Fo0bN4aZmRl0Ol2Fv6b0bGrH/35TvVVcXIz79++Xaq/Iw7/mz5+PiIgI/Oc//8GLL76IoqIi/Pbbb9Kp59deew23b9/G0qVLsXnzZtjb2wMA2rVrBwB444038Nlnn2HSpEnw8/PDlStXMHPmTBw4cAAnT56Era0tAODdd99FZGQkxo0bh4CAAKSmpuK1115DUVFRmadqw8PD4enpiZUrV6JBgwZQq9XIzMwEAMyaNQsajQb5+fnYsmULvL29sXfv3lJh9+mnn6JDhw749NNPkZ2djdDQUAwaNAgeHh4wMjLCF198gZSUFISFheG1117Dtm3bHvu1+vLLLzFixAj4+Pjgq6++gk6nw/z586X37969O2bOnInnn38eEydOxNy5c9GzZ09YWlqWO+b169fx3HPPoaioCDNmzECHDh1w69Yt7Ny5E1lZWbCzs4NOp8Pt27cRFhaGJk2aoLCwEHv27EFAQACioqIwcuRIvTG3bduG/fv347333oO5uTmWL1+OV155BYaGhnj55Zcfu8abN2+iR48eMDIywvLly2FnZ4eYmBhMmjTpsfs98McffyAwMBBOTk4wNjbG6dOnMWfOHPz222/44osv9GrT09MxZswYTJ8+HU2bNsXSpUsxduxYpKam4ttvv8WMGTOgUqnw3nvv4aWXXsLly5eh1WoBAOfPn4eXlxeaNWuGhQsXQqPRYOfOnZgyZQr+/PNPzJo1C507d0ZUVBTGjBmD//znPxg4cCAAoGnTpgCA/fv3o3///vDw8MDKlSuhUqkQGxuLYcOG4c6dO6XunRg7diwGDhyIDRs2oKCgAEZGRhX6mlAVEEQ1UFRUlADw2M3R0VFvH0dHRzFq1CjptZ+fn+jUqdNj32fBggUCgEhOTtZrv3DhggAgJkyYoNd+9OhRAUDMmDFDCCHE7du3hVKpFMOGDdOrO3LkiAAgevToIbXt379fABAvvvjiE9d///59UVRUJHr37i0GDx4stScnJwsAomPHjqK4uFhqX7JkiQAg/P399caZOnWqACBycnLKfa/i4mKh1WqFq6ur3ph5eXlCrVYLLy+vUmv45ptvnriGsWPHCiMjI3H+/Pkn1j7wYN3BwcHCzc1Nrw+AMDU1Fenp6Xr1bdq0ES1btnzi2G+//bZQKBQiMTFRr71v374CgNi/f7/UNmrUqFI/Xw8rLi4WRUVFYv369cLAwEDcvn1b6uvRo4cAII4fPy613bp1SxgYGAhTU1Nx/fp1qT0xMVEAEJ988onU1q9fP9G0adNS37NJkyYJExMT6b0SEhIEABEVFVVqfm3atBFubm6iqKhIr93Pz0/Y29tL3+cHf89GjhxZ7lqpevF0NNVo69evR0JCQqntwWnRx3n++edx+vRpTJgwATt37kRubm6F33f//v0AUOqI4fnnn0fbtm2xd+9eAEB8fDx0Oh2GDh2qV9e1a9dy764dMmRIme0rV65E586dYWJiAkNDQxgZGWHv3r24cOFCqdoBAwagQYP//+vbtm1bAJCOiB5tv3r1ajkrBZKSknDjxg0EBQXpjdmwYUMMGTIE8fHxuHPnTrn7l2fHjh3o2bOnNIfyfPPNN+jWrRsaNmworXvNmjVlrrt3796ws7OTXhsYGGDYsGG4dOmSdJng/v37epv431mT/fv3o3379ujYsaPemIGBgRVaz6lTp+Dv7w8bGxsYGBjAyMgII0eORHFxMX7//Xe9Wnt7e3Tp0kV6bW1tDbVajU6dOklHvMD/f39SUlIA/HV6fu/evRg8eDDMzMz01jFgwADcu3cP8fHxj53npUuX8Ntvv2HEiBGlvh4DBgxAWloakpKS9PYp72eSqh9DmGq0tm3bwt3dvdSmUqmeuG94eDg++ugjxMfHw9fXFzY2Nujdu3e5v/b0sFu3bgGAdIr6YVqtVup/8N+Hg+GBstrKG3PRokV444034OHhgU2bNiE+Ph4JCQno378/7t69W6re2tpa77WxsfFj2+/du1fmXB5eQ3lrLSkpQVZWVrn7lyczM1M6PVqezZs3Y+jQoWjSpAmio6Nx5MgRJCQkYOzYsWXOWaPRlNv2YB1GRkZ627p166T+x+3/OFevXsULL7yA69ev4+OPP8bPP/+MhIQE6Trto9+jR78PwF/fiyd9f27duoX79+9j6dKlpdYxYMAAAMCff/752Lk+uN4eFhZWaowJEyaUOUZZ33v6e/CaMNVZhoaGmDZtGqZNm4bs7Gzs2bMHM2bMQL9+/ZCamgozM7Ny97WxsQEApKWllQqSGzduSNeDH9Q9+IfvYenp6WUeDZd112l0dDS8vb2xYsUKvfaybhqqag+v9VE3btxAgwYNYGVl9dTjNm7cuNRNbI+Kjo6Gk5MTNm7cqPd1Ke/GoPT09HLbHqwjISFBr9/JyUnqf9z+j7N161YUFBRg8+bNcHR0lNqr+teDrKysYGBggKCgIEycOLHMmgfrKc+Dn83w8HAEBASUWePs7Kz3mndCy4chTPVCo0aN8PLLL+P69euYOnUqrly5gnbt2kGpVAIofSTTq1cvAH+FxIO7UIG//oG/cOEC3n33XQCAh4cHlEolNm7cqPcPXnx8PFJSUir8gQ8KhUKaywO//vorjhw5AgcHh6de79NwdnZGkyZN8OWXXyIsLEz6B7mgoACbNm2S7ph+Wr6+vtiwYQOSkpJK/aP/gEKhgLGxsV4IpKenl3l3NADs3bsXN2/elM4yFBcXY+PGjWjRooX0P0vu7u5l7tuzZ0/Mnz8fp0+f1jsl/eWXXz5xLQ/m9/D3SAiB1atXP3Hfp2FmZoaePXvi1KlT6NChg3SkXJbyfnadnZ3RqlUrnD59GnPnzq3S+VHVYwhTnTVo0CC4uLjA3d0djRs3RkpKCpYsWQJHR0e0atUKAODq6goA+PjjjzFq1CgYGRnB2dkZzs7OGDduHJYuXYoGDRrA19dXujvawcEB//73vwH8ddpx2rRpiIyMhJWVFQYPHoxr165h9uzZsLe317vG+jh+fn54//33MWvWLPTo0QNJSUl477334OTkVObd4VWpQYMGmD9/PkaMGAE/Pz+8/vrr0Ol0WLBgAbKzszFv3rxKjfvee+9hx44dePHFFzFjxgy4uroiOzsbcXFxmDZtGtq0aQM/Pz9s3rwZEyZMwMsvv4zU1FS8//77sLe3x8WLF0uNaWtri169emHmzJnS3dG//fZbhX5NaerUqfjiiy8wcOBAfPDBB9Ld0b/99tsT9+3bty+MjY3xyiuvYPr06bh37x5WrFhRqdP0T/Lxxx+je/fueOGFF/DGG2+gefPmyMvLw6VLl/D9999j3759AP76XWZTU1PExMSgbdu2aNiwIbRaLbRaLVatWgVfX1/069cPo0ePRpMmTXD79m1cuHABJ0+exDfffFPl86ZKkvvOMKKyPLhrMyEhocz+gQMHPvHu6IULFwovLy9ha2srjI2NRbNmzURwcLC4cuWK3n7h4eFCq9WKBg0a6N0lW1xcLD788EPRunVrYWRkJGxtbcWrr74qUlNT9fYvKSkRH3zwgWjatKkwNjYWHTp0ED/88IPo2LGj3p3Nj7uzWKfTibCwMNGkSRNhYmIiOnfuLLZu3VrqLt0Hd0cvWLBAb//yxn7S1/FhW7duFR4eHsLExESYm5uL3r17i19++aVC71Oe1NRUMXbsWKHRaISRkZHQarVi6NCh4ubNm1LNvHnzRPPmzYVSqRRt27YVq1evFrNmzRKP/vMEQEycOFEsX75ctGjRQhgZGYk2bdqImJiYCs1FCCHOnz8v+vbtK0xMTIS1tbUIDg4W3333XYXujv7+++9Fx44dhYmJiWjSpIl46623xI4dO0rt26NHD9G+fftS7+3o6CgGDhxYqv3Buh6WnJwsxo4dK5o0aSKMjIxE48aNhZeXl/jggw/06r766ivRpk0bYWRkJACIWbNmSX2nT58WQ4cOFWq1WhgZGQmNRiN69eolVq5cKdU8zc8HVQ+FEBX4hUsieirJyclo06YNZs2ahRkzZsg9nTpBoVBg4sSJWLZsmdxTIaoyPB1N9IxOnz6Nr776Cl5eXrC0tERSUhLmz58PS0tLBAcHyz09IqrBGMJEz8jc3BzHjx/HmjVrkJ2dDZVKBW9vb8yZM6fcX1MiIgIAno4mIiKSCT+sg4iISCYMYSIiIpkwhImIiGTCG7OqUElJCW7cuAELCwt+DBwRUT0lhEBeXh60Wu0TP7CHIVyFbty4Ue0fMUhERLVDamrqEx9iwhCuQhYWFgD++sI/7mHnRERUd+Xm5sLBwUHKhMdhCFehB6egLS0tGcJERPVcRS5L8sYsIiIimTCEiYiIZMIQJiIikglDmIiISCYMYSIiIpkwhImIiGTCECYiIpIJQ5iIiEgmDGEiIiKZMISJiIhkwhAmIiKSCUOYiIhIJgxhIiIimTCEiYiIZMJHGdZDmZmZyM3NrZaxLS0t0bhx42oZm4iormEI1zOZmZl4dcxruJ13p1rGt7YwQ3TU5wxiIqIKYAjXM7m5ubiddweNPYfA3NquSscuuH0TmUc2ITc3lyFMRFQBDOF6ytzaDpbqplU+bmaVj0hEVHfxxiwiIiKZMISJiIhkwhAmIiKSCUOYiIhIJrwxqwaqzt/jTUlJwf2i+9UyNhERPR2GcA1T3b/He+/uHVy7noZmRUXVMj4REVUcQ7iGqc7f4wWAjD/OIiX1CxTfZwgTEcmNIVxDVdfv8ebfSq/yMYmIqHJ4YxYREZFMGMJEREQyYQgTERHJhCFMREQkE4YwERGRTBjCREREMmEIExERyUTWEP7pp58waNAgaLVaKBQKbN26Va9foVCUuS1YsECq8fb2LtU/fPhwvXGysrIQFBQElUoFlUqFoKAgZGdn69VcvXoVgwYNgrm5OWxtbTFlyhQUFhZW19KJiIjkDeGCggJ07NgRy5YtK7M/LS1Nb/viiy+gUCgwZMgQvbqQkBC9ulWrVun1BwYGIjExEXFxcYiLi0NiYiKCgoKk/uLiYgwcOBAFBQU4dOgQYmNjsWnTJoSGhlb9oomIiP5H1k/M8vX1ha+vb7n9Go1G7/V3332Hnj174h//+Ideu5mZWanaBy5cuIC4uDjEx8fDw8MDALB69Wp4enoiKSkJzs7O2LVrF86fP4/U1FRotVoAwMKFCzF69GjMmTMHlpaWz7JMIiKiMtWaa8I3b97E9u3bERwcXKovJiYGtra2aN++PcLCwpCXlyf1HTlyBCqVSgpgAOjatStUKhUOHz4s1bi4uEgBDAD9+vWDTqfDiRMnyp2TTqdDbm6u3kZERFRRteazo9etWwcLCwsEBATotY8YMQJOTk7QaDQ4e/YswsPDcfr0aezevRsAkJ6eDrVaXWo8tVqN9PR0qcbOTv9hCVZWVjA2NpZqyhIZGYnZs2c/69KIiKieqjUh/MUXX2DEiBEwMTHRaw8JCZH+7OLiglatWsHd3R0nT55E586dAfx1g9ejhBB67RWpeVR4eDimTZsmvc7NzYWDg0PFF0VERPVarTgd/fPPPyMpKQmvvfbaE2s7d+4MIyMjXLx4EcBf15Vv3rxZqi4zM1M6+tVoNKWOeLOyslBUVFTqCPlhSqUSlpaWehsREVFF1YoQXrNmDbp06YKOHTs+sfbcuXMoKiqCvb09AMDT0xM5OTk4duyYVHP06FHk5OTAy8tLqjl79izS0tKkml27dkGpVKJLly5VvBoiIqK/yHo6Oj8/H5cuXZJeJycnIzExEdbW1mjWrBmAv07xfvPNN1i4cGGp/f/44w/ExMRgwIABsLW1xfnz5xEaGgo3Nzd069YNANC2bVv0798fISEh0q8ujRs3Dn5+fnB2dgYA+Pj4oF27dggKCsKCBQtw+/ZthIWFISQkhEe3RERUbWQ9Ej5+/Djc3Nzg5uYGAJg2bRrc3Nzw3//+V6qJjY2FEAKvvPJKqf2NjY2xd+9e9OvXD87OzpgyZQp8fHywZ88eGBgYSHUxMTFwdXWFj48PfHx80KFDB2zYsEHqNzAwwPbt22FiYoJu3bph6NCheOmll/DRRx9V4+qJiKi+k/VI2NvbG0KIx9aMGzcO48aNK7PPwcEBBw8efOL7WFtbIzo6+rE1zZo1ww8//PDEsYiIiKpKrbgmTEREVBcxhImIiGTCECYiIpIJQ5iIiEgmDGEiIiKZMISJiIhkwhAmIiKSCUOYiIhIJgxhIiIimTCEiYiIZMIQJiIikglDmIiISCYMYSIiIpkwhImIiGTCECYiIpIJQ5iIiEgmDGEiIiKZMISJiIhkwhAmIiKSCUOYiIhIJgxhIiIimTCEiYiIZMIQJiIikglDmIiISCYMYSIiIpkwhImIiGTCECYiIpIJQ5iIiEgmDGEiIiKZMISJiIhkwhAmIiKSCUOYiIhIJgxhIiIimTCEiYiIZMIQJiIikglDmIiISCYMYSIiIpkwhImIiGQiawj/9NNPGDRoELRaLRQKBbZu3arXP3r0aCgUCr2ta9euejU6nQ6TJ0+Gra0tzM3N4e/vj2vXrunVZGVlISgoCCqVCiqVCkFBQcjOztaruXr1KgYNGgRzc3PY2tpiypQpKCwsrI5lExERAZA5hAsKCtCxY0csW7as3Jr+/fsjLS1N2n788Ue9/qlTp2LLli2IjY3FoUOHkJ+fDz8/PxQXF0s1gYGBSExMRFxcHOLi4pCYmIigoCCpv7i4GAMHDkRBQQEOHTqE2NhYbNq0CaGhoVW/aCIiov8xlPPNfX194evr+9gapVIJjUZTZl9OTg7WrFmDDRs2oE+fPgCA6OhoODg4YM+ePejXrx8uXLiAuLg4xMfHw8PDAwCwevVqeHp6IikpCc7Ozti1axfOnz+P1NRUaLVaAMDChQsxevRozJkzB5aWllW4aiIior/U+GvCBw4cgFqtRuvWrRESEoKMjAyp78SJEygqKoKPj4/UptVq4eLigsOHDwMAjhw5ApVKJQUwAHTt2hUqlUqvxsXFRQpgAOjXrx90Oh1OnDhR7tx0Oh1yc3P1NiIiooqq0SHs6+uLmJgY7Nu3DwsXLkRCQgJ69eoFnU4HAEhPT4exsTGsrKz09rOzs0N6erpUo1arS42tVqv1auzs7PT6raysYGxsLNWUJTIyUrrOrFKp4ODg8EzrJSKi+kXW09FPMmzYMOnPLi4ucHd3h6OjI7Zv346AgIBy9xNCQKFQSK8f/vOz1DwqPDwc06ZNk17n5uYyiImIqMJq9JHwo+zt7eHo6IiLFy8CADQaDQoLC5GVlaVXl5GRIR3ZajQa3Lx5s9RYmZmZejWPHvFmZWWhqKio1BHyw5RKJSwtLfU2IiKiiqpVIXzr1i2kpqbC3t4eANClSxcYGRlh9+7dUk1aWhrOnj0LLy8vAICnpydycnJw7Ngxqebo0aPIycnRqzl79izS0tKkml27dkGpVKJLly5/x9KIiKgekvV0dH5+Pi5duiS9Tk5ORmJiIqytrWFtbY2IiAgMGTIE9vb2uHLlCmbMmAFbW1sMHjwYAKBSqRAcHIzQ0FDY2NjA2toaYWFhcHV1le6Wbtu2Lfr374+QkBCsWrUKADBu3Dj4+fnB2dkZAODj44N27dohKCgICxYswO3btxEWFoaQkBAe3RIRUbWRNYSPHz+Onj17Sq8fXF8dNWoUVqxYgTNnzmD9+vXIzs6Gvb09evbsiY0bN8LCwkLaZ/HixTA0NMTQoUNx9+5d9O7dG2vXroWBgYFUExMTgylTpkh3Ufv7++v9brKBgQG2b9+OCRMmoFu3bjA1NUVgYCA++uij6v4SEBFRPSZrCHt7e0MIUW7/zp07nziGiYkJli5diqVLl5ZbY21tjejo6MeO06xZM/zwww9PfD8iIqKqUquuCRMREdUlDGEiIiKZMISJiIhkwhAmIiKSCUOYiIhIJgxhIiIimTCEiYiIZMIQJiIikglDmIiISCYMYSIiIpkwhImIiGTCECYiIpIJQ5iIiEgmDGEiIiKZMISJiIhkwhAmIiKSCUOYiIhIJgxhIiIimTCEiYiIZMIQJiIikglDmIiISCYMYSIiIpkwhImIiGTCECYiIpIJQ5iIiEgmDGEiIiKZMISJiIhkwhAmIiKSCUOYiIhIJgxhIiIimTCEiYiIZMIQJiIikglDmIiISCYMYSIiIpkwhImIiGTCECYiIpIJQ5iIiEgmDGEiIiKZMISJiIhkImsI//TTTxg0aBC0Wi0UCgW2bt0q9RUVFeHtt9+Gq6srzM3NodVqMXLkSNy4cUNvDG9vbygUCr1t+PDhejVZWVkICgqCSqWCSqVCUFAQsrOz9WquXr2KQYMGwdzcHLa2tpgyZQoKCwura+lERETyhnBBQQE6duyIZcuWleq7c+cOTp48iZkzZ+LkyZPYvHkzfv/9d/j7+5eqDQkJQVpamrStWrVKrz8wMBCJiYmIi4tDXFwcEhMTERQUJPUXFxdj4MCBKCgowKFDhxAbG4tNmzYhNDS06hdNRET0P4Zyvrmvry98fX3L7FOpVNi9e7de29KlS/H888/j6tWraNasmdRuZmYGjUZT5jgXLlxAXFwc4uPj4eHhAQBYvXo1PD09kZSUBGdnZ+zatQvnz59HamoqtFotAGDhwoUYPXo05syZA0tLy6pYLhERkZ5adU04JycHCoUCjRo10muPiYmBra0t2rdvj7CwMOTl5Ul9R44cgUqlkgIYALp27QqVSoXDhw9LNS4uLlIAA0C/fv2g0+lw4sSJcuej0+mQm5urtxEREVWUrEfCT+PevXt45513EBgYqHdkOmLECDg5OUGj0eDs2bMIDw/H6dOnpaPo9PR0qNXqUuOp1Wqkp6dLNXZ2dnr9VlZWMDY2lmrKEhkZidmzZ1fF8oiIqB6qFSFcVFSE4cOHo6SkBMuXL9frCwkJkf7s4uKCVq1awd3dHSdPnkTnzp0BAAqFotSYQgi99orUPCo8PBzTpk2TXufm5sLBwaHiCyMionqtxp+OLioqwtChQ5GcnIzdu3c/8fps586dYWRkhIsXLwIANBoNbt68WaouMzNTOvrVaDSljnizsrJQVFRU6gj5YUqlEpaWlnobERFRRdXoEH4QwBcvXsSePXtgY2PzxH3OnTuHoqIi2NvbAwA8PT2Rk5ODY8eOSTVHjx5FTk4OvLy8pJqzZ88iLS1Nqtm1axeUSiW6dOlSxasiIiL6i6yno/Pz83Hp0iXpdXJyMhITE2FtbQ2tVouXX34ZJ0+exA8//IDi4mLpaNXa2hrGxsb4448/EBMTgwEDBsDW1hbnz59HaGgo3Nzc0K1bNwBA27Zt0b9/f4SEhEi/ujRu3Dj4+fnB2dkZAODj44N27dohKCgICxYswO3btxEWFoaQkBAe3RIRUbWR9Uj4+PHjcHNzg5ubGwBg2rRpcHNzw3//+19cu3YN27Ztw7Vr19CpUyfY29tL24O7mo2NjbF3717069cPzs7OmDJlCnx8fLBnzx4YGBhI7xMTEwNXV1f4+PjAx8cHHTp0wIYNG6R+AwMDbN++HSYmJujWrRuGDh2Kl156CR999NHf+wUhIqJ6RdYjYW9vbwghyu1/XB8AODg44ODBg098H2tra0RHRz+2plmzZvjhhx+eOBYREVFVqdHXhImIiOoyhjAREZFMGMJEREQyYQgTERHJhCFMREQkE4YwERGRTBjCREREMmEIExERyYQhTEREJBOGMBERkUwYwkRERDJhCBMREcmEIUxERCQThjAREZFMKhXCycnJVT0PIiKieqdSIdyyZUv07NkT0dHRuHfvXlXPiYiIqF6oVAifPn0abm5uCA0NhUajweuvv45jx45V9dyIiIjqtEqFsIuLCxYtWoTr168jKioK6enp6N69O9q3b49FixYhMzOzqudJRERU5zzTjVmGhoYYPHgwvv76a3z44Yf4448/EBYWhqZNm2LkyJFIS0urqnkSERHVOc8UwsePH8eECRNgb2+PRYsWISwsDH/88Qf27duH69ev45///GdVzZOIiKjOMazMTosWLUJUVBSSkpIwYMAArF+/HgMGDECDBn9lupOTE1atWoU2bdpU6WSJiIjqkkqF8IoVKzB27FiMGTMGGo2mzJpmzZphzZo1zzQ5IiKiuqxSIXzx4sUn1hgbG2PUqFGVGZ6IiKheqNQ14aioKHzzzTel2r/55husW7fumSdFRERUH1QqhOfNmwdbW9tS7Wq1GnPnzn3mSREREdUHlQrhlJQUODk5lWp3dHTE1atXn3lSRERE9UGlQlitVuPXX38t1X769GnY2Ng886SIiIjqg0qF8PDhwzFlyhTs378fxcXFKC4uxr59+/Dmm29i+PDhVT1HIiKiOqlSd0d/8MEHSElJQe/evWFo+NcQJSUlGDlyJK8JExERVVClQtjY2BgbN27E+++/j9OnT8PU1BSurq5wdHSs6vkRERHVWZUK4Qdat26N1q1bV9VciIiI6pVKhXBxcTHWrl2LvXv3IiMjAyUlJXr9+/btq5LJERER1WWVCuE333wTa9euxcCBA+Hi4gKFQlHV8yIiIqrzKhXCsbGx+PrrrzFgwICqng8REVG9UalfUTI2NkbLli2rei5ERET1SqVCODQ0FB9//DGEEFU9HyIionqjUqejDx06hP37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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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MzMz7Ny5E1ZWVhgwYADGjx+PZ555Bh9++GFz3h4iIqImUQghRHOfXFVVha+//hoJCQn45ptv0LVrV0yePBkRERFwcXExZT/bBL1eD5VKBZ1O1y5n1OfPn8dzk15D55FTYa/uaPL29UV5uLBzJZI+W40uXbqYvH0iIlNoThbc0wVc5ubmGDNmDP75z3/igw8+wPnz5xETE4OOHTvipZdeMjoHS0RERA27pzA+evQopk6dCjc3NyxduhQxMTE4f/489u7di19//RVPP/20qfpJRER032rWBVxLly7FunXrkJ2djREjRmDDhg0YMWIEOnT4Pds9PT2xZs0aPProoybtLBER0f2oWWG8atUqTJo0CS+//HKj3wndqVMnxMfH31PniIiI2oNmhXHtF2rcjqWlJSZOnNic5omIiNqVZp0zXrduHb744ot667/44gusX7/+njtFRETUnjQrjBcuXAhnZ+d669VqNRYsWHDPnSIiImpPmhXGFy9ehKenZ731Hh4euHTp0j13ioiIqD1pVhir1WqcOHGi3vrjx4/f1fdHExER0f80K4yfe+45zJgxA/v27UN1dTWqq6uxd+9evPHGG3juuedM3UciIqL7WrOupn7//fdx8eJFDBs2DObmvzdRU1ODl156ieeMiYiImqhZYWxpaYktW7bg73//O44fPw5ra2v4+PjAw8PD1P0jIiK67zUrjGt169YN3bp1M1VfiIiI2qVmhXF1dTUSEhLw7bffoqioCDU1NUbb9+7da5LOERERtQfNCuM33ngDCQkJGDlyJLy9vaFQKEzdLyIionajWWGclJSEf/7znxgxYoSp+0NERNTuNOujTZaWlnjkkUdM3RciIqJ2qVlhHB0djY8//hhCCFP3h4iIqN1p1mHqgwcPYt++ffjmm2/Qs2dPWFhYGG3funWrSTpHRETUHjQrjB988EGMGTPG1H0hIiJql5oVxuvWrTN1P4iIiNqtZp0zBoCqqirs2bMHa9asQVlZGQDg8uXLuHbtmsk6R0RE1B40a2Z88eJFhISE4NKlSzAYDBg+fDjs7OywaNEi3Lx5E6tXrzZ1P4mIiO5bzZoZv/HGG/Dz80NJSQmsra2l9WPGjMG3335rss4RERG1B82+mvqHH36ApaWl0XoPDw/8+uuvJukYERFRe9GsmXFNTQ2qq6vrrc/Ly4Odnd09d4qIiKg9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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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hytXrlSqy8/Pl45+dTodUlNTZfsLCgpQVlZW6Qj5Xmq1Gmq1+hFn83D5+fl1emrb3t4eLi4uddY/ERHVTL0I4RUrVsDHxwedOnV6aO2JEydQVlYGNzc3AEBAQACKiopw8OBBdO3aFQCQmpqKoqIidOvWTaqZPXs2cnJypOdt374darUaPj4+dTSrquXn5+PV117Htes36uw1HO1sELvyHwxiIiKFKRrCxcXFOHv2rPQ4MzMT6enpcHR0RIsWLQDcOcX7ww8/YMGCBZWef+7cOcTFxWHAgAFwdnbGyZMnER0djc6dO6N79+4AgPbt2yMkJASRkZHSR5fGjx+PsLAweHp6AgCCg4PRoUMHhIeHY/78+bh27RpiYmIQGRn52K+MNhgMuHb9BlwCXoCtY/VH4bVVcu0K8pPXw2AwMISJiBSmaAgfPnwYQUFB0uO776+OGTMGq1atAgDEx8dDCIFXXnml0vMtLS2xY8cOfPHFFyguLoa7uzsGDhyIGTNmwMzMTKqLi4vDlClTEBwcDAAYPHiw7LPJZmZm2Lp1KyZOnIju3bvD2toaI0eOxGeffVYX064RW0dX2Gub10nf+XXSKxERPSqVEEIoPYiGwmAwQKPRoKioqNZH0OfOncPLYyeg5cCJdRLChrxsnN/6FeK//RpPP/20yfsnImrsHiUL6s3nhImIiBoahjAREZFCGMJEREQKYQgTEREphCFMRESkEIYwERGRQhjCRERECmEIExERKYQhTEREpBCGMBERkUIYwkRERAphCBMRESmEIUxERKQQhjAREZFCGMJEREQKYQgTEREphCFMRESkEIYwERGRQhjCRERECmEIExERKYQhTEREpBCGMBERkUIYwkRERAphCBMRESmEIUxERKQQhjAREZFCGMJEREQKYQgTEREphCFMRESkEIYwERGRQhjCRERECmEIExERKYQhTEREpBCGMBERkUIYwkRERAphCBMRESmEIUxERKQQhjAREZFCGMJEREQKYQgTEREphCFMRESkEIYwERGRQhQN4b1792LQoEHQ6/VQqVTYtGmTbH9ERARUKpVs8/f3l9UYjUZMnjwZzs7OsLW1xeDBg5GdnS2rKSgoQHh4ODQaDTQaDcLDw1FYWCiruXjxIgYNGgRbW1s4OztjypQpKC0trYtpExERAVA4hEtKStCpUycsWbKk2pqQkBDk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rVu3cO7cOamuY8eOaNLkf38aXF1d4e3tLT02MzODk5MT8vLyAAChoaFSfx07dgQA9OzZE9evX8cvv/yCPXv2oFevXggKCsKePXsAALt370avXr2qHOepU6fQokULNG/eXGoLCAio8bp07NgRZmZm0mM3NzdprERPGl6YRVRPmZmZITExEQcOHMD27duxePFifPjhh0hNTa2yvqKiAj4+PoiLi6u0794LoywsLGT7VCpVlW0VFRUAgH/84x+4efOm7LkajQbPPvssdu/ejQMHDqB379547rnnkJ6ejjNnzuD06dOV3se9S1Rxi3OVSlXNKlT2oLESPWkYwkT1mEqlQvfu3dG9e3f83//9Hzw8PLBx40ZYWlqivLxcVtulSxesW7cOWq0W9vb2JhvDU089VWV7YGAgdu3ahdTUVHz00Udo1qwZOnTogI8//hharRbt27ev8nkdOnTAxYsXcfnyZej1egBAcnKyrMbS0hIAKs2RqL7h6Wiieio1NRVz5szB4cOHcfHiRWzYsAH5+flo3749WrZsiV9//RUZGRn4/fffUVZWhlGjRsHZ2RnPP/889u3bh8zMTOzZswdvv/02srOzTT6+wMBAJCQkQKVSoUOHDlJbXFxctaeiAaBv377w9PTE6NGjcfToUezbtw8ffvihrEar1cLa2hoJCQm4cuUKioqKTD5+oseBIUxUT9nb22Pv3r0YMGAA2rZti7/85S9YsGABQkNDERkZCU9PT/j6+sLFxQU///wzbGxssHfvXrRo0QLDhg1D+/btMXbsWNy8edOkR8Z39ezZEwDQq1cv6XRyr169UF5e/sAQbtKkCTZu3Aij0YiuXbvi9ddfx+zZs2U15ubm+PLLL7Fs2TLo9Xo8//zzJh8/0eOgElW9AUNERER1jkfCRERECmEIExERKYQhTEREpBCGMBERkUIYwkRERAphCBMRESmEIUxERKQQhjAREZFCGMJEREQKYQgTEREphCFMRESkkP8PMT4IpBGBhNcAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "numeric_columns = X_train.select_dtypes(include='number') # Select only numeric columns\n", + "\n", + "for column in numeric_columns.columns:\n", + " plt.figure(figsize=(5,5))\n", + " plt.hist(X_train[column], bins=15, edgecolor='black', alpha=0.7)\n", + " plt.title(f'Histogram of {column}')\n", + " plt.xlabel(column)\n", + " plt.ylabel('Frequency')\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "717bbe9d-18ee-4463-9a52-9128566851d5", + "metadata": {}, + "source": [ + "Based on the histograms, here are our findings for each feature being plotted.\n", + "\n", + "1. `cap-diameter`: The distribution is highly skewed to the right, with most values concentrated between 0 and 10 cm. There are also some outliers sitting at around 40 to 60 cm. \n", + "\n", + "2. `stem-height`: Slightly right-skewed distribution. The majority of mushrooms have stem heights between 4 and 10 cm, with few having stem heights over 20 cm.\n", + "\n", + "3. `stem-width`: Another heavily right-skewed distribution, with the majority of mushrooms having stem width below 20 cm, and a some rare cases exceeding 50 cm.\n", + "\n", + "The skewness observed across the 3 numeric features will be addressed in the preprocessing phase with `QuantileTransformer` from `sklearn.preprocessing` which maps data to a normal distribution while retaining the relative rank of values, making them more suitable for models sensitive to feature distributions, such as `SVC` and `LogisticRegression`. " + ] + }, + { + "cell_type": "markdown", + "id": "1b80b242-d2c4-48ba-9124-0f1a75233cf7", + "metadata": {}, + "source": [ + "##### Part 3: The distribution of categorical features" + ] + }, + { + "cell_type": "markdown", + "id": "fc0e83a8-e064-416d-9043-c9a340d24f18", + "metadata": {}, + "source": [ + "To understand the categorical features in the data set, we analyzed their frequency and percentage distributions, providing insights into the variability and class imbalance that might occur for each feature. " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "c5d9010f-313a-4abf-a50c-e55c3b64b186", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Frequency and Percentage for 'cap-shape':\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 FrequencyPercentage
cap-shape  
x2151044.15
f1069821.96
s571711.73
b46159.47
o26345.41
p20984.31
c14502.98
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---------------------------------------- \n", + "\n", + "Frequency and Percentage for 'cap-color':\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 FrequencyPercentage
cap-color  
n1940739.83
y687614.11
w617512.67
g34107.00
e32056.58
o29055.96
r13992.87
u13552.78
p13322.73
k10162.09
b9641.98
l6781.39
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---------------------------------------- \n", + "\n", + "Frequency and Percentage for 'does-bruise-or-bleed':\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 FrequencyPercentage
does-bruise-or-bleed  
f4033382.78
t838917.22
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---------------------------------------- \n", + "\n", + "Frequency and Percentage for 'gill-color':\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 FrequencyPercentage
gill-color  
w1483630.45
n774215.89
y759515.59
p47699.79
g32956.76
f27345.61
o23124.75
k19083.92
r11312.32
e8421.73
u8271.70
b7311.50
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---------------------------------------- \n", + "\n", + "Frequency and Percentage for 'stem-color':\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 FrequencyPercentage
stem-color  
w1837737.72
n1447829.72
y629112.91
g20904.29
o17333.56
e16283.34
u11892.44
p8141.67
f7051.45
k6761.39
r4200.86
l1810.37
b1400.29
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---------------------------------------- \n", + "\n", + "Frequency and Percentage for 'has-ring':\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 FrequencyPercentage
has-ring  
f3649574.90
t1222725.10
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---------------------------------------- \n", + "\n", + "Frequency and Percentage for 'ring-type':\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 FrequencyPercentage
ring-type  
f3844082.28
e19644.20
z17133.67
l11512.46
r11292.42
p10282.20
g10052.15
m2870.61
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---------------------------------------- \n", + "\n", + "Frequency and Percentage for 'habitat':\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 FrequencyPercentage
habitat  
d3516272.17
g640313.14
l25395.21
m23444.81
h15983.28
p2980.61
w2880.59
u900.18
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---------------------------------------- \n", + "\n", + "Frequency and Percentage for 'season':\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 FrequencyPercentage
season  
a2407949.42
u1830037.56
w41498.52
s21944.50
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---------------------------------------- \n", + "\n" + ] + } + ], + "source": [ + "categorical_columns = X_train.select_dtypes(include='object') # Select only categorical columns\n", + "\n", + "# Calculate frequency and percentage for each categorical features\n", + "for column in categorical_columns.columns:\n", + " print(f\"Frequency and Percentage for '{column}':\")\n", + " \n", + " # Frequency\n", + " frequency = X_train[column].value_counts()\n", + " # Percentage\n", + " percentage = round(X_train[column].value_counts(normalize=True) * 100, 2)\n", + " \n", + " # Combine into one DataFrame\n", + " freq_percent_df = pd.DataFrame({\n", + " \"Frequency\": frequency,\n", + " \"Percentage\": percentage\n", + " })\n", + "\n", + " # Highlight values with a gradient\n", + " styled_df = freq_percent_df.style.format(\n", + " precision=2\n", + " ).background_gradient(\n", + " subset=['Percentage'],\n", + " cmap='YlOrRd'\n", + " )\n", + "\n", + " # Display the styled DataFrame\n", + " display(styled_df)\n", + " print(\"-\" * 40, '\\n')" + ] + }, + { + "cell_type": "markdown", + "id": "12823bac-ddf4-47d7-bda9-785b424a1837", + "metadata": {}, + "source": [ + "Based on the Frequency and Percentage distributions, here are our findings:\n", + "\n", + "1. `cap-shape`: The most common cap shape is `x` (convex), comprising 43.97% of the data. Other shapes like `f` (flat) and `s` (sunken) are also prevalent, while `c` (conical) is the least common with 2.95% appearance.\n", + "\n", + "2. `cap-color`: The most frequently appeared color is `n` (brown), with 39.71% of the data. Other colors like `y` (yellow), `w` (white), and `g` (gray) are also well-represented, while rare colors like `b` (buff) and `l` (blue) appear in less than 2% of the data.\n", + "\n", + "3. `does-bruise-or-bleed`: The majority of the mushrooms are `f` (do not bruise or bleed), while their counterpart make up 17.26% of the data.\n", + "\n", + "4. `gill-color`: The most common gill color is `w` (white), with 30.45% of the data. Other colors such as `n` (brown) and `y` (yellow) are also frequent, while rare gill colors like `e` (red), `b` (buff) and `u` (purple) appear in less than 2% of the data.\n", + "\n", + "5. `stem-color`: `w` (white) and `n` (brown) are the dominating stem colors, accounting for 37.75% and 29.5% of the data, respectively. Other colors like `r` (green), `l` (blue) and `b` (buff) are less frequent, appearing in less than 1% of the observations.\n", + "\n", + "6. `has-ring`: Most mushrooms are `f` (do not have a ring), with 74.84% observations. The remaining 25.16% mushrooms are `t` (have a ring).\n", + "\n", + "7. `ring-type`: `f` (none) is the most common ring type, accounting for 82.3% of the data. Other types like `e` (evanescent) and `z` (zone) are less frequent, while rare types like `m` (movable) occur in less than 1% of the data.\n", + "\n", + "8. `habitat`: The predominant habitat is `d` (woods), with 72.46% appearance. Other habitats such as `g` (grasses) and `l` (leaves) are less common, while `w` (waste), `p` (paths), and `u` (urban) only make up less than 1% of the data individually.\n", + "\n", + "9. `season`: Most mushrooms grow in `a` (autumn), comprising 49.36% of the data, followed by `u` (summer) at 37.5%. The other two seasons `w` (winter) and `s` (spring) are less frequent.\n", + "\n", + "Categorical features will be encoded into binary format in the following preprocessing phase with `OneHotEncoder`. Since we are dealing with a mix of binary and non-binary categorical features, for features like `does-bruise-or-bleed` and `has-ring` that have two unique values, they will be handled with `drop='if_binary'` argument to reduce redundancy while still capturing the information. " + ] + }, + { + "cell_type": "markdown", + "id": "a8a13abe-906b-4230-8772-2d799a51a857", + "metadata": {}, + "source": [ + "##### Part 4: The distribution of the target" + ] + }, + { + "cell_type": "markdown", + "id": "e175de25-1893-40f0-a794-1153470d7230", + "metadata": {}, + "source": [ + "The target variable `class` represents whether a mushroom is `p` (poisonous) or `e` (edible). Understanding the distribution of the target helps assessing class balance, which might have impact on models' performance." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "9e47fdb0-f94a-4777-a3c1-954e7d62202a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
FrequencyPercentage
target
p2699655.41
e2172644.59
\n", + "
" + ], + "text/plain": [ + " Frequency Percentage\n", + "target \n", + "p 26996 55.41\n", + "e 21726 44.59" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + " # Frequency\n", + "frequency = y_train.value_counts()\n", + "# Percentage\n", + "percentage = round(y_train.value_counts(normalize=True) * 100, 2)\n", + "\n", + "# Combine into one DataFrame\n", + "freq_percent_df = pd.DataFrame({\n", + " \"Frequency\": frequency,\n", + " \"Percentage\": percentage\n", + "})\n", + "freq_percent_df" + ] + }, + { + "cell_type": "markdown", + "id": "10f25100-5adc-46c3-8503-6faebcc29100", + "metadata": {}, + "source": [ + "Based on the Frequency and Percentage distribution, here are our findings:\n", + "\n", + "1. `p` (Poisonous): There are 27,143 instances of poisonous mushrooms, accounting for 55.56% of the data.\n", + "\n", + "2. `e` (Edible): There are 21,712 instances of edible mushrooms, constituting 44.44% of the data.\n", + "\n", + "Using $F_{\\beta}$, precision, recall, or confusion matrix to evaluate the model's performance is advisable in the following procedure. " + ] + }, + { + "cell_type": "markdown", + "id": "e6000a8d-7e7b-4fd1-aa27-b3c8074e6d91", + "metadata": {}, + "source": [ + "#### Preprocessing and Model Building\n", + "\n", + "Three classification models including Support Vector Classifier (SVC), K-Nearest Neighbors (KNN), and Logistic Regression are used to predict whether a mushroom is edible or poisonous. Predicting a mushroom to be edible when it is in fact poisonous could have severe health consequences. Therefore the best model should prioritize the minimization of this error. To do this, we can evaluate models on an $F_{\\beta}$ score with $\\beta = 2$." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "2b26607e-2448-452d-8e0b-e25c56ceba44", + "metadata": {}, + "outputs": [], + "source": [ + "# loading in some models\n", + "from sklearn.neighbors import KNeighborsClassifier\n", + "from sklearn.svm import SVC\n", + "from sklearn.linear_model import LogisticRegression" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "32e69dc9-c9c6-4734-8f01-37a6813ef1d8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
ColumnTransformer(transformers=[('quantiletransformer',\n",
+       "                                 QuantileTransformer(output_distribution='normal',\n",
+       "                                                     random_state=123),\n",
+       "                                 ['cap-diameter', 'stem-height', 'stem-width']),\n",
+       "                                ('pipeline',\n",
+       "                                 Pipeline(steps=[('simpleimputer',\n",
+       "                                                  SimpleImputer(fill_value='missing',\n",
+       "                                                                strategy='constant')),\n",
+       "                                                 ('onehotencoder',\n",
+       "                                                  OneHotEncoder(drop='if_binary',\n",
+       "                                                                handle_unknown='ignore',\n",
+       "                                                                sparse_output=False))]),\n",
+       "                                 ['ring-type']),\n",
+       "                                ('onehotencoder',\n",
+       "                                 OneHotEncoder(drop='if_binary',\n",
+       "                                               handle_unknown='ignore',\n",
+       "                                               sparse_output=False),\n",
+       "                                 ['does-bruise-or-bleed', 'has-ring',\n",
+       "                                  'cap-shape', 'cap-color', 'gill-color',\n",
+       "                                  'stem-color', 'habitat', 'season'])])
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" + ], + "text/plain": [ + "ColumnTransformer(transformers=[('quantiletransformer',\n", + " QuantileTransformer(output_distribution='normal',\n", + " random_state=123),\n", + " ['cap-diameter', 'stem-height', 'stem-width']),\n", + " ('pipeline',\n", + " Pipeline(steps=[('simpleimputer',\n", + " SimpleImputer(fill_value='missing',\n", + " strategy='constant')),\n", + " ('onehotencoder',\n", + " OneHotEncoder(drop='if_binary',\n", + " handle_unknown='ignore',\n", + " sparse_output=False))]),\n", + " ['ring-type']),\n", + " ('onehotencoder',\n", + " OneHotEncoder(drop='if_binary',\n", + " handle_unknown='ignore',\n", + " sparse_output=False),\n", + " ['does-bruise-or-bleed', 'has-ring',\n", + " 'cap-shape', 'cap-color', 'gill-color',\n", + " 'stem-color', 'habitat', 'season'])])" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# importing required preprocessors, pipelines, etc.\n", + "from sklearn.impute import SimpleImputer\n", + "from sklearn.preprocessing import QuantileTransformer,OneHotEncoder\n", + "from sklearn.compose import make_column_transformer\n", + "from sklearn.pipeline import make_pipeline\n", + "\n", + "# converting targets to Series objects to avoid warnings\n", + "y_train = y_train.squeeze()\n", + "y_test = y_test.squeeze()\n", + "\n", + "# random state for reproducability\n", + "SEED = 123\n", + "\n", + "# feature sets for each transformation\n", + "numeric_cols = ['cap-diameter','stem-height','stem-width']\n", + "categorical_cols = ['does-bruise-or-bleed','has-ring','cap-shape','cap-color','gill-color','stem-color','habitat','season']\n", + "impute_cols = ['ring-type']\n", + "\n", + "# creating transformers\n", + "numeric_transformer = QuantileTransformer(output_distribution='normal',random_state=SEED)\n", + "categorical_transformer = OneHotEncoder(drop='if_binary',handle_unknown='ignore',sparse_output=False)\n", + "impute_transformer = make_pipeline(\n", + " SimpleImputer(strategy='constant',fill_value = 'missing'),\n", + " categorical_transformer\n", + ")\n", + "\n", + "# final preprocessor\n", + "preprocessor = make_column_transformer(\n", + " (numeric_transformer,numeric_cols),\n", + " (impute_transformer,impute_cols),\n", + " (categorical_transformer,categorical_cols)\n", + ")\n", + "preprocessor" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "1a03aff3-0dd9-4d8d-acff-9a57fc86a6a8", + "metadata": {}, + "outputs": [], + "source": [ + "# create model pipelines\n", + "svc = make_pipeline(preprocessor,SVC(random_state=SEED))\n", + "knn = make_pipeline(preprocessor,KNeighborsClassifier())\n", + "logreg = make_pipeline(preprocessor,LogisticRegression(max_iter=5000,random_state=SEED))" + ] + }, + { + "cell_type": "markdown", + "id": "b80b1c6f-a12f-4b03-8ae6-384513426051", + "metadata": {}, + "source": [ + "#### Model Evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "23716434-2c8d-4a6e-8627-dfbcc2a70eb8", + "metadata": {}, + "outputs": [], + "source": [ + "# decide which metrics to use: f_beta score? Weighted to lower false positives\n", + "from sklearn.metrics import ConfusionMatrixDisplay, make_scorer, fbeta_score, accuracy_score, precision_score, recall_score\n", + "from sklearn.model_selection import cross_validate, cross_val_predict, GridSearchCV, RandomizedSearchCV" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "b81f3323-048e-4911-82a6-c80f5af91105", + "metadata": {}, + "outputs": [], + "source": [ + "# define the hyperparameter grid\n", + "from scipy.stats import loguniform, randint\n", + "\n", + "knn_grid = {'kneighborsclassifier__n_neighbors':randint(5,1000)}\n", + "\n", + "svc_grid = {'svc__C':loguniform(1e-3,1e3),\n", + " 'svc__gamma':loguniform(1e-3,1e3)}\n", + "\n", + "logreg_grid = {'logisticregression__C':loguniform(1e-3,1e3)}" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "3b1c6975-7d4d-4834-9ae8-17caea713141", + "metadata": {}, + "outputs": [], + "source": [ + "# create metrics\n", + "scoring_metrics = {\n", + " 'accuracy':make_scorer(accuracy_score),\n", + " 'f2_score':make_scorer(fbeta_score,beta=2,pos_label='p',average='binary') \n", + "}\n", + "cv_results = dict()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "038cd3ae-2375-4350-b564-39d243b37dae", + "metadata": {}, + "outputs": [], + "source": [ + "# hyperparameter tuning\n", + "cv_results['logreg'] = RandomizedSearchCV(\n", + " logreg,logreg_grid,n_iter=30,n_jobs=-1,\n", + " scoring=scoring_metrics,random_state=SEED,\n", + " refit='f2_score'\n", + ").fit(X_train,y_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "71ef0579-1ba4-4f5a-bf9e-160ada934a8b", + "metadata": {}, + "outputs": [], + "source": [ + "cv_results['svc'] = RandomizedSearchCV(\n", + " svc,svc_grid,n_iter=3,n_jobs=-1,cv=3,\n", + " scoring=scoring_metrics,random_state=SEED,\n", + " refit='f2_score'\n", + ").fit(X_train,y_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "434f3c94-b7bf-4c7a-919e-31e67b637b46", + "metadata": {}, + "outputs": [], + "source": [ + "cv_results['knn'] = RandomizedSearchCV(\n", + " knn,knn_grid,n_iter=5,n_jobs=-1,cv=3,\n", + " scoring=scoring_metrics,random_state=SEED,\n", + " refit='f2_score'\n", + ").fit(X_train,y_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "1c18117a-eaa9-4d89-85ca-ccabc5553f10", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
paramsmean_fit_timemean_test_accuracystd_test_accuracymean_test_f2_scorestd_test_f2_score
Logisic Regression{'logisticregression__C': 0.05784745785308777}0.3356790.7465010.0037110.7793130.003517
SVC{'svc__C': 20.74024196289186, 'svc__gamma': 0....34.7748240.9965720.0003190.9970740.000163
KNN{'kneighborsclassifier__n_neighbors': 327}0.1048820.9318170.0017840.9368280.001980
\n", + "
" + ], + "text/plain": [ + " params \\\n", + "Logisic Regression {'logisticregression__C': 0.05784745785308777} \n", + "SVC {'svc__C': 20.74024196289186, 'svc__gamma': 0.... \n", + "KNN {'kneighborsclassifier__n_neighbors': 327} \n", + "\n", + " mean_fit_time mean_test_accuracy std_test_accuracy \\\n", + "Logisic Regression 0.335679 0.746501 0.003711 \n", + "SVC 34.774824 0.996572 0.000319 \n", + "KNN 0.104882 0.931817 0.001784 \n", + "\n", + " mean_test_f2_score std_test_f2_score \n", + "Logisic Regression 0.779313 0.003517 \n", + "SVC 0.997074 0.000163 \n", + "KNN 0.936828 0.001980 " + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# compilng hyperparameters and scores of best models into one dataframe\n", + "cols = ['params','mean_fit_time','mean_test_accuracy','std_test_accuracy','mean_test_f2_score','std_test_f2_score']\n", + "final_results = pd.concat(\n", + " [pd.DataFrame(result.cv_results_).query('rank_test_f2_score == 1')[cols] for _,result in cv_results.items()]\n", + ")\n", + "final_results.index = ['Logisic Regression','SVC','KNN']\n", + "final_results" + ] + }, + { + "cell_type": "markdown", + "id": "6c8c2497-cce7-4473-9604-2fee9235914f", + "metadata": {}, + "source": [ + "After tuning the hyperparameter, the Logistic Regression model has the mean accuracy of 0.75 and mean $F_{\\beta}$ score of 0.78 on the validation set. The KNN model has the mean accuracy of 0.93 and mean $F_{\\beta}$ score of 0.94. The SVC outperforms both Logistic Regression and KNN significantly in both accuracy of 0.99 and $F_{\\beta}$ score of 0.99. Thus, SVC is the ideal choice to identify edible or poisonous mushroom (recall is the highest priority)." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "9764dd35-0038-4c6d-8214-26700bf4052e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAg0AAAGwCAYAAAAqpFaiAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABA1ElEQVR4nO3deXhU9dn/8c9km4SQDISQhEBEUIhgIiIoCfgILgRQttqnaKkRWgwqAkVArOCCWogbi0qLFC1QhAf91eKGjWBVWoSARKMCkWrZgiQkSkggZJ05vz8iQ8eAznAmJOS8X9d1rjLnfM+Ze6Zj5p77uxybYRiGAAAAfkJAYwcAAADODyQNAADAKyQNAADAKyQNAADAKyQNAADAKyQNAADAKyQNAADAK0GNHYAZLpdLhw4dUkREhGw2W2OHAwDwkWEYOnbsmOLj4xUQ0HC/YysrK1VdXW36OiEhIQoNDfVDROen8zppOHTokBISEho7DACASfn5+erQoUODXLuyslKdOrZUYZHT9LXi4uK0d+9eyyYO53XSEBERIUmavGGg7OHBjRwN0DA+7stnG81XrWq0Se+4/543hOrqahUWObU/50JFRpx9NaPsmEsde+1TdXU1ScP56GSXhD08WPaW/GFF8xRk47ONZuz7Gxmciy7mlhE2tYw4++dxiW7w8zppAADAW07DJaeJuy05DZf/gjlPkTQAACzBJUMunX3WYObc5oIplwAAwCtUGgAAluCSS2Y6GMyd3TyQNAAALMFpGHIaZ9/FYObc5oLuCQAA4BUqDQAAS2AgpHkkDQAAS3DJkJOkwRS6JwAAgFeoNAAALIHuCfNIGgAAlsDsCfPongAAAF6h0gAAsATX95uZ862OpAEAYAlOk7MnzJzbXJA0AAAswWnI5F0u/RfL+YoxDQAAwCtUGgAAlsCYBvNIGgAAluCSTU7ZTJ1vdXRPAAAAr1BpAABYgsuo28ycb3VUGgAAluD8vnvCzOaLzMxMXXnllYqIiFBMTIxGjhyp3bt3e7QZO3asbDabx5aSkuLRpqqqSpMmTVJ0dLTCw8M1fPhwHTx40KNNSUmJ0tPT5XA45HA4lJ6erqNHj3q0OXDggIYNG6bw8HBFR0dr8uTJqq6u9uk1kTQAANAANm7cqHvuuUfZ2dnasGGDamtrlZaWpvLyco92gwcPVkFBgXt75513PI5PmTJFa9eu1Zo1a7Rp0yYdP35cQ4cOldPpdLcZPXq0cnNzlZWVpaysLOXm5io9Pd193Ol06qabblJ5ebk2bdqkNWvW6LXXXtO0adN8ek10TwAALOFsqgU/PN8XWVlZHo+XLVummJgY5eTk6JprrnHvt9vtiouLO+01SktL9dJLL2nlypW64YYbJEkvv/yyEhIS9N5772nQoEHKy8tTVlaWsrOz1adPH0nS0qVLlZqaqt27dysxMVHr16/Xrl27lJ+fr/j4eEnSvHnzNHbsWM2ZM0eRkZFevSYqDQAAS3AZNtObJJWVlXlsVVVVXj1/aWmpJCkqKspj/4cffqiYmBh17dpVGRkZKioqch/LyclRTU2N0tLS3Pvi4+OVlJSkzZs3S5K2bNkih8PhThgkKSUlRQ6Hw6NNUlKSO2GQpEGDBqmqqko5OTlev4ckDQAA+CAhIcE9dsDhcCgzM/MnzzEMQ1OnTtXVV1+tpKQk9/4hQ4Zo1apVev/99zVv3jx9/PHHuu6669yJSGFhoUJCQtS6dWuP68XGxqqwsNDdJiYmpt5zxsTEeLSJjY31ON66dWuFhIS423iD7gkAgCX4q3siPz/fo5xvt9t/8tyJEyfq888/16ZNmzz233LLLe5/JyUlqXfv3urYsaPWrVunm2+++YzXMwxDNtup1/Lf/zbT5qdQaQAAWIJTAaY3SYqMjPTYfippmDRpkt5880198MEH6tChw4+2bdeunTp27KivvvpKkhQXF6fq6mqVlJR4tCsqKnJXDuLi4nT48OF61youLvZo88OKQklJiWpqaupVIH4MSQMAwBIMk+MZDMO3KoVhGJo4caL+9re/6f3331enTp1+8pzvvvtO+fn5ateunSSpV69eCg4O1oYNG9xtCgoKtGPHDvXt21eSlJqaqtLSUm3bts3dZuvWrSotLfVos2PHDhUUFLjbrF+/Xna7Xb169fL6NdE9AQBAA7jnnnu0evVqvfHGG4qIiHD/0nc4HAoLC9Px48c1e/Zs/fznP1e7du20b98+zZw5U9HR0frZz37mbjtu3DhNmzZNbdq0UVRUlKZPn67k5GT3bIpu3bpp8ODBysjI0JIlSyRJ48eP19ChQ5WYmChJSktLU/fu3ZWenq6nn35aR44c0fTp05WRkeH1zAmJSgMAwCLO9eJOixcvVmlpqQYMGKB27dq5t1deeUWSFBgYqC+++EIjRoxQ165dNWbMGHXt2lVbtmxRRESE+zoLFizQyJEjNWrUKPXr108tWrTQW2+9pcDAQHebVatWKTk5WWlpaUpLS9Nll12mlStXuo8HBgZq3bp1Cg0NVb9+/TRq1CiNHDlSzzzzjE+vyWYYxnm7MGZZWZkcDofu23yj7C2DGzscoEFk9+Czjear1qjRh3pDpaWlPv3i9cXJ74q/f95J4RFn/1u5/JhLQy7b26CxNnVUGgAAgFcY0wAAsASXbHKZ+K3s0nlbmPcbkgYAgCWc62WkmyO6JwAAgFeoNAAALMFpBMhpnP1vZef5O2/Ab0gaAACWUDem4ey7GMyc21zQPQEAALxCpQEAYAmu/7p/xNmdT/cESQMAwBIY02AeSQMAwBJcCmCdBpMY0wAAALxCpQEAYAlOwyanj7e3/uH5VkfSAACwBKfJgZBOuifongAAAN6h0gAAsASXESCXidkTLmZPkDQAAKyB7gnz6J4AAABeodIAALAEl8zNgHD5L5TzFkkDAMASzC/uRHGedwAAAHiFSgMAwBLM33uC39kkDQAAS3DJJpfMjGlgRUiSBgCAJVBpMI93AAAAeIVKAwDAEswv7sTvbJIGAIAluAybXGbWaeAul6RNAADAO1QaAACW4DLZPcHiTiQNAACLMH+XS5IG3gEAAOAVKg0AAEtwyianiQWazJzbXJA0AAAsge4J83gHAACAV6g0AAAswSlzXQxO/4Vy3iJpAABYAt0T5pE0AAAsgRtWmcc7AAAAvEKlAQBgCYZscpkY02Aw5ZKkAQBgDXRPmMc7AAAAvEKlAQBgCdwa2zySBgCAJThN3uXSzLnNBe8AAADwCpUGAIAl0D1hHkkDAMASXAqQy0SB3cy5zQXvAAAA8AqVBgCAJTgNm5wmuhjMnNtckDQAACyBMQ3mkTQAACzBMHmXS4MVIRnTAAAAvEOlAQBgCU7Z5DRx0ykz5zYXJA0AAEtwGebGJbgMPwZznqJ7AgAAeIVKQzP2zUsBOvIPmyr22hRglyIuN3TBFKfCLjzV5sh7Nh3+a4DK82yqPWpT8is1Cr+k/rWOfWZT/vMBOv6FTbZgqUWioW5/cCogVCr92Ka8O07/UUpaVauWSXXp+fEdNh14tu65JKnlpYYuuNd52ucDzpVbJh7Wb2YWau3SaL3wSHtJUmgLp8bNKlDqoDJFtq7V4YMheuOlaL39l+hGjhZmuEwOhDRzbnNB0tCMlW23KfYWl1peashwSvnPByrvriD1+FutAlvUtXFW1CUTbdJc2vPo6T8Oxz6z6csJgYr/jUsX/s4pW7B04t82d50q4nJDV/yjxuOcg38IVGm2TeGX1iUMznIp7+5ARQ0w1GlWrYxa6eDiQH15d5B6rq9VQHCDvQ3AGXXtcUI33nZEe3aGeuy/69FD6tH3uJ6adIEO54foiv7HNCnzoL47HKwt7zoaKVqY5ZJNLhPjEsyc21yQNjVj3RY7FTPCUIuLpfBE6aLHnKousLl/6UtS22GGOtzlUmSfM3fW7X86QHG/dKn9OJdaXCyFdZTaDDQUEFJ3PCBYCok+tQU5pJIPbWo70iXb909Vsc8mZ5lNHe6pq3S0uFjqcJdTNUdsqi5swDcBOIPQFk7dv2i/Ft7XQcdKAz2Odet1Qhv+X5Q+39JShw+G6O+r2mjPrjB1uexEI0ULNA0kDRbiPF73v0GR3o/mqflOOv5FgIKjpB23Byrn2iDt/E2gyj45c8ZdstGmmqNS2xEu976wCw0FtTZUtDZArhrJVSkVrQ1Q2EWG7O3O9hUBZ2/i3G+07R+R+vRfEfWO7dwWrpS0UrWJq5FkqEff42rfuUo5G+u3xfnj5IqQZjara/SkwTAMPfXUU+rcubPCwsLUo0cP/fWvf23ssJodw5D2PxOoiJ4uteji/XmV39T9R3LwhQDF3OzSJX+sVXg3Q3njA1Wx//TnFK8NUKu+huxxp/YFhkvdX6zVt+sCtO2qIG1LDdLRzQG65A+1stFJhnOs/4gSXZxcoT9nnj5j/eND8Trw71Ct/mSX1u3/XL9ftUeLHmivndtanuNI4U8nxzSY2ayu0d+BBx98UMuWLdPixYu1c+dO3Xvvvbrtttu0cePGem2rqqpUVlbmscE7+zIDVP6VTRc/6fTtxO+LBTH/61LMSEPh3aQL73Mp7EKp+PX6H5+qw9LRzTa1/ZnL8zKV0n8eCVTE5YaSVjp16QqnWlxk6Mt7guSqPMsXBZyFtvHVuvuxQ3pq0gWqqTr9n8CR477VJb1O6OExF2ri4K5a+li8JmZ+o57/c+wcR4vzWWZmpq688kpFREQoJiZGI0eO1O7duz3aGIah2bNnKz4+XmFhYRowYIB27tzp0aaqqkqTJk1SdHS0wsPDNXz4cB08eNCjTUlJidLT0+VwOORwOJSenq6jR496tDlw4ICGDRum8PBwRUdHa/LkyaqurvbpNTVq0lBeXq758+frz3/+swYNGqTOnTtr7Nixuu2227RkyZJ67TMzM91viMPhUEJCQiNEff7Zmxmgkg8D1H1preyxvp0bHF3XlRHW2bNLI7SToarC+qW64tcDFOSQWvf3bP/tOzZVH7LposecaplkKOIyQxc/4VTVN9KRDyj54dy5+LIKtW5bq0VZ/9Y7Bz7TOwc+U4++5Rox7lu9c+Az2cOcGvu7Qv1pdry2bnBob16Y3lwWrY1vttL/3lXc2OHDBJds7vtPnNXm40DIjRs36p577lF2drY2bNig2tpapaWlqby83N3mqaee0vz587Vo0SJ9/PHHiouL08CBA3Xs2KkEdcqUKVq7dq3WrFmjTZs26fjx4xo6dKiczlM/AkePHq3c3FxlZWUpKytLubm5Sk9Pdx93Op266aabVF5erk2bNmnNmjV67bXXNG3aNJ9eU6MWhnft2qXKykoNHDjQY391dbV69uxZr/0DDzygqVOnuh+XlZWROPwIw6irMBx5P0DdX6pVaAffr2FvLwW3NVS5zybpVCJQud+mVld7VhMMQyp+I0Bth7nqzYZwVX4/2+K//puz2b5/zIIpOIdy/9VS46/t6rFv2oJ85X8dqlf/0FaBgVJwiCGX58dbLqdkC+DDej4zTM6eMHw8Nysry+PxsmXLFBMTo5ycHF1zzTUyDEMLFy7UrFmzdPPNN0uSVqxYodjYWK1evVp33nmnSktL9dJLL2nlypW64YYbJEkvv/yyEhIS9N5772nQoEHKy8tTVlaWsrOz1adPH0nS0qVLlZqaqt27dysxMVHr16/Xrl27lJ+fr/j4eEnSvHnzNHbsWM2ZM0eRkZFevaZGTRpc3/9XuW7dOrVv397jmN1ur9febrefdj9Ob9/cAH379wAlLnQqMFyq/rZuf1BLKeD7GWa1pVJVgVRdXPcfQ8X3yUHw9zMhbDYpfqxLBxcHqEWiofBEQ8VvBqhin9R1nudf1bJtNlV9Y1PMD7omJMmR6tL+BQHaN7duJobhkg79OVC2ICnySv4Q49ypKA/U/t1hHvsqTwToWMmp/Z9tDlfGQwWqrgzQ4YPBuiy1XDf8b4n+9Gh8Y4QMP/HXXS5/2DXu7XdTaWmpJCkqKkqStHfvXhUWFiotLc3jWv3799fmzZt15513KicnRzU1NR5t4uPjlZSUpM2bN2vQoEHasmWLHA6HO2GQpJSUFDkcDm3evFmJiYnasmWLkpKS3AmDJA0aNEhVVVXKycnRtdde69V70KhJQ/fu3WW323XgwAH179+/MUNplg6/WjeNbNc4z/+bOz9Wq5gRdV/URz60ac/Dp45/fX/dv9vf5VTC3XVf/u1uc8lVJe1/OlC1pd8v7PSCU6E/KPIUrQ1Qy8tdCutcP5awTlLic05980KAdtweJNmk8EsMXfJHp0La+usVA/6ReXdH/WZmge5ftF8RrZwq+iZEy59sp7f/0qaxQ0MT8MMK9yOPPKLZs2f/6DmGYWjq1Km6+uqrlZSUJEkqLKybbx4b69lvHBsbq/3797vbhISEqHXr1vXanDy/sLBQMTEx9Z4zJibGo80Pn6d169YKCQlxt/FGoyYNERERmj59uu699165XC5dffXVKisr0+bNm9WyZUuNGTOmMcM776V8VvOTbWJGGIoZ8dPt2o+rW6fhx3R54scHWbZKNdQq1ceBmMA5MON/L/Z4XFIcrHn3XtBI0aCh+GtFyPz8fI9yvjdVhokTJ+rzzz/Xpk2b6h2z2TyrH4Zh1Nv3Qz9sc7r2Z9PmpzT6ZLfHH39cMTExyszM1J49e9SqVStdccUVmjlzZmOHBgBoRvzVPREZGen1GABJmjRpkt58803985//VIcOpwaXxcXVzUsvLCxUu3anpv8WFRW5qwJxcXGqrq5WSUmJR7WhqKhIffv2dbc5fPhwvectLi72uM7WrVs9jpeUlKimpqZeBeLHNPqUS5vNpsmTJ+vLL79UdXW1ioqKlJWVpWuuuaaxQwMA4KwZhqGJEyfqb3/7m95//3116tTJ43inTp0UFxenDRs2uPdVV1dr48aN7oSgV69eCg4O9mhTUFCgHTt2uNukpqaqtLRU27Ztc7fZunWrSktLPdrs2LFDBQUF7jbr16+X3W5Xr169vH5NjV5pAADgXDjX95645557tHr1ar3xxhuKiIhwjx1wOBwKCwuTzWbTlClTNHfuXHXp0kVdunTR3Llz1aJFC40ePdrddty4cZo2bZratGmjqKgoTZ8+XcnJye7ZFN26ddPgwYOVkZHhXq5g/PjxGjp0qBITEyVJaWlp6t69u9LT0/X000/ryJEjmj59ujIyMnyqmpA0AAAswV/dE95avHixJGnAgAEe+5ctW6axY8dKkmbMmKGKigpNmDBBJSUl6tOnj9avX6+IiFNLli9YsEBBQUEaNWqUKioqdP3112v58uUKDDx1z5RVq1Zp8uTJ7lkWw4cP16JFi9zHAwMDtW7dOk2YMEH9+vVTWFiYRo8erWeeecan12QzDOO8ne9WVlYmh8Oh+zbfKHtLbpOI5im7B59tNF+1Ro0+1BsqLS316RevL05+V9z07h0KDg856+vUlFdr3aAXGzTWpo5KAwDAEs51paE5ImkAAFgCSYN5jT57AgAAnB+oNAAALIFKg3kkDQAASzDk+7TJH55vdSQNAABLoNJgHmMaAACAV6g0AAAsgUqDeSQNAABLIGkwj+4JAADgFSoNAABLoNJgHkkDAMASDMMmw8QXv5lzmwu6JwAAgFeoNAAALMElm6nFncyc21yQNAAALIExDebRPQEAALxCpQEAYAkMhDSPpAEAYAl0T5hH0gAAsAQqDeYxpgEAAHiFSgMAwBIMk90TVBpIGgAAFmFIMgxz51sd3RMAAMArVBoAAJbgkk02VoQ0haQBAGAJzJ4wj+4JAADgFSoNAABLcBk22VjcyRSSBgCAJRiGydkTTJ+gewIAAHiHSgMAwBIYCGkeSQMAwBJIGswjaQAAWAIDIc1jTAMAAPAKlQYAgCUwe8I8kgYAgCXUJQ1mxjT4MZjzFN0TAADAK1QaAACWwOwJ80gaAACWYHy/mTnf6uieAAAAXqHSAACwBLonzCNpAABYA/0TppE0AACswWSlQVQaGNMAAAC8Q6UBAGAJrAhpHkkDAMASGAhpHt0TAADAK1QaAADWYNjMDWak0kDSAACwBsY0mEf3BAAA8AqVBgCANbC4k2kkDQAAS2D2hHleJQ3PPfec1xecPHnyWQcDAACaLq+ShgULFnh1MZvNRtIAAGi66GIwxaukYe/evQ0dBwAADYruCfPOevZEdXW1du/erdraWn/GAwBAwzD8sFmcz0nDiRMnNG7cOLVo0UKXXnqpDhw4IKluLMMTTzzh9wABAEDT4HPS8MADD+izzz7Thx9+qNDQUPf+G264Qa+88opfgwMAwH9sftiszecpl6+//rpeeeUVpaSkyGY79QZ2795d//nPf/waHAAAfsM6Dab5XGkoLi5WTExMvf3l5eUeSQQAAFb2z3/+U8OGDVN8fLxsNptef/11j+Njx46VzWbz2FJSUjzaVFVVadKkSYqOjlZ4eLiGDx+ugwcPerQpKSlRenq6HA6HHA6H0tPTdfToUY82Bw4c0LBhwxQeHq7o6GhNnjxZ1dXVPr8mn5OGK6+8UuvWrXM/PpkoLF26VKmpqT4HAADAOXGOB0KWl5erR48eWrRo0RnbDB48WAUFBe7tnXfe8Tg+ZcoUrV27VmvWrNGmTZt0/PhxDR06VE6n091m9OjRys3NVVZWlrKyspSbm6v09HT3cafTqZtuuknl5eXatGmT1qxZo9dee03Tpk3z7QXpLLonMjMzNXjwYO3atUu1tbV69tlntXPnTm3ZskUbN270OQAAAM4JP93lsqyszGO33W6X3W6v13zIkCEaMmTIj17SbrcrLi7utMdKS0v10ksvaeXKlbrhhhskSS+//LISEhL03nvvadCgQcrLy1NWVpays7PVp08fSad+xO/evVuJiYlav369du3apfz8fMXHx0uS5s2bp7Fjx2rOnDmKjIz0+i3wudLQt29fffTRRzpx4oQuuugirV+/XrGxsdqyZYt69erl6+UAADivJCQkuLsCHA6HMjMzz/paH374oWJiYtS1a1dlZGSoqKjIfSwnJ0c1NTVKS0tz74uPj1dSUpI2b94sSdqyZYscDoc7YZCklJQUORwOjzZJSUnuhEGSBg0apKqqKuXk5PgU71ndeyI5OVkrVqw4m1MBAGgU/ro1dn5+vsev89NVGbwxZMgQ/eIXv1DHjh21d+9ePfTQQ7ruuuuUk5Mju92uwsJChYSEqHXr1h7nxcbGqrCwUJJUWFh42nGGMTExHm1iY2M9jrdu3VohISHuNt46q6TB6XRq7dq1ysvLk81mU7du3TRixAgFBXH/KwBAE+Wn2RORkZE+lfTP5JZbbnH/OykpSb1791bHjh21bt063XzzzWcOwzA8Jh6cbhLC2bTxhs/f8jt27NCIESNUWFioxMRESdK///1vtW3bVm+++aaSk5N9vSQAAJbXrl07dezYUV999ZUkKS4uTtXV1SopKfGoNhQVFalv377uNocPH653reLiYnd1IS4uTlu3bvU4XlJSopqamnoViJ/i85iGO+64Q5deeqkOHjyoTz75RJ988ony8/N12WWXafz48b5eDgCAc+PkQEgzWwP67rvvlJ+fr3bt2kmSevXqpeDgYG3YsMHdpqCgQDt27HAnDampqSotLdW2bdvcbbZu3arS0lKPNjt27FBBQYG7zfr162W3230ei+hzpeGzzz7T9u3bPbKe1q1ba86cObryyit9vRwAAOeEzajbzJzvi+PHj+vrr792P967d69yc3MVFRWlqKgozZ49Wz//+c/Vrl077du3TzNnzlR0dLR+9rOfSZIcDofGjRunadOmqU2bNoqKitL06dOVnJzsnk3RrVs3DR48WBkZGVqyZIkkafz48Ro6dKi7NyAtLU3du3dXenq6nn76aR05ckTTp09XRkaGz90sPlcaEhMTT1sKKSoq0sUXX+zr5QAAODfO8ToN27dvV8+ePdWzZ09J0tSpU9WzZ089/PDDCgwM1BdffKERI0aoa9euGjNmjLp27aotW7YoIiLCfY0FCxZo5MiRGjVqlPr166cWLVrorbfeUmBgoLvNqlWrlJycrLS0NKWlpemyyy7TypUr3ccDAwO1bt06hYaGql+/fho1apRGjhypZ555xrcXJMlmGD89lvS/56Ru2rRJM2bM0OzZs90rV2VnZ+uxxx7TE088oRtvvNHnIM5WWVmZHA6H7tt8o+wtg8/Z8wLnUnYPPttovmqNGn2oN1RaWuqXwYWnc/K7ImHhYwoIC/3pE87AVVGp/CkPN2isTZ1X3ROtWrXyGGFpGIZGjRrl3ncy7xg2bJjHKlUAADQZflrcycq8Sho++OCDho4DAICGxQ2rTPMqaejfv39DxwEAAJq4s16N6cSJEzpw4EC9u2RddtllpoMCAMDvqDSY5nPSUFxcrF//+tf6+9//ftrjjGkAADRJJA2m+TzlcsqUKSopKVF2drbCwsKUlZWlFStWqEuXLnrzzTcbIkYAANAE+FxpeP/99/XGG2/oyiuvVEBAgDp27KiBAwcqMjJSmZmZuummmxoiTgAAzGH2hGk+VxrKy8vdd9SKiopScXGxpLo7X37yySf+jQ4AAD85uSKkmc3qzmpFyN27d0uSLr/8ci1ZskTffPONXnjhBfd62QAAoPnxuXtiypQp7ptePPLIIxo0aJBWrVqlkJAQLV++3N/xAQDgHwyENM3npOFXv/qV+989e/bUvn379OWXX+qCCy5QdHS0X4MDAABNx1mv03BSixYtdMUVV/gjFgAAGoxNJu9y6bdIzl9eJQ1Tp071+oLz588/62AAAEDT5VXS8Omnn3p1sf++qdW59HHfYAXZuBMgmqd3D+U2dghAgyk75lLrrufoyZhyaRo3rAIAWAMDIU3zecolAACwJtMDIQEAOC9QaTCNpAEAYAlmV3VkRUi6JwAAgJeoNAAArIHuCdPOqtKwcuVK9evXT/Hx8dq/f78kaeHChXrjjTf8GhwAAH5j+GGzOJ+ThsWLF2vq1Km68cYbdfToUTmdTklSq1attHDhQn/HBwAAmgifk4bnn39eS5cu1axZsxQYGOje37t3b33xxRd+DQ4AAH/h1tjm+TymYe/everZs2e9/Xa7XeXl5X4JCgAAv2NFSNN8rjR06tRJubm59fb//e9/V/fu3f0REwAA/seYBtN8rjTcd999uueee1RZWSnDMLRt2zb93//9nzIzM/Xiiy82RIwAAKAJ8Dlp+PWvf63a2lrNmDFDJ06c0OjRo9W+fXs9++yzuvXWWxsiRgAATGNxJ/POap2GjIwMZWRk6Ntvv5XL5VJMTIy/4wIAwL9Yp8E0U4s7RUdH+ysOAADQxPmcNHTq1Ek225lHkO7Zs8dUQAAANAiz0yapNPieNEyZMsXjcU1NjT799FNlZWXpvvvu81dcAAD4F90TpvmcNPz2t7897f4//OEP2r59u+mAAABA0+S3u1wOGTJEr732mr8uBwCAf7FOg2l+u8vlX//6V0VFRfnrcgAA+BVTLs3zOWno2bOnx0BIwzBUWFio4uJi/fGPf/RrcAAAoOnwOWkYOXKkx+OAgAC1bdtWAwYM0CWXXOKvuAAAQBPjU9JQW1urCy+8UIMGDVJcXFxDxQQAgP8xe8I0nwZCBgUF6e6771ZVVVVDxQMAQIPg1tjm+Tx7ok+fPvr0008bIhYAANCE+TymYcKECZo2bZoOHjyoXr16KTw83OP4ZZdd5rfgAADwK6oFpnidNPzmN7/RwoULdcstt0iSJk+e7D5ms9lkGIZsNpucTqf/owQAwCzGNJjmddKwYsUKPfHEE9q7d29DxgMAAJoor5MGw6hLsTp27NhgwQAA0FBY3Mk8n8Y0/NjdLQEAaNLonjDNp6Sha9euP5k4HDlyxFRAAACgafIpaXj00UflcDgaKhYAABoM3RPm+ZQ03HrrrYqJiWmoWAAAaDh0T5jm9eJOjGcAAMDafJ49AQDAeYlKg2leJw0ul6sh4wAAoEExpsE8n5eRBgDgvESlwTSfb1gFAACsiUoDAMAaqDSYRtIAALAExjSYR/cEAADwCpUGAIA10D1hGkkDAMAS6J4wj+4JAAAawD//+U8NGzZM8fHxstlsev311z2OG4ah2bNnKz4+XmFhYRowYIB27tzp0aaqqkqTJk1SdHS0wsPDNXz4cB08eNCjTUlJidLT0+VwOORwOJSenq6jR496tDlw4ICGDRum8PBwRUdHa/Lkyaqurvb5NZE0AACswfDD5oPy8nL16NFDixYtOu3xp556SvPnz9eiRYv08ccfKy4uTgMHDtSxY8fcbaZMmaK1a9dqzZo12rRpk44fP66hQ4fK6XS624wePVq5ubnKyspSVlaWcnNzlZ6e7j7udDp10003qby8XJs2bdKaNWv02muvadq0ab69INE9AQCwinM8pmHIkCEaMmTI6S9lGFq4cKFmzZqlm2++WZK0YsUKxcbGavXq1brzzjtVWlqql156SStXrtQNN9wgSXr55ZeVkJCg9957T4MGDVJeXp6ysrKUnZ2tPn36SJKWLl2q1NRU7d69W4mJiVq/fr127dql/Px8xcfHS5LmzZunsWPHas6cOYqMjPT6NVFpAADAB2VlZR5bVVWVz9fYu3evCgsLlZaW5t5nt9vVv39/bd68WZKUk5Ojmpoajzbx8fFKSkpyt9myZYscDoc7YZCklJQUORwOjzZJSUnuhEGSBg0apKqqKuXk5PgUN0kDAMASbH7YJCkhIcE9fsDhcCgzM9PnWAoLCyVJsbGxHvtjY2PdxwoLCxUSEqLWrVv/aJuYmJh614+JifFo88Pnad26tUJCQtxtvEX3BADAGvzUPZGfn+9R0rfb7Wd9SZvN5vHYMIx6++qF8YM2p2t/Nm28QaUBAGAJJ6dcmtkkKTIy0mM7m6QhLi5Okur90i8qKnJXBeLi4lRdXa2SkpIfbXP48OF61y8uLvZo88PnKSkpUU1NTb0KxE8haQAA4Bzr1KmT4uLitGHDBve+6upqbdy4UX379pUk9erVS8HBwR5tCgoKtGPHDneb1NRUlZaWatu2be42W7duVWlpqUebHTt2qKCgwN1m/fr1stvt6tWrl09x0z0BALCGczx74vjx4/r666/dj/fu3avc3FxFRUXpggsu0JQpUzR37lx16dJFXbp00dy5c9WiRQuNHj1akuRwODRu3DhNmzZNbdq0UVRUlKZPn67k5GT3bIpu3bpp8ODBysjI0JIlSyRJ48eP19ChQ5WYmChJSktLU/fu3ZWenq6nn35aR44c0fTp05WRkeHTzAmJpAEAYCXncFXH7du369prr3U/njp1qiRpzJgxWr58uWbMmKGKigpNmDBBJSUl6tOnj9avX6+IiAj3OQsWLFBQUJBGjRqliooKXX/99Vq+fLkCAwPdbVatWqXJkye7Z1kMHz7cY22IwMBArVu3ThMmTFC/fv0UFham0aNH65lnnvH5NdkMwzhvF8YsKyuTw+HQAI1QkC24scMBGsS7h3IbOwSgwZQdc6l11z0qLS31+Vev18/x/XfFpXfOVWBI6Flfx1ldqZ1LZjZorE0dlQYAgCVw7wnzSBoAANbAXS5NY/YEAADwCpUGAIAl0D1hHkkDAMAa6J4wje4JAADgFSoNAABLoHvCPJIGAIA10D1hGkkDAMAaSBpMY0wDAADwCpUGAIAlMKbBPJIGAIA10D1hGt0TAADAK1QaAACWYDMM2Uzc2NnMuc0FSQMAwBronjCN7gkAAOAVKg0AAEtg9oR5JA0AAGuge8I0uicAAIBXqDQAACyB7gnzSBoAANZA94RpJA0AAEug0mAeYxoAAIBXqDQAAKyB7gnTSBoAAJZBF4M5dE8AAACvUGkAAFiDYdRtZs63OJIGAIAlMHvCPLonAACAV6g0AACsgdkTppE0AAAsweaq28ycb3V0TwAAAK9QaUA9t00rVPq0wx77jhQF6ZeXXypJ6jfkqG5M/05dLquQI8qpuwd21Z6dYY0RKixuzfMx+uidVsr/2q6QUJe69z6hcbMOKeHiKo92B76y66Xfx+vz7JYyXFLHxErNemGfYjrUSJIO7QvR0sfitXNbS9VU29Tr2jLd8/tv1Lptbb3nrK6y6bc3ddWeXWH64/rduiipwn1sUPzl9dpPeiJfQ2//zr8vHGeH7gnTSBpwWvu+DNXvbunsfuxy2tz/Dm3h0q6Pw/Wvt1vp3mcONkZ4gCTp8y0tNWzst+p6+Qk5a6XlT7bTzF9epKUbv1Roi7pa8qF9IZo6sosG3/qd0qcXKjzSqQNfhSoktO4boPJEgGb+8iJ17l6hJ//f15KkFU+108NjOunZt79SwA/qsS/9Pl5t4mq0Z9fpE+VpCw6o97Vl7sfhEc4GeOU4G8yeMI+kAafldEolxcGnPfaP16IkSbEdqs9lSEA9c1fv8Xg8bcEB3ZKcrK8+D1NySrkkafkT7XTVdWW646ECd7t2HU99dnduC9fh/BD9Yf1uhUe43Nf53+7Jyt3UUldcc9zd9uP3I5SzMUIPvbhXH78fedqYWkY6FRVTv0KBJoB1GkxjTANOq32naq3+ZKdWZOfpgcX7FXdB1U+fBDSy8rJASVJEq7pf9y6XtO0fkWrfuUozf9lZo5Iv1eSbumjz3x3uc2qqbZJNCg459YUQYncpIMDQzm0t3ftKioO08L4EzXh+v+xhZ/7y+MOD7fWLS5M0aUhXvf2XNnIxeA7NSKMmDQMGDNDEiRM1ceJEtWrVSm3atNGDDz4o4wzZXFVVlcrKyjw2+N+Xn7TQ05MTNHN0Zy28r4Nat63Rgje/VkRrfj2h6TIM6U+z2+vSq47rwksqJUlHvw1SRXmgXlkUo97XHlPm/+1Rv8GleuyOC/X5lnBJ0iW9yhXawqWX5sSr8oRNlScCtPTxeLlcNh0pCnJf+5kpF+im9O/UtUfFGWMYM6NAs5bs0xOv/Ef9R5ToT4/Ga81zsQ3/4uGVk90TZjara/TuiRUrVmjcuHHaunWrtm/frvHjx6tjx47KyMio1zYzM1OPPvpoI0RpLds/OFV23feltGt7Cy3f8qUG/qJEf/tT20aMDDizP8xsr715YZr3+lfufcb3v/JTB5Xp5vHFkqSLkiq0a3u41v0lWpellqtVG6ceXLJPzz/QQW+8FC1bgHTtyBJdnHxCAXWFC73xUrROHAvQLZMO//BpPYyecur4yQGSqxbEeexHI2IgpGmNnjQkJCRowYIFstlsSkxM1BdffKEFCxacNml44IEHNHXqVPfjsrIyJSQknMtwLamqIlD7vgxV+050UaBp+sOs9tqy3qF5a79W2/ga9/7IKKcCgwx17Frp0T6hS6V2bgt3P+414JiWb8lT6XeBCgySWjqcurXHpYpLqPvM534UoS8/CdfQC3t4XGfikK667uYS3ffsgdPG1e2KEzpxLFAlxUGnnYkBnG8aPWlISUmRzXZqZH5qaqrmzZsnp9OpwMBAj7Z2u112u/1ch2h5wSEuJVxcpR1bw3+6MXAOGUZdwrA5y6Gn//q14i7wHJwbHGKoa48TOvgfz78b3+yxu6db/jdHm7qxELmbWurot0FKSavrAp3w+EGNvf/U36PvCoM1c/RFmvnCPl3S88QZ4/t6R5hCQl0Kj2QGRVPA7AnzGj1pQNOT8fAhZa+PVNE3wWoVXavRU4rUIsKpDa/WzZqIaFWrtu1r1Ca27o9uwkV1v+JKioLOOOMCaAiLZnbQB2tba/ayPQpr6XKPQQiPcLoHK/5iQpHm3tVRSSnH1aPvcW3/IFLZG+qSjJPeXROlC7pUytGmVnk54Vr8cHv9bHyxe72HugTjVJIRGl7X7xHfsdpd2cheH6kjxUHq3uuEQkJd+uyjllr+ZDvd+KvvFGLn26ZJYPaEaY2eNGRnZ9d73KVLl3pVBpw70e1q9MAf9ysyyqnS7wL15SfhmjK0i4q+CZEkpaSVafrCfHf7mS/UlWZXzovVy/PiGiVmWNPbK6IlSff9vIvH/mkLDijtliOSpH5DSjX5iYNasyhWix/qoA6dq/TQ0r1K6lPubn/wP3Yty2ynY0cDFZtQrV9OPuweA+GtwGBDby+P1p9m2+Vy1U3rvP2+Ag0f+63JVwk0HTbjTFMVzoEBAwYoJydHGRkZuvPOO/XJJ58oIyND8+bN05133vmT55eVlcnhcGiARijIxi9cNE/vHspt7BCABlN2zKXWXfeotLRUkZGnX/vC9HN8/12ROuQxBQWHnvV1amsqteXvDzdorE1do1cabr/9dlVUVOiqq65SYGCgJk2apPHjxzd2WACA5obZE6Y1etIQHByshQsXavHixY0dCgAA+BGNnjQAAHAuMHvCPJIGAIA1uIy6zcz5FteoScOHH37YmE8PALASxjSYxg2rAACAV+ieAABYgk0mxzT4LZLzF0kDAMAaWBHSNLonAACAV6g0AAAsgSmX5pE0AACsgdkTptE9AQAAvEKlAQBgCTbDkM3EYEYz5zYXJA0AAGtwfb+ZOd/i6J4AAABeIWkAAFjCye4JM5svZs+eLZvN5rHFxcW5jxuGodmzZys+Pl5hYWEaMGCAdu7c6XGNqqoqTZo0SdHR0QoPD9fw4cN18OBBjzYlJSVKT0+Xw+GQw+FQenq6jh49etbv048haQAAWIPhh81Hl156qQoKCtzbF1984T721FNPaf78+Vq0aJE+/vhjxcXFaeDAgTp27Ji7zZQpU7R27VqtWbNGmzZt0vHjxzV06FA5nU53m9GjRys3N1dZWVnKyspSbm6u0tPTfQ/WC4xpAABYQyOsCBkUFORRXTh1KUMLFy7UrFmzdPPNN0uSVqxYodjYWK1evVp33nmnSktL9dJLL2nlypW64YYbJEkvv/yyEhIS9N5772nQoEHKy8tTVlaWsrOz1adPH0nS0qVLlZqaqt27dysxMfHsX+9pUGkAAMAHZWVlHltVVdUZ23711VeKj49Xp06ddOutt2rPnj2SpL1796qwsFBpaWnutna7Xf3799fmzZslSTk5OaqpqfFoEx8fr6SkJHebLVu2yOFwuBMGSUpJSZHD4XC38SeSBgCAJZxcEdLMJkkJCQnu8QMOh0OZmZmnfb4+ffroL3/5i959910tXbpUhYWF6tu3r7777jsVFhZKkmJjYz3OiY2NdR8rLCxUSEiIWrdu/aNtYmJi6j13TEyMu40/0T0BALAGP3VP5OfnKzIy0r3bbreftvmQIUPc/05OTlZqaqouuugirVixQikpKZIkm83z3pmGYdTbVz8Mzzana+/Ndc4GlQYAAHwQGRnpsZ0pafih8PBwJScn66uvvnKPc/hhNaCoqMhdfYiLi1N1dbVKSkp+tM3hw4frPVdxcXG9KoY/kDQAACzB5jK/mVFVVaW8vDy1a9dOnTp1UlxcnDZs2OA+Xl1drY0bN6pv376SpF69eik4ONijTUFBgXbs2OFuk5qaqtLSUm3bts3dZuvWrSotLXW38Se6JwAA1nCOZ09Mnz5dw4YN0wUXXKCioiL9/ve/V1lZmcaMGSObzaYpU6Zo7ty56tKli7p06aK5c+eqRYsWGj16tCTJ4XBo3LhxmjZtmtq0aaOoqChNnz5dycnJ7tkU3bp10+DBg5WRkaElS5ZIksaPH6+hQ4f6feaERNIAAECDOHjwoH75y1/q22+/Vdu2bZWSkqLs7Gx17NhRkjRjxgxVVFRowoQJKikpUZ8+fbR+/XpFRES4r7FgwQIFBQVp1KhRqqio0PXXX6/ly5crMDDQ3WbVqlWaPHmye5bF8OHDtWjRogZ5TTbDOH/vwFFWViaHw6EBGqEgW3BjhwM0iHcP5TZ2CECDKTvmUuuue1RaWuoxuNCvz3Hyu+LKWQoKCj3r69TWVurDj+c0aKxNHZUGAIAlcJdL8xgICQAAvEKlAQBgDY2wjHRzQ9IAALAGQ5KZaZPkDCQNAABrYEyDeYxpAAAAXqHSAACwBkMmxzT4LZLzFkkDAMAaGAhpGt0TAADAK1QaAADW4JJk5m7RJm9Y1RyQNAAALIHZE+bRPQEAALxCpQEAYA0MhDSNpAEAYA0kDabRPQEAALxCpQEAYA1UGkwjaQAAWANTLk0jaQAAWAJTLs1jTAMAAPAKlQYAgDUwpsE0kgYAgDW4DMlm4ovfRdJA9wQAAPAKlQYAgDXQPWEaSQMAwCJMJg0iaaB7AgAAeIVKAwDAGuieMI2kAQBgDS5DproYmD1B9wQAAPAOlQYAgDUYrrrNzPkWR9IAALAGxjSYRtIAALAGxjSYxpgGAADgFSoNAABroHvCNJIGAIA1GDKZNPgtkvMW3RMAAMArVBoAANZA94RpJA0AAGtwuSSZWGvBxToNdE8AAACvUGkAAFgD3ROmkTQAAKyBpME0uicAAIBXqDQAAKyBZaRNI2kAAFiCYbhkmLhTpZlzmwuSBgCANRiGuWoBYxoY0wAAALxDpQEAYA2GyTENVBpIGgAAFuFySTYT4xIY00D3BAAA8A6VBgCANdA9YRpJAwDAEgyXS4aJ7gmmXNI9AQAAvESlAQBgDXRPmEbSAACwBpch2UgazKB7AgAAeIVKAwDAGgxDkpl1Gqg0kDQAACzBcBkyTHRPGCQNJA0AAIswXDJXaWDKJWMaAACAV6g0AAAsge4J80gaAADWQPeEaed10nAy66tVjan1OoCmrOwYf6jQfJUdr/t8n4tf8Wa/K2pV479gzlPnddJw7NgxSdImvdPIkQANp3XXxo4AaHjHjh2Tw+FokGuHhIQoLi5OmwrNf1fExcUpJCTED1Gdn2zGedxJ43K5dOjQIUVERMhmszV2OJZQVlamhIQE5efnKzIysrHDAfyKz/e5ZxiGjh07pvj4eAUENNzY/MrKSlVXV5u+TkhIiEJDQ/0Q0fnpvK40BAQEqEOHDo0dhiVFRkbyRxXNFp/vc6uhKgz/LTQ01NJf9v7ClEsAAOAVkgYAAOAVkgb4xG6365FHHpHdbm/sUAC/4/MN/LjzeiAkAAA4d6g0AAAAr5A0AAAAr5A0AAAAr5A0AAAAr5A0AAAAr5A0AAAAr5A0wCuGYeipp55S586dFRYWph49euivf/1rY4cF+MWAAQM0ceJETZw4Ua1atVKbNm304IMPnpM7LwLnE5IGeOXBBx/UsmXLtHjxYu3cuVP33nuvbrvtNm3cuLGxQwP8YsWKFQoKCtLWrVv13HPPacGCBXrxxRcbOyygSWFxJ/yk8vJyRUdH6/3331dqaqp7/x133KETJ05o9erVjRgdYN6AAQNUVFSknTt3uu+Y+7vf/U5vvvmmdu3a1cjRAU3HeX2XS5wbu3btUmVlpQYOHOixv7q6Wj179mykqAD/SklJcScMkpSamqp58+bJ6XQqMDCwESMDmg6SBvwkl8slSVq3bp3at2/vcYw1+gHAOkga8JO6d+8uu92uAwcOqH///o0dDtAgsrOz6z3u0qULVQbgv5A04CdFRERo+vTpuvfee+VyuXT11VerrKxMmzdvVsuWLTVmzJjGDhEwLT8/X1OnTtWdd96pTz75RM8//7zmzZvX2GEBTQpJA7zy+OOPKyYmRpmZmdqzZ49atWqlK664QjNnzmzs0AC/uP3221VRUaGrrrpKgYGBmjRpksaPH9/YYQFNCrMnAFjegAEDdPnll2vhwoWNHQrQpLFOAwAA8ApJAwAA8ArdEwAAwCtUGgAAgFdIGgAAgFdIGgAAgFdIGgAAgFdIGgAAgFdIGgCTZs+ercsvv9z9eOzYsRo5cuQ5j2Pfvn2y2WzKzc09Y5sLL7zQpwWMli9frlatWpmOzWaz6fXXXzd9HQCNi6QBzdLYsWNls9lks9kUHByszp07a/r06SovL2/w53722We1fPlyr9p680UPAE0F955AszV48GAtW7ZMNTU1+te//qU77rhD5eXlWrx4cb22NTU1Cg4O9svzOhwOv1wHAJoaKg1otux2u+Li4pSQkKDRo0frV7/6lbtEfrJL4c9//rM6d+4su90uwzBUWlqq8ePHKyYmRpGRkbruuuv02WefeVz3iSeeUGxsrCIiIjRu3DhVVlZ6HP9h94TL5dKTTz6piy++WHa7XRdccIHmzJkjSerUqZMkqWfPnrLZbBowYID7vGXLlqlbt24KDQ3VJZdcoj/+8Y8ez7Nt2zb17NlToaGh6t27tz799FOf36P58+crOTlZ4eHhSkhI0IQJE3T8+PF67V5//XV17dpVoaGhGjhwoPLz8z2Ov/XWW+rVq5dCQ0PVuXNnPfroo6qtrfU5HgBNG0kDLCMsLEw1NTXux19//bVeffVVvfbaa+7ugZtuukmFhYV65513lJOToyuuuELXX3+9jhw5Ikl69dVX9cgjj2jOnDnavn272rVrV+/L/IceeOABPfnkk3rooYe0a9curV69WrGxsZLqvvgl6b333lNBQYH+9re/SZKWLl2qWbNmac6cOcrLy9PcuXP10EMPacWKFZKk8vJyDR06VImJicrJydHs2bM1ffp0n9+TgIAAPffcc9qxY4dWrFih999/XzNmzPBoc+LECc2ZM0crVqzQRx99pLKyMt16663u4++++65uu+02TZ48Wbt27dKSJUu0fPlyd2IEoBkxgGZozJgxxogRI9yPt27darRp08YYNWqUYRiG8cgjjxjBwcFGUVGRu80//vEPIzIy0qisrPS41kUXXWQsWbLEMAzDSE1NNe666y6P43369DF69Ohx2ucuKysz7Ha7sXTp0tPGuXfvXkOS8emnn3rsT0hIMFavXu2x7/HHHzdSU1MNwzCMJUuWGFFRUUZ5ebn7+OLFi097rf/WsWNHY8GCBWc8/uqrrxpt2rRxP162bJkhycjOznbvy8vLMyQZW7duNQzDMP7nf/7HmDt3rsd1Vq5cabRr1879WJKxdu3aMz4vgPMDYxrQbL399ttq2bKlamtrVVNToxEjRuj55593H+/YsaPatm3rfpyTk6Pjx4+rTZs2HtepqKjQf/7zH0lSXl6e7rrrLo/jqamp+uCDD04bQ15enqqqqnT99dd7HXdxcbHy8/M1btw4ZWRkuPfX1ta6x0vk5eWpR48eatGihUccvvrggw80d+5c7dq1S2VlZaqtrVVlZaXKy8sVHh4uSQoKClLv3r3d51xyySVq1aqV8vLydNVVVyknJ0cff/yxR2XB6XSqsrJSJ06c8IgRwPmNpAHN1rXXXqvFixcrODhY8fHx9QY6nvxSPMnlcqldu3b68MMP613rbKcdhoWF+XyOy+WSVNdF0adPH49jgYGBkiTDD/eZ279/v2688UbdddddevzxxxUVFaVNmzZp3LhxHt04Ut2UyR86uc/lcunRRx/VzTffXK9NaGio6TgBNB0kDWi2wsPDdfHFF3vd/oorrlBhYaGCgoJ04YUXnrZNt27dlJ2drdtvv929Lzs7+4zX7NKli8LCwvSPf/xDd9xxR73jISEhkup+mZ8UGxur9u3ba8+ePfrVr3512ut2795dK1euVEVFhTsx+bE4Tmf79u2qra3VvHnzFBBQN7zp1VdfrdeutrZW27dv11VXXSVJ2r17t44ePapLLrlEUt37tnv3bp/eawDnJ5IG4Hs33HCDUlNTNXLkSD355JNKTEzUoUOH9M4772jkyJHq3bu3fvvb32rMmDHq3bu3rr76aq1atUo7d+5U586dT3vN0NBQ3X///ZoxY4ZCQkLUr18/FRcXa+fOnRo3bpxiYmIUFhamrKwsdejQQaGhoXI4HJo9e7YmT56syMhIDRkyRFVVVdq+fbtKSko0depUjR49WrNmzdK4ceP04IMPat++fXrmmWd8er0XXXSRamtr9fzzz2vYsGH66KOP9MILL9RrFxwcrEmTJum5555TcHCwJk6cqJSUFHcS8fDDD2vo0KFKSEjQL37xCwUEBOjzzz/XF198od///ve+/x8BoMli9gTwPZvNpnfeeUfXXHONfvOb36hr16669dZbtW/fPvdsh1tuuUUPP/yw7r//fvXq1Uv79+/X3Xff/aPXfeihhzRt2jQ9/PDD6tatm2655RYVFRVJqhsv8Nxzz2nJkiWKj4/XiBEjJEl33HGHXnzxRS1fvlzJycnq37+/li9f7p6i2bJlS7311lvatWuXevbsqVmzZunJJ5/06fVefvnlmj9/vp588kklJSVp1apVyszMrNeuRYsWuv/++zV69GilpqYqLCxMa9ascR8fNGiQ3n77bW3YsEFXXnmlUlJSNH/+fHXs2NGneAA0fTbDH52jAACg2aPSAAAAvELSAAAAvELSAAAAvELSAAAAvELSAAAAvELSAAAAvELSAAAAvELSAAAAvELSAAAAvELSAAAAvELSAAAAvPL/AXc/a8mQm2whAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "best_model = cv_results['svc'].best_estimator_\n", + "best_model.fit(X_train,y_train)\n", + "\n", + "# confusion matrix of test results\n", + "ConfusionMatrixDisplay.from_estimator(\n", + " best_model,\n", + " X_train,\n", + " y_train\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "7162513f-f781-4d4c-a535-1b63d10fdb4a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test F2-Score: 0.9968782518210197\n", + "Test Accuracy: 0.9963057220261062\n" + ] + } + ], + "source": [ + "# Finally, report the test score and confusion matrix \n", + "y_test_predict = best_model.predict(X_test)\n", + "\n", + "test_f2_score = fbeta_score(y_test,y_test_predict,beta=2,pos_label='p')\n", + "test_accuracy = accuracy_score(y_test,y_test_predict)\n", + "print(f'Test F2-Score: {test_f2_score}\\nTest Accuracy: {test_accuracy}')" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "14991874-e219-46e1-b434-c96c96528cb7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgQAAAGwCAYAAADWsX1oAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABAXklEQVR4nO3de3wU9bnH8e/mtrmQLCSQhGhE0IAgFxE0BG1JD1cV0ePrFG0waouARaARKFbxglUT4ZSLSEsRLVCEUmuLl6oRrMopQrhpLIRIrSAmQkjUsAkh953zR2R0CaxZNsmSzOf9es2r3ZlnZp+llH32+f3mNzbDMAwBAABLC/B3AgAAwP8oCAAAAAUBAACgIAAAAKIgAAAAoiAAAACiIAAAAJKC/J2AL1wul44cOaLIyEjZbDZ/pwMA8JJhGCovL1dCQoICAlruN2pVVZVqamp8vk5ISIhCQ0ObIaPzT5suCI4cOaLExER/pwEA8FFBQYEuvPDCFrl2VVWVunfroKLiep+vFR8fr0OHDrXLoqBNFwSRkZGSpJlvD5c9ok1/FOCstqe0v394gFPqVKutesP897wl1NTUqKi4Xof3XKyoyHPvQpSVu9Rt0GeqqamhIDjfnBomsEcEKbRDsJ+zAVpGkI2/22jHvlk8vzWGfTtE2tQh8tzfx6X2PTTdpgsCAACaqt5wqd6Hp/fUG67mS+Y8REEAALAElwy5dO4VgS/ntgXcdggAAOgQAACswSWXfGn6+3b2+Y+CAABgCfWGoXrj3Nv+vpzbFjBkAAAA6BAAAKyBSYWeURAAACzBJUP1FARnxZABAACgQwAAsAaGDDyjIAAAWAJ3GXjGkAEAAKBDAACwBtc3my/nt2cUBAAAS6j38S4DX85tCygIAACWUG/Ix6cdNl8u5yPmEAAAADoEAABrYA6BZxQEAABLcMmmetl8Or89Y8gAAADQIQAAWIPLaNh8Ob89oyAAAFhCvY9DBr6c2xYwZAAAAOgQAACsgQ6BZxQEAABLcBk2uQwf7jLw4dy2gCEDAABAhwAAYA0MGXhGQQAAsIR6Bajeh8Z4fTPmcj6iIAAAWILh4xwCgzkEAACgvaNDAACwBOYQeEZBAACwhHojQPWGD3MI2vnSxQwZAAAAOgQAAGtwySaXD7+DXWrfLQI6BAAASzg1h8CXzVtffPGFbr/9dsXExCg8PFxXXHGF9uzZYx43DEPz5s1TQkKCwsLClJqaqry8PLdrVFdXa/r06ercubMiIiI0btw4FRYWusWUlpYqPT1dDodDDodD6enpOn78uFe5UhAAANACSktLdc011yg4OFhvvvmm9u/fr4ULF6pjx45mzIIFC7Ro0SItW7ZMu3btUnx8vEaOHKny8nIzJiMjQxs3btSGDRu0detWnThxQmPHjlV9/bcrI6SlpSk3N1fZ2dnKzs5Wbm6u0tPTvcqXIQMAgCX4PqmwYcigrKzMbb/dbpfdbm8UP3/+fCUmJmrVqlXmvosvvtj874ZhaMmSJZo7d65uueUWSdKaNWsUFxen9evXa8qUKXI6nXr++ee1du1ajRgxQpL0wgsvKDExUW+//bZGjx6t/Px8ZWdnKycnR8nJyZKklStXKiUlRQcOHFCvXr2a9PnoEAAALKFhDoFvmyQlJiaarXmHw6GsrKwzvt+rr76qwYMH68c//rFiY2M1cOBArVy50jx+6NAhFRUVadSoUeY+u92uYcOGadu2bZKkPXv2qLa21i0mISFBffv2NWO2b98uh8NhFgOSNGTIEDkcDjOmKegQAADghYKCAkVFRZmvz9QdkKSDBw9q+fLlmjlzph588EHt3LlTM2bMkN1u1x133KGioiJJUlxcnNt5cXFxOnz4sCSpqKhIISEh6tSpU6OYU+cXFRUpNja20fvHxsaaMU1BQQAAsASXj88yOHWXQVRUlFtBcNZ4l0uDBw9WZmamJGngwIHKy8vT8uXLdccdd5hxNpv7ZEXDMBrtO93pMWeKb8p1voshAwCAJZyaQ+DL5o2uXbuqT58+bvt69+6tzz//XJIUHx8vSY1+xRcXF5tdg/j4eNXU1Ki0tNRjzLFjxxq9f0lJSaPugycUBAAAS3ApwOfNG9dcc40OHDjgtu/f//63unXrJknq3r274uPjtXnzZvN4TU2NtmzZoqFDh0qSBg0apODgYLeYo0ePat++fWZMSkqKnE6ndu7cacbs2LFDTqfTjGkKhgwAAGgB9913n4YOHarMzEyNHz9eO3fu1LPPPqtnn31WUkObPyMjQ5mZmUpKSlJSUpIyMzMVHh6utLQ0SZLD4dDEiRM1a9YsxcTEKDo6WrNnz1a/fv3Muw569+6tMWPGaNKkSVqxYoUkafLkyRo7dmyT7zCQKAgAABZRb9hU78MjjL0996qrrtLGjRv1wAMP6Ne//rW6d++uJUuWaMKECWbMnDlzVFlZqalTp6q0tFTJycnatGmTIiMjzZjFixcrKChI48ePV2VlpYYPH67Vq1crMDDQjFm3bp1mzJhh3o0wbtw4LVu2zKt8bYZhtNm1GMvKyuRwOPTA9tEK7RDs73SAFvHP/qH+TgFoMXVGrd7TK3I6nU2aqHcuTn1XrP5wgMIjA7//hLM4WV6vuwZ+1KK5+hNzCAAAAEMGAABrcBkBcvmwUqGr7TbUm4SCAABgCfU+rkNQz9MOAQBAe0eHAABgCS55f6fA6ee3ZxQEAABLOJfFhU4/vz1r358OAAA0CR0CAIAlnMvzCE4/vz2jIAAAWIJLNrnkyxyCcz+3LaAgAABYAh0Cz9r3pwMAAE1ChwAAYAm+L0zUvn9DUxAAACzBZdjk8mUdAh/ObQvad7kDAACahA4BAMASXD4OGbT3hYkoCAAAluD70w7bd0HQvj8dAABoEjoEAABLqJdN9T4sLuTLuW0BBQEAwBIYMvCsfX86AADQJHQIAACWUC/f2v71zZfKeYmCAABgCQwZeEZBAACwBB5u5Fn7/nQAAKBJ6BAAACzBkE0uH+YQGNx2CABA28eQgWft+9MBAIAmoUMAALAEHn/sGQUBAMAS6n182qEv57YF7fvTAQCAJqFDAACwBIYMPKMgAABYgksBcvnQGPfl3LagfX86AADQJHQIAACWUG/YVO9D29+Xc9sCCgIAgCUwh8AzCgIAgCUYPj7t0GClQgAA0N7RIQAAWEK9bKr34QFFvpzbFlAQAAAswWX4Ng/AZTRjMuchhgwAAAAdAqs5/Lsgff579//Zg2MMDXm3ulHsJ78OUtFLQerxy1pdkF7vtv94ToBqSmwKCJeiBrjU/b46hXf/tnyuLZMOPhWsr95rqDljUl265Fe1CopqoQ8GNNGt047pmuudSry0WjVVAdq/O1zPP9lVhZ+GmjGzFn+uUbeWup2XvydcGTcmtXa6aEYuHycV+nJuW0BBYEHhl7jUb2XNtzvO8Hf8y3cCVL43QCGxjXtkHfoYir2+VvauUp1TOrw8SPumhOiqN6tlC2yIOXB/sKqP2dR3ecP7fPJYsA48GKzLl9W2xEcCmqx/SoVeW91Z/84NV2CQobvuP6rMPx3UpGG9VF0ZaMbteidSC+9LNF/X1bbv8WMrcMkmlw/zAHw5ty2gILAgW5AU0vnsx6uPSZ9mBqvv72uUNy2k0fGu//Ntt0AXSBdPr9MH/2NX1RGbwhINnTxoU+n7gRrwQrWi+jcUFEmP1uqjdLtOHnLvJACtbe6EHm6vF953kV7cl6ek/pXat6ODub+2xqbSkuDWTg/wGwoCC6o8bNOO4XbZgg1F9jd08Yw6hV3Y8CVtuKQDDwbrwrvqFHHp939x15+Uil4OVOgFLtnjG+LLPgpQYKRhFgOSFDXAUGCkobKPAhTevf5slwNaXURUw9/H8uOBbvv7p5zQn/+VpxPOAO3N6aBVT8XL+RUFQlvGSoWe+X1AxDAMLViwQD169FBYWJgGDBigl156yd9ptVuR/Vzq9WSt+i6vUdK8OtV+adNH6SGqPd5wvPAPgbIFSQkTPH9pH9kQqPeT7do2JFSl7weo77O1Cvjm38qaL6WQ6MbFREi0odovm/kDAT4xNHneEe3bEaHDB8LMvbvfjdT8ad0058c99OyvE9TzipNa8JeDCg5x+TFX+OrUHAJfNm/MmzdPNpvNbYuPjzePG4ahefPmKSEhQWFhYUpNTVVeXp7bNaqrqzV9+nR17txZERERGjdunAoLC91iSktLlZ6eLofDIYfDofT0dB0/ftzrPx+/FwQPPfSQVq1apeXLlysvL0/33Xefbr/9dm3ZsqVRbHV1tcrKytw2eCf6By51HulSRE9DnYa4dPmyhjH+Y68Gqny/TV+sC1LPx2tl+55COPaGel35Yo36/6FaYRcZ+nh2sFyN5yW6MQypnQ/BoY25N/MLde9dqaypF7nt3/JqJ+38R5QOHwjTjs0OPTShhy7oUa2rh/NvDrxz+eWX6+jRo+a2d+9e89iCBQu0aNEiLVu2TLt27VJ8fLxGjhyp8vJyMyYjI0MbN27Uhg0btHXrVp04cUJjx45Vff23P9rS0tKUm5ur7OxsZWdnKzc3V+np6V7n6tchg4qKCi1atEjvvPOOUlJSJEk9evTQ1q1btWLFCg0bNswtPisrS4899pg/Um23AsOliCSXKg/bZLMFqPZraedo+7cB9TYdXBikL9YF6ersb7/xgyKloEhDYd2kyAG12n6NXV/+I0Cx17sU0lmq+brxN39tqU3BMa3xqYDvN/WJQqWMKtOs/75EXx5tPFfmu74uDlZxYbAu6FHjMQ7nN5d8fJbBN79oTv8xarfbZbfbz3SKgoKC3LoCpxiGoSVLlmju3Lm65ZZbJElr1qxRXFyc1q9frylTpsjpdOr555/X2rVrNWLECEnSCy+8oMTERL399tsaPXq08vPzlZ2drZycHCUnJ0uSVq5cqZSUFB04cEC9evVq8ufza4dg//79qqqq0siRI9WhQwdz++Mf/6hPP/20UfwDDzwgp9NpbgUFBX7Iun1x1UgnDwYopIuh2BvrdeVLNbryxW+3kFhDF95Vb94t4InxzSzsqAEu1ZfbVL732//jlf3Lpvpym6IG0HKFvxm698lCXXOdU3N+fImOFZz5H/LviuxUpy4Jtfr6GNOu2jLjm7sMznUzvikIEhMTzfa8w+FQVlbWWd/zk08+UUJCgrp3767bbrtNBw8elCQdOnRIRUVFGjVqlBlrt9s1bNgwbdu2TZK0Z88e1dbWusUkJCSob9++Zsz27dvlcDjMYkCShgwZIofDYcY0lV//drtcDV8Or7/+ui644AK3Y2eqtjxVYWiag78JUnRqvULjpZqvpYJng1RfIcWNq1dwRym4o/vYvy1ICokxzDsDKgtt+jI7QB2HuhTcyVBNsU2FfwhSgF3qdG1DCyu8h6FO19Trk8eCdenDDbcZfvLrYEX/sJ47DOB30zK/0I/+u1TzftpdlScC1KlLw9/RivJA1VQFKDS8Xumzj2nr6w59fSxYcYk1+ukDR+X8Okjvv+nwc/bwRXM97bCgoEBRUd8uqnK276Xk5GT98Y9/VM+ePXXs2DE98cQTGjp0qPLy8lRUVCRJiouLczsnLi5Ohw8fliQVFRUpJCREnTp1ahRz6vyioiLFxsY2eu/Y2Fgzpqn8WhD06dNHdrtdn3/+eaPhAbSM6mKbDtwfotpSKTi6YZLhgBdqFJrQtPMDQgw5PwjQFy8Eqa5MCo6RHINcGvDHGoV8Zzig11O1+vSpYO27p6EVG53q0qUPsAYB/O/Gu76SJP3mb+5dyN9kJGrzi9FyuWy6+LJKjfifUkVE1evr4iB99H4HZd7TTZUVgWe6JCwmKirKrSA4m+uuu8787/369VNKSoouueQSrVmzRkOGDJEk2U6bsGUYRqN9pzs95kzxTbnO6fxaEERGRmr27Nm677775HK5dO2116qsrEzbtm1Thw4ddOedd/ozvXap9wLvvpS/O29AkuyxUt/fff81gh3SZVkUADj/jE4Y4PF4TVWA5qZd0krZoDX5e6XCiIgI9evXT5988oluvvlmSQ2/8Lt27WrGFBcXm12D+Ph41dTUqLS01K1LUFxcrKFDh5oxx44da/ReJSUljboP38fvdxk8/vjjeuSRR5SVlaXevXtr9OjReu2119S9e3d/pwYAaEdODRn4svmiurpa+fn56tq1q7p37674+Hht3rzZPF5TU6MtW7aYX/aDBg1ScHCwW8zRo0e1b98+MyYlJUVOp1M7d+40Y3bs2CGn02nGNJXfZ8jYbDbNmDFDM2bM8HcqAAA0m9mzZ+vGG2/URRddpOLiYj3xxBMqKyvTnXfeKZvNpoyMDGVmZiopKUlJSUnKzMxUeHi40tLSJEkOh0MTJ07UrFmzFBMTo+joaM2ePVv9+vUz7zro3bu3xowZo0mTJmnFihWSpMmTJ2vs2LFe3WEgnQcFAQAAraG1n2VQWFion/zkJ/ryyy/VpUsXDRkyRDk5OerWrZskac6cOaqsrNTUqVNVWlqq5ORkbdq0SZGRkeY1Fi9erKCgII0fP16VlZUaPny4Vq9ercDAb+ezrFu3TjNmzDDvRhg3bpyWLVvm9eezGYbRZqd9l5WVyeFw6IHtoxXagSVF0T79s3/o9wcBbVSdUav39IqcTmeTJuqdi1PfFTe8dbeCIzyvOeFJbUWNXh/9XIvm6k9+n0MAAAD8jyEDAIAlNNc6BO0VBQEAwBIoCDxjyAAAANAhAABYAx0CzygIAACWYMj7WwdPP789oyAAAFgCHQLPmEMAAADoEAAArIEOgWcUBAAAS6Ag8IwhAwAAQIcAAGANdAg8oyAAAFiCYdhk+PCl7su5bQFDBgAAgA4BAMAaXLL5tDCRL+e2BRQEAABLYA6BZwwZAAAAOgQAAGtgUqFnFAQAAEtgyMAzCgIAgCXQIfCMOQQAAIAOAQDAGgwfhwzae4eAggAAYAmGJMPw7fz2jCEDAABAhwAAYA0u2WRjpcKzoiAAAFgCdxl4xpABAACgQwAAsAaXYZONhYnOioIAAGAJhuHjXQbt/DYDhgwAAAAdAgCANTCp0DMKAgCAJVAQeEZBAACwBCYVesYcAgAAQIcAAGAN3GXgGQUBAMASGgoCX+YQNGMy5yGGDAAAAB0CAIA1cJeBZxQEAABLML7ZfDm/PWPIAAAA0CEAAFgDQwaeURAAAKyBMQOPKAgAANbgY4dA7bxDwBwCAABAQQAAsIZTKxX6sp2rrKws2Ww2ZWRkfCcfQ/PmzVNCQoLCwsKUmpqqvLw8t/Oqq6s1ffp0de7cWRERERo3bpwKCwvdYkpLS5Weni6HwyGHw6H09HQdP37c6xwpCAAAlnBqUqEv27nYtWuXnn32WfXv399t/4IFC7Ro0SItW7ZMu3btUnx8vEaOHKny8nIzJiMjQxs3btSGDRu0detWnThxQmPHjlV9fb0Zk5aWptzcXGVnZys7O1u5ublKT0/3Ok8KAgAAWsiJEyc0YcIErVy5Up06dTL3G4ahJUuWaO7cubrlllvUt29frVmzRidPntT69eslSU6nU88//7wWLlyoESNGaODAgXrhhRe0d+9evf3225Kk/Px8ZWdn67nnnlNKSopSUlK0cuVK/f3vf9eBAwe8ypWCAABgDYbN901SWVmZ21ZdXX3Wt7z33nt1ww03aMSIEW77Dx06pKKiIo0aNcrcZ7fbNWzYMG3btk2StGfPHtXW1rrFJCQkqG/fvmbM9u3b5XA4lJycbMYMGTJEDofDjGkqCgIAgCU01xyCxMREc7ze4XAoKyvrjO+3YcMGffDBB2c8XlRUJEmKi4tz2x8XF2ceKyoqUkhIiFtn4UwxsbGxja4fGxtrxjQVtx0CAOCFgoICRUVFma/tdvsZY37xi19o06ZNCg0NPeu1bDb3eQmGYTTad7rTY84U35TrnI4OAQDAGoxm2CRFRUW5bWcqCPbs2aPi4mINGjRIQUFBCgoK0pYtW7R06VIFBQWZnYHTf8UXFxebx+Lj41VTU6PS0lKPMceOHWv0/iUlJY26D9+HggAAYAmteZfB8OHDtXfvXuXm5prb4MGDNWHCBOXm5qpHjx6Kj4/X5s2bzXNqamq0ZcsWDR06VJI0aNAgBQcHu8UcPXpU+/btM2NSUlLkdDq1c+dOM2bHjh1yOp1mTFM1achg6dKlTb7gjBkzvEoAAID2JjIyUn379nXbFxERoZiYGHN/RkaGMjMzlZSUpKSkJGVmZio8PFxpaWmSJIfDoYkTJ2rWrFmKiYlRdHS0Zs+erX79+pmTFHv37q0xY8Zo0qRJWrFihSRp8uTJGjt2rHr16uVVzk0qCBYvXtyki9lsNgoCAMD56zx6HsGcOXNUWVmpqVOnqrS0VMnJydq0aZMiIyPNmMWLFysoKEjjx49XZWWlhg8frtWrVyswMNCMWbdunWbMmGHejTBu3DgtW7bM63xshuHL2kv+VVZWJofDoQe2j1Zoh2B/pwO0iH/2P/uEJKCtqzNq9Z5ekdPpdJuo15xOfVckrnhUAWHn/v8nV2WVCqY81qK5+tM5zyGoqanRgQMHVFdX15z5AADQMpppUmF75XVBcPLkSU2cOFHh4eG6/PLL9fnnn0tqmDvw1FNPNXuCAACg5XldEDzwwAP66KOP9N5777ndWzlixAj9+c9/btbkAABoPrZm2Novrxcmevnll/XnP/9ZQ4YMcVv0oE+fPvr000+bNTkAAJqNr21/hgzclZSUnHGZxIqKCq9XRQIAAOcHrwuCq666Sq+//rr5+lQRsHLlSqWkpDRfZgAANCcmFXrk9ZBBVlaWxowZo/3796uurk5PP/208vLytH37dm3ZsqUlcgQAwHffeWLhOZ/fjnndIRg6dKjef/99nTx5Updccok2bdqkuLg4bd++XYMGDWqJHAEAQAs7p6cd9uvXT2vWrGnuXAAAaDHffYTxuZ7fnp1TQVBfX6+NGzcqPz9fNptNvXv31k033aSgIJ6mDAA4T3GXgUdef4Pv27dPN910k4qKiswHJ/z73/9Wly5d9Oqrr6pfv37NniQAAGhZXs8huPvuu3X55ZersLBQH3zwgT744AMVFBSof//+mjx5ckvkCACA705NKvRla8e87hB89NFH2r17tzp16mTu69Spk5588kldddVVzZocAADNxWY0bL6c35553SHo1auXjh071mh/cXGxLr300mZJCgCAZsc6BB41qSAoKyszt8zMTM2YMUMvvfSSCgsLVVhYqJdeekkZGRmaP39+S+cLAABaQJOGDDp27Oi2LLFhGBo/fry5z/jmXowbb7xR9fX1LZAmAAA+YmEij5pUELz77rstnQcAAC2L2w49alJBMGzYsJbOAwAA+NE5ryR08uRJff7556qpqXHb379/f5+TAgCg2dEh8MjrgqCkpEQ//elP9eabb57xOHMIAADnJQoCj7y+7TAjI0OlpaXKyclRWFiYsrOztWbNGiUlJenVV19tiRwBAEAL87pD8M477+iVV17RVVddpYCAAHXr1k0jR45UVFSUsrKydMMNN7REngAA+Ia7DDzyukNQUVGh2NhYSVJ0dLRKSkokNTwB8YMPPmje7AAAaCanVir0ZWvPzmmlwgMHDkiSrrjiCq1Y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dVAQ4Hu5XC5J0uuvv64LLrjA7RhrvgNA+0BBgO/Vp08f2e12ff755xo2bJi/0wFaRE5OTqPXSUlJdAdgGRQE+F6RkZGaPXu27rvvPrlcLl177bUqKyvTtm3b1KFDB915553+ThHwWUFBgWbOnKkpU6bogw8+0DPPPKOFCxf6Oy2g1VAQoEkef/xxxcbGKisrSwcPHlTHjh115ZVX6sEHH/R3akCzuOOOO1RZWamrr75agYGBmj59uiZPnuzvtIBWw10GACwvNTVVV1xxhZYsWeLvVAC/YR0CAABAQQAAABgyAAAAokMAAABEQQAAAERBAAAAREEAAABEQQAAAERBAPhs3rx5uuKKK8zXd911l26++eZWz+Ozzz6TzWZTbm7uWWMuvvhirxbfWb16tTp27OhzbjabTS+//LLP1wHQcigI0C7dddddstlsstlsCg4OVo8ePTR79mxVVFS0+Hs//fTTWr16dZNim/IlDgCtgWcZoN0aM2aMVq1apdraWv3zn//U3XffrYqKCi1fvrxRbG1trYKDg5vlfR0OR7NcBwBaEx0CtFt2u13x8fFKTExUWlqaJkyYYLatT7X5//CHP6hHjx6y2+0yDENOp1OTJ09WbGysoqKi9F//9V/66KOP3K771FNPKS4uTpGRkZo4caKqqqrcjp8+ZOByuTR//nxdeumlstvtuuiii/Tkk09Kkrp37y5JGjhwoGw2m1JTU83zVq1apd69eys0NFSXXXaZfve737m9z86dOzVw4ECFhoZq8ODB+vDDD73+M1q0aJH69euniIgIJSYmaurUqTpx4kSjuJdfflk9e/ZUaGioRo4cqYKCArfjr732mgYNGqTQ0FD16NFDjz32mOrq6rzOB4D/UBDAMsLCwlRbW2u+/s9//qMXX3xRf/3rX82W/Q033KCioiK98cYb2rNnj6688koNHz5cX3/9tSTpxRdf1KOPPqonn3xSu3fvVteuXRt9UZ/ugQce0Pz58/Xwww9r//79Wr9+veLi4iQ1fKlL0ttvv62jR4/qb3/7myRp5cqVmjt3rp588knl5+crMzNTDz/8sNasWSNJqqio0NixY9WrVy/t2bNH8+bN0+zZs73+MwkICNDSpUu1b98+rVmzRu+8847mzJnjFnPy5Ek9+eSTWrNmjd5//32VlZXptttuM4+/9dZbuv322zVjxgzt379fK1as0OrVq82iB0AbYQDt0J133mncdNNN5usdO3YYMTExxvjx4w3DMIxHH33UCA4ONoqLi82Yf/zjH0ZUVJRRVVXldq1LLrnEWLFihWEYhpGSkmLcc889bseTk5ONAQMGnPG9y8rKDLvdbqxcufKMeR46dMiQZHz44Ydu+xMTE43169e77Xv88ceNlJQUwzAMY8WKFUZ0dLRRUVFhHl++fPkZr/Vd3bp1MxYvXnzW4y+++KIRExNjvl61apUhycjJyTH35efnG5KMHTt2GIZhGD/4wQ+MzMxMt+usXbvW6Nq1q/lakrFx48azvi8A/2MOAdqtv//97+rQoYPq6upUW1urm266Sc8884x5vFu3burSpYv5es+ePTpx4oRiYmLcrlNZWalPP/1UkpSfn6977rnH7XhKSorefffdM+aQn5+v6upqDR8+vMl5l5SUqKCgQBMnTtSkSZPM/XV1deb8hPz8fA0YMEDh4eFueXjr3XffVWZmpvbv36+ysjLV1dWpqqpKFRUVioiIkCQFBQVp8ODB5jmXXXaZOnbsqPz8fF199dXas2ePdu3a5dYRqK+vV1VVlU6ePOmWI4DzFwUB2q0f/ehHWr58uYKDg5WQkNBo0uCpL7xTXC6Xunbtqvfee6/Rtc711ruwsDCvz3G5XJIahg2Sk5PdjgUGBkqSjGZ4Jtnhw4d1/fXX65577tHjjz+u6Ohobd26VRMnTnQbWpEabhs83al9LpdLjz32mG655ZZGMaGhoT7nCaB1UBCg3YqIiNCll17a5Pgrr7xSRUVFCgoK0sUXX3zGmN69eysnJ0d33HGHuS8nJ+es10xKSlJYWJj+8Y9/6O677250PCQkRFLDL+pT4uLidMEFF+jgwYOaMGHCGa/bp08frV27VpWVlWbR4SmPM9m9e7fq6uq0cOFCBQQ0TCd68cUXG8XV1dVp9+7duvrqqyVJBw4c0PHjx3XZZZdJavhzO3DggFd/1gDOPxQEwDdGjBihlJQU3XzzzZo/f7569eqlI0eO6I033tDNN9+swYMH6xe/+IXuvPNODR48WNdee63WrVunvLw89ejR44zXDA0N1f333685c+YoJCRE11xzjUpKSpSXl6eJEycqNjZWYWFhys7O1oUXXqjQ0FA5HA7NmzdPM2bMUFRUlK677jpVV1dr9+7dKi0t1cyZM5WWlqa5c+dq4sSJeuihh/TZZ5/pN7/5jVef95JLLlFdXZ2eeeYZ3XjjjXr//ff1+9//vlFccHCwpk+frqVLlyo4OFjTpk3TkCFDzALhkUce0dixY5WYmKgf//jHCggI0L/+9S/t3btXTzzxhPf/QwDwC+4yAL5hs9n0xhtv6Ic//KF+9rOfqWfPnrrtttv02WefmXcF3HrrrXrkkUd0//33a9CgQTp8+LB+/vOfe7zuww8/rFmzZumRRx5R7969deutt6q4uFhSw/j80qVLtWLFCiUkJOimm26SJN1999167rnntHr1avXr10/Dhg3T6tWrzdsUO3TooNdee0379+/XwIEDNXfuXM2fP9+rz3vFFVdo0aJFmj9/vvr27at169YpKyurUVx4eLjuv/9+paWlKSUlRWFhYdqwYYN5fPTo0fr73/+uzZs366qrrtKQIUO0aNEidevWzat8APiXzWiOwUgAANCm0SEAAAAUBAAAgIIAAACIggAAAIiCAAAAiIIAAACIggAAAIiCAAAAiIIAAACIggAAAIiCAAAASPp/6rxW1sUEoVMAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plotting confusion matrix for test set\n", + "ConfusionMatrixDisplay.from_predictions(\n", + " y_test,\n", + " y_test_predict\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "17aa63ee-0e26-4bcf-82cd-740d6493ea65", + "metadata": {}, + "source": [ + "The prediction model performed quite well on test data, with a final overall accuracy of 0.99 and $F_{\\beta}$ score of 0.99. The model only makes 40 mistakes out of 12214 test samples. 17 mistakes were predicting a poisonous mushroom as edible (false negative), while 23 mistakes were predicting a edible mushroom as poisonous (false positive). The model’s performance is promising for implementation, as false negatives represent potential safety risks and these errors could lead to consuming poisonous mushrooms, it is minimized to protect users. On the other hand, false positives are less harmful, they may lead to discarding safe mushrooms unnecessarily but do not endanger safety." + ] + }, + { + "cell_type": "markdown", + "id": "ebd8961e-06e7-4f8d-a4a8-3745e2dffe3c", + "metadata": {}, + "source": [ + "While the overall performance of the SVC model are impressive, efforts could focus on further reducing false negatives to enhance the safety of predictions. It might be important to take a closer look at the 40 misclassified observations to identify specific features contributing to these misclassifications. Implementing feature engineering on those features such as encoding rare categories differently can enhance the model’s power and reduce the misclassification cases. Additionally, trying other classifiers like Decision Tree and Random Forest which are less sensitive to scaling or irrelevant features might improve the prediction.\n" + ] + }, + { + "cell_type": "markdown", + "id": "4a4fb6c1-9c89-4ff0-ac25-81461d4c0245", + "metadata": {}, + "source": [ + "## References\n", + "Wagner, D., Heider, D., & Hattab, G. (2021). Secondary Mushroom [Dataset]. UCI Machine Learning Repository. https://doi.org/10.24432/C5FP5Q.\n", + "\n", + "Scikit-learn developers. (n.d.). QuantileTransformer. Scikit-learn. Retrieved November 21, 2024, from https://scikit-learn.org/dev/modules/generated/sklearn.preprocessing.QuantileTransformer.html\n", + "\n", + "Hunter, J. D. (2007). Matplotlib: A 2D Graphics Environment. Computing in Science & Engineering, 9(3), 90–95.\n", + "\n", + "McKinney, W. (2010). Data Structures for Statistical Computing in Python. Proceedings of the 9th Python in Science Conference, 51–56.\n", + "\n", + "Pedregosa, F., Varoquaux, G., Gramfort, A., Michel, V., Thirion, B., Grisel, O., … Duchesnay, E. (2011). Scikit-learn: Machine Learning in Python. Journal of Machine Learning Research, 12, 2825–2830.\n", + "\n", + "Harris, C. R., Millman, K. J., van der Walt, S. J., Gommers, R., Virtanen, P., Cournapeau, D., … Oliphant, T. E. (2020). Array programming with NumPy. Nature, 585(7825), 357–362.\n", + "\n", + "Virtanen, P., Gommers, R., Oliphant, T. E., Haberland, M., Reddy, T., Cournapeau, D., … van der Walt, S. J. (2020). SciPy 1.0: Fundamental Algorithms for Scientific Computing in Python. Nature Methods, 17, 261–272.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:mushroom_classifier_env]", + "language": "python", + "name": "conda-env-mushroom_classifier_env-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}