From a11a714de4492273f0d0e17d600a22571188a6fd Mon Sep 17 00:00:00 2001 From: Nhan Date: Tue, 20 Feb 2024 21:21:25 +0100 Subject: [PATCH] Done --- .../lab_imbalance-checkpoint.ipynb | 510 ++++++++++++++ your-code/lab_imbalance.ipynb | 657 ++++++++++++++---- 2 files changed, 1020 insertions(+), 147 deletions(-) create mode 100644 your-code/.ipynb_checkpoints/lab_imbalance-checkpoint.ipynb diff --git a/your-code/.ipynb_checkpoints/lab_imbalance-checkpoint.ipynb b/your-code/.ipynb_checkpoints/lab_imbalance-checkpoint.ipynb new file mode 100644 index 0000000..f091cb9 --- /dev/null +++ b/your-code/.ipynb_checkpoints/lab_imbalance-checkpoint.ipynb @@ -0,0 +1,510 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Inbalanced Classes\n", + "## In this lab, we are going to explore a case of imbalanced classes. \n", + "\n", + "\n", + "Like we disussed in class, when we have noisy data, if we are not careful, we can end up fitting our model to the noise in the data and not the 'signal'-- the factors that actually determine the outcome. This is called overfitting, and results in good results in training, and in bad results when the model is applied to real data. Similarly, we could have a model that is too simplistic to accurately model the signal. This produces a model that doesnt work well (ever). \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note: before doing the first commit, make sure you don't include the large csv file, either by adding it to .gitignore, or by deleting it." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### First, download the data from: https://www.kaggle.com/datasets/chitwanmanchanda/fraudulent-transactions-data?resource=download . Import the dataset and provide some discriptive statistics and plots. What do you think will be the important features in determining the outcome?\n", + "### Note: don't use the entire dataset, use a sample instead, with n=100000 elements, so your computer doesn't freeze." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " step type amount nameOrig oldbalanceOrg newbalanceOrig \\\n", + "0 278 CASH_IN 330218.42 C632336343 20866.00 351084.42 \n", + "1 15 PAYMENT 11647.08 C1264712553 30370.00 18722.92 \n", + "2 10 CASH_IN 152264.21 C1746846248 106589.00 258853.21 \n", + "3 403 TRANSFER 1551760.63 C333676753 0.00 0.00 \n", + "4 206 CASH_IN 78172.30 C813403091 2921331.58 2999503.88 \n", + "\n", + " nameDest oldbalanceDest newbalanceDest isFraud isFlaggedFraud \n", + "0 C834976624 452419.57 122201.15 0 0 \n", + "1 M215391829 0.00 0.00 0 0 \n", + "2 C1607284477 201303.01 49038.80 0 0 \n", + "3 C1564353608 3198359.45 4750120.08 0 0 \n", + "4 C1091768874 415821.90 337649.60 0 0 \n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "fraud=pd.read_csv(\"/Users/nhannguyen/Downloads/Fraud.csv\")\n", + "# Sample 1000 random rows from the DataFrame\n", + "fraud = fraud.sample(n=100000, random_state=42)\n", + "\n", + "# Reset the index of the sampled DataFrame\n", + "fraud.reset_index(drop=True, inplace=True)\n", + "\n", + "# Display the first few rows of the sampled DataFrame\n", + "print(fraud.head())" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Descriptive Statistics for the 'isFraud' variable:\n", + "count 100000.000000\n", + "mean 0.001410\n", + "std 0.037524\n", + "min 0.000000\n", + "25% 0.000000\n", + "50% 0.000000\n", + "75% 0.000000\n", + "max 1.000000\n", + "Name: isFraud, dtype: float64\n" + ] + } + ], + "source": [ + "# Calculate descriptive statistics for the \"isFraud\" variable\n", + "fraud_stats = fraud['isFraud'].describe()\n", + "\n", + "# Print the descriptive statistics\n", + "print(\"Descriptive Statistics for the 'isFraud' variable:\")\n", + "print(fraud_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### What is the distribution of the outcome? " + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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AAAAAMARmSYoGWM0cOBAPfLII6pYsaIkKTw8XJKSTRLh5+dnXWZv4sSJ8vX1tT6KFCmSvoUDAAAAyHIyTVB67bXXtG/fPn300UfJllns+juNMcnakgwbNkwRERHWx/nz59OlXgAAAABZV6qnB09Pffv21erVq/XTTz+pcOHC1nZ/f39Jd3qWChYsaG2/dOnSPacid3d3l7u7e/oWDAAAACBLc2qPkjFGr732mr744gtt3rxZQUFBNsuDgoLk7++vDRs2WNvi4uK0ZcsW1a1bN6PLBQAAAPAf4dQepT59+mjlypX6+uuv5e3tbb3uyNfXVx4eHrJYLBowYIBCQ0NVqlQplSpVSqGhofL09FSnTp2cWToAAACALMypQWnevHmSpEaNGtm0L1myRF27dpUkDR48WLdu3VLv3r117do1hYSEaP369fL29s7gagEAAAD8V2Sq+yilB+6jBNzBPSAcl7U/HQEAqcU51HGZ9Rz60N5HCQAAAAAyA4ISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHacGpZ9++klPPPGEAgICZLFY9NVXX9ksN8Zo9OjRCggIkIeHhxo1aqSDBw86p1gAAAAA/xlODUo3b95U5cqVNXv27BSXT5kyRdOnT9fs2bO1c+dO+fv7q1mzZoqKisrgSgEAAAD8l7g6c+ctW7ZUy5YtU1xmjNGMGTM0fPhwtWvXTpK0bNky+fn5aeXKlerZs2dGlgoAAADgPyTTXqN0+vRphYeHq3nz5tY2d3d3NWzYUNu2bbvn62JjYxUZGWnzAAAA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Bwfr2LFj1i8V2bJl4zhDmgoLC1P16tWVmJioa9eu6auvvtLt27c51pCmoqOjNXToUCUmJlo/z6Q7PZmS9Oeff+r777/XxYsXFRsb66wy/7MISlnU+vXr9cgjj6hatWp67rnnNGTIEP3www+Ki4tTly5dtGLFCr3//vuaOXMms5PhX9m0aZP69++vDz/8UC+88IJWrVql7NmzKzQ0VN99950SExMJS0gTSUNTBg4cqI0bN2r27NmaOnWq9csFxxnSStI1SSNGjNC1a9esn2lr165VfHw8xxrSjLu7u3r06KEKFSqofv36kqSZM2dq1qxZ6tOnj65fv66JEyeqcuXKevbZZzVq1CgdP37cyVX/d1gMv+lZStI/548//qg+ffro5MmTmjBhgpYvX66bN28qNjZWTz31lDp16qRffvlFEydOVO/evdW5c2eVKFHCydXjYXP+/HmdPHlSPj4+qlatmuLi4pQ9e3Zdv35dbdu2VVxcnIYPH65WrVpZ/wrLMDw8qKlTp+rSpUuaOnWqJCkuLk4rVqxQz5499b///c86DI/jDP9GTEyMevbsqaJFi1qvSbpx44batm2rqKgovfnmm3r88ccZWox/JSwsTL/88ot69+6t+Ph4bd68WQMHDtTff/+tmJgYrVu3TrVq1bKu//HHH+v333/XihUrtG3bNhUtWtSJ1f+HGGQpkZGRxhhjYmJizE8//WSKFi1qnn/+eRMXF2f++OMPM3bsWPPss88aLy8v8/jjjxuLxWIsFouZN2+ekyvHwyYsLMxYLBazaNEik5iYaG2/ffu2McaY69evmwYNGpg6deqYb775xiQkJDirVDzkzpw5Y1555RUTHR1tjPm/Y8wYY+Li4szixYuNm5ubefPNN63tdx+TQGodO3bMbNu2zfz999/Wtri4OGOMMTdu3DBNmjQxNWvWNF9++aX1OORYg6P27t1rLBaLGT58uLUtPj7efPfdd+aRRx4xZcqUsbbHxsbavPbWrVsZVieMIShlIT///LPx8vIy+/fvN8bc+XD/8ccfTb58+UybNm1s1j1x4oT55ptvTJcuXUybNm1svngAqTVw4EDj6elplixZYnMM3R2WGjZsaOrVq2c++eQTwhIeyKpVq0ypUqVMu3btrH8MuldYGjFihLPKRBYwYMAAY7FYzPfff2+M+b8QlHS83R2Wvv76a86dcNje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XzsdlCxZUjdv3tT69evVvHnzFGesW7Vqla5cuaKWLVuqcePGTqgSD6vIyEj5+PjIYrFYpyWdNGmSOnfurNjYWFWtWjXZ+t7e3ipWrJhNOzMpAsgs9u3bp7Zt2ypXrlw6efKkjDFatGiRBg4cqKZNm6pHjx6aPHmy1q5dq7Vr16pq1arq1q2bVq1aZZ3tjs803M++fftUp04d9e/fX3379tWvv/6qZ599VhUqVFCjRo1ksVjk6emphg0bas+ePSpevLgkMfriP4yhd+ng1KlTqlatmh599FFNnz5dRYsWlfR/PQCRkZHq3Lmz2rRpo27dukli4gakzooVK/Tee++pdu3aGjFihLJnz25zrdHdvZfGGEVEROiFF15QZGSkfvjhB44xAJlO0pfXvn37asiQITp27Jhmz56t7777TuvWrdP8+fP1zTffyMvLSx9//LFq1apl/eLKF1ik1uHDhxUcHKz+/ftr2rRp1vayZcvKy8tLP/30k7y8vKztVapUUe3atTV//nxnlItMgk+XdFC8eHHNnz9fa9as0Ztvvqm9e/dKuvPXrj///FMdO3bUlStX1LlzZ+tr+AKL+4mOjtaXX36pnDlzav/+/WrQoIGGDh2q3bt3W9dJCklXr17Vxx9/rI4dO+rPP//Upk2b5OLiooSEBGeVDwDJnD9/Xk2bNlXr1q01adIk5c6dWyEhIWrfvr3i4uLk4uKiOnXq6PLly1q1apVq1aplM2yYkITUSExM1OnTp5WQkKBChQopMjJSkhQaGqpjx45Jknr06KHx48db72FZtWpV/fXXX4qKinJa3XA+ht6lkw4dOujGjRvq3bu3tmzZoooVKyoxMVERERFKTEzUL7/8IldXV3qSkGqenp5q3LixFi5cqLCwMH322Wdat26dWrRooeeff14NGzbUU089JenOhCJLly5V8eLFtWbNGrm6ulqH6QFAZpGQkKCgoCDFxsZq69ateuSRRyRJ+fPnl8ViUbZs2fTyyy/r/fff19KlS1WzZk2G2MEh+/fv17vvvqv3339f7777rvr37y93d3ddvnxZ7777rj788EMVKlRIx48f1/r16zVz5kxNmzZNRYoU0dSpU+Xt7e3stwAnYuhdOtu7d68WL16sY8eOqXDhwqpatap69eolFxcXvrjigTz22GN64okn1LNnT7m5uWnNmjVq06aNvLy8VK9e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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "# Group the data by transaction type and calculate the count of fraudulent transactions for each type\n", + "fraud_by_type = fraud.groupby('type')['isFraud'].sum()\n", + "\n", + "# Plot the distribution of fraud by transaction type\n", + "plt.figure(figsize=(10, 6))\n", + "fraud_by_type.plot(kind='bar', color='blue')\n", + "plt.title('Distribution of Fraud by Transaction Type')\n", + "plt.xlabel('Transaction Type')\n", + "plt.ylabel('Count of Fraudulent Transactions')\n", + "plt.xticks(rotation=45, ha='right')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " step type amount nameOrig oldbalanceOrg newbalanceOrig \\\n", + "0 278 CASH_IN 330218.42 C632336343 20866.0 351084.42 \n", + "\n", + " nameDest oldbalanceDest newbalanceDest isFraud isFlaggedFraud \n", + "0 C834976624 452419.57 122201.15 0 0 \n" + ] + } + ], + "source": [ + "# IsFraud is the most importatnt\n", + "print(fraud.head(1))" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "RangeIndex: 100000 entries, 0 to 99999\n", + "Data columns (total 11 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 step 100000 non-null int64 \n", + " 1 type 100000 non-null object \n", + " 2 amount 100000 non-null float64\n", + " 3 nameOrig 100000 non-null object \n", + " 4 oldbalanceOrg 100000 non-null float64\n", + " 5 newbalanceOrig 100000 non-null float64\n", + " 6 nameDest 100000 non-null object \n", + " 7 oldbalanceDest 100000 non-null float64\n", + " 8 newbalanceDest 100000 non-null float64\n", + " 9 isFraud 100000 non-null int64 \n", + " 10 isFlaggedFraud 100000 non-null int64 \n", + "dtypes: float64(5), int64(3), object(3)\n", + "memory usage: 8.4+ MB\n" + ] + } + ], + "source": [ + "fraud.info()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Clean the dataset. Pre-process it to make it suitable for ML training. Feel free to explore, drop, encode, transform, etc. Whatever you feel will improve the model score." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.impute import SimpleImputer\n", + "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", + "from sklearn.compose import ColumnTransformer\n", + "from sklearn.pipeline import Pipeline\n", + "\n", + "\n", + "# Drop unnecessary columns\n", + "fraud.drop(['nameOrig', 'nameDest', 'isFlaggedFraud'], axis=1, inplace=True)\n", + "\n", + "# Separate numerical and categorical columns\n", + "numerical_cols = ['step', 'amount', 'oldbalanceOrg', 'newbalanceOrig', 'oldbalanceDest', 'newbalanceDest']\n", + "categorical_cols = ['type']\n", + "\n", + "# Create pipelines for numerical and categorical preprocessing steps\n", + "numerical_pipeline = Pipeline([\n", + " ('imputer', SimpleImputer(strategy='mean')),\n", + " ('scaler', StandardScaler())\n", + "])\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "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", + "
steptypeamountoldbalanceOrgnewbalanceOrigoldbalanceDestnewbalanceDestisFraud
0278CASH_IN330218.4220866.00351084.42452419.57122201.150
115PAYMENT11647.0830370.0018722.920.000.000
210CASH_IN152264.21106589.00258853.21201303.0149038.800
3403TRANSFER1551760.630.000.003198359.454750120.080
4206CASH_IN78172.302921331.582999503.88415821.90337649.600
\n", + "
" + ], + "text/plain": [ + " step type amount oldbalanceOrg newbalanceOrig oldbalanceDest \\\n", + "0 278 CASH_IN 330218.42 20866.00 351084.42 452419.57 \n", + "1 15 PAYMENT 11647.08 30370.00 18722.92 0.00 \n", + "2 10 CASH_IN 152264.21 106589.00 258853.21 201303.01 \n", + "3 403 TRANSFER 1551760.63 0.00 0.00 3198359.45 \n", + "4 206 CASH_IN 78172.30 2921331.58 2999503.88 415821.90 \n", + "\n", + " newbalanceDest isFraud \n", + "0 122201.15 0 \n", + "1 0.00 0 \n", + "2 49038.80 0 \n", + "3 4750120.08 0 \n", + "4 337649.60 0 " + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fraud.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run a logisitc regression classifier and evaluate its accuracy." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy: 0.999\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "from sklearn.impute import SimpleImputer\n", + "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", + "from sklearn.compose import ColumnTransformer\n", + "from sklearn.pipeline import Pipeline\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.linear_model import LogisticRegression\n", + "from sklearn.metrics import accuracy_score\n", + "\n", + "# Ensure that 'type' column is in categorical_cols list\n", + "categorical_cols = ['type']\n", + "\n", + "# Ensure that all numerical columns are present in the DataFrame\n", + "numerical_cols = ['step', 'amount', 'oldbalanceOrg', 'newbalanceOrig', 'oldbalanceDest', 'newbalanceDest']\n", + "for col in numerical_cols:\n", + " if col not in fraud.columns:\n", + " raise ValueError(f\"Column '{col}' is not present in the DataFrame.\")\n", + "\n", + "# Create pipelines for numerical and categorical preprocessing steps\n", + "numerical_pipeline = Pipeline([\n", + " ('imputer', SimpleImputer(strategy='mean')),\n", + " ('scaler', StandardScaler())\n", + "])\n", + "\n", + "categorical_pipeline = Pipeline([\n", + " ('encoder', OneHotEncoder())\n", + "])\n", + "\n", + "# Create a column transformer to apply the appropriate preprocessing steps to each column\n", + "preprocessor = ColumnTransformer([\n", + " ('num', numerical_pipeline, numerical_cols),\n", + " ('cat', categorical_pipeline, categorical_cols)\n", + "])\n", + "\n", + "# Fit and transform the data using the preprocessor\n", + "X_processed = preprocessor.fit_transform(fraud.drop('isFraud', axis=1))\n", + "y = fraud['isFraud']\n", + "\n", + "# Split the data into training and testing sets\n", + "X_train, X_test, y_train, y_test = train_test_split(X_processed, y, test_size=0.2, random_state=42)\n", + "\n", + "# Initialize logistic regression classifier\n", + "logistic_reg = LogisticRegression()\n", + "\n", + "# Train the classifier on the training data\n", + "logistic_reg.fit(X_train, y_train)\n", + "\n", + "# Predict the labels for the test set\n", + "y_pred = logistic_reg.predict(X_test)\n", + "\n", + "# Evaluate the accuracy of the model\n", + "accuracy = accuracy_score(y_test, y_pred)\n", + "\n", + "# Print the accuracy score\n", + "print(\"Accuracy:\", accuracy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now pick a model of your choice and evaluate its accuracy." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy (Random Forest): 0.99965\n" + ] + } + ], + "source": [ + "from sklearn.ensemble import RandomForestClassifier\n", + "\n", + "# Initialize Random Forest Classifier\n", + "random_forest = RandomForestClassifier(random_state=42)\n", + "\n", + "# Train the classifier on the training data\n", + "random_forest.fit(X_train, y_train)\n", + "\n", + "# Predict the labels for the test set\n", + "y_pred_rf = random_forest.predict(X_test)\n", + "\n", + "# Evaluate the accuracy of the model\n", + "accuracy_rf = accuracy_score(y_test, y_pred_rf)\n", + "\n", + "# Print the accuracy score\n", + "print(\"Accuracy (Random Forest):\", accuracy_rf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Which model worked better and how do you know?" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "#both model has pretty impressive accuracy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note: before doing the first commit, make sure you don't include the large csv file, either by adding it to .gitignore, or by deleting it." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "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.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/your-code/lab_imbalance.ipynb b/your-code/lab_imbalance.ipynb index dbb15e1..f091cb9 100644 --- a/your-code/lab_imbalance.ipynb +++ b/your-code/lab_imbalance.ipynb @@ -1,147 +1,510 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Inbalanced Classes\n", - "## In this lab, we are going to explore a case of imbalanced classes. \n", - "\n", - "\n", - "Like we disussed in class, when we have noisy data, if we are not careful, we can end up fitting our model to the noise in the data and not the 'signal'-- the factors that actually determine the outcome. This is called overfitting, and results in good results in training, and in bad results when the model is applied to real data. Similarly, we could have a model that is too simplistic to accurately model the signal. This produces a model that doesnt work well (ever). \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Note: before doing the first commit, make sure you don't include the large csv file, either by adding it to .gitignore, or by deleting it." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### First, download the data from: https://www.kaggle.com/datasets/chitwanmanchanda/fraudulent-transactions-data?resource=download . Import the dataset and provide some discriptive statistics and plots. What do you think will be the important features in determining the outcome?\n", - "### Note: don't use the entire dataset, use a sample instead, with n=100000 elements, so your computer doesn't freeze." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "# Your code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### What is the distribution of the outcome? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Your response here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Clean the dataset. Pre-process it to make it suitable for ML training. Feel free to explore, drop, encode, transform, etc. Whatever you feel will improve the model score." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "# Your code here\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Run a logisitc regression classifier and evaluate its accuracy." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Your code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Now pick a model of your choice and evaluate its accuracy." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Your code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Which model worked better and how do you know?" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# Your response here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Note: before doing the first commit, make sure you don't include the large csv file, either by adding it to .gitignore, or by deleting it." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "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.6.8" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Inbalanced Classes\n", + "## In this lab, we are going to explore a case of imbalanced classes. \n", + "\n", + "\n", + "Like we disussed in class, when we have noisy data, if we are not careful, we can end up fitting our model to the noise in the data and not the 'signal'-- the factors that actually determine the outcome. This is called overfitting, and results in good results in training, and in bad results when the model is applied to real data. Similarly, we could have a model that is too simplistic to accurately model the signal. This produces a model that doesnt work well (ever). \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note: before doing the first commit, make sure you don't include the large csv file, either by adding it to .gitignore, or by deleting it." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### First, download the data from: https://www.kaggle.com/datasets/chitwanmanchanda/fraudulent-transactions-data?resource=download . Import the dataset and provide some discriptive statistics and plots. What do you think will be the important features in determining the outcome?\n", + "### Note: don't use the entire dataset, use a sample instead, with n=100000 elements, so your computer doesn't freeze." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " step type amount nameOrig oldbalanceOrg newbalanceOrig \\\n", + "0 278 CASH_IN 330218.42 C632336343 20866.00 351084.42 \n", + "1 15 PAYMENT 11647.08 C1264712553 30370.00 18722.92 \n", + "2 10 CASH_IN 152264.21 C1746846248 106589.00 258853.21 \n", + "3 403 TRANSFER 1551760.63 C333676753 0.00 0.00 \n", + "4 206 CASH_IN 78172.30 C813403091 2921331.58 2999503.88 \n", + "\n", + " nameDest oldbalanceDest newbalanceDest isFraud isFlaggedFraud \n", + "0 C834976624 452419.57 122201.15 0 0 \n", + "1 M215391829 0.00 0.00 0 0 \n", + "2 C1607284477 201303.01 49038.80 0 0 \n", + "3 C1564353608 3198359.45 4750120.08 0 0 \n", + "4 C1091768874 415821.90 337649.60 0 0 \n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "fraud=pd.read_csv(\"/Users/nhannguyen/Downloads/Fraud.csv\")\n", + "# Sample 1000 random rows from the DataFrame\n", + "fraud = fraud.sample(n=100000, random_state=42)\n", + "\n", + "# Reset the index of the sampled DataFrame\n", + "fraud.reset_index(drop=True, inplace=True)\n", + "\n", + "# Display the first few rows of the sampled DataFrame\n", + "print(fraud.head())" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Descriptive Statistics for the 'isFraud' variable:\n", + "count 100000.000000\n", + "mean 0.001410\n", + "std 0.037524\n", + "min 0.000000\n", + "25% 0.000000\n", + "50% 0.000000\n", + "75% 0.000000\n", + "max 1.000000\n", + "Name: isFraud, dtype: float64\n" + ] + } + ], + "source": [ + "# Calculate descriptive statistics for the \"isFraud\" variable\n", + "fraud_stats = fraud['isFraud'].describe()\n", + "\n", + "# Print the descriptive statistics\n", + "print(\"Descriptive Statistics for the 'isFraud' variable:\")\n", + "print(fraud_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### What is the distribution of the outcome? " + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0oAAAJSCAYAAAD9KDWvAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB9PElEQVR4nO3deVhU5f//8dcIiICAO4gbuK+4i0vuaS6lZVpmpWamprlkflwyd8U1M3ctt1LL9kzL3MoytVwS933NJJcUUAQE7t8f/pivM2AyBgzS83Fdc9Xc58w578HDnHlx3+c+FmOMEQAAAADAKpuzCwAAAACAzIagBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBCBNLF26VBaLxfrIkSOH/P391bhxY02cOFGXLl1K9prRo0fLYrE4tJ/o6GiNHj1aP/74o0OvS2lfgYGBevzxxx3azv2sXLlSM2bMSHGZxWLR6NGj03R/aW3Tpk2qUaOGvLy8ZLFY9NVXX6W43pkzZ2z+ve9+1KhRI2OL/gdJx+WZM2f+cb2uXbsqZ86c6V7H/R6BgYHpVoOzHTp0SKNHj07x36Jr164Z/t67du2aqn+Trl27ZmhdADIPV2cXACBrWbJkicqWLavbt2/r0qVL2rp1qyZPnqxp06Zp1apVevTRR63rdu/eXS1atHBo+9HR0RozZowkqVGjRql+3YPs60GsXLlSBw4c0IABA5It2759uwoXLpzuNTwoY4yeeeYZlS5dWqtXr5aXl5fKlCnzj6/p27evOnXqZNOWnoHjYdW6dWtt377dpq1OnTpq37693njjDWubu7t7RpeWYQ4dOqQxY8aoUaNGyULRiBEj1L9//wytZ8SIEerVq5f1+Z49e9SnTx+FhoaqcePG1vb8+fNnaF0AMg+CEoA0VbFiRZsehaefflqvv/66HnnkEbVr107Hjx+Xn5+fJKlw4cLpHhyio6Pl6emZIfu6n9q1azt1//fz559/6u+//9ZTTz2lpk2bpuo1RYsWTfX7MsYoJiZGHh4e/6bMh1L+/PlT/MLt5+f3jz+/hIQExcfHZ+kAJUklSpRwyj7v3m9MTIwkqVSpUpn+dxVAxmDoHYB0V7RoUb399tuKiorSggULrO0pDYfbvHmzGjVqpLx588rDw0NFixbV008/rejoaJ05c8b6ZXPMmDHJhsYkbW/Pnj1q3769cufObf0i9E/D/L788ksFBwcrR44cKl68uGbOnGmz/F7Dt3788UdZLBbrMMBGjRpp7dq1Onv2rM3QnSQpDb07cOCA2rZtq9y5cytHjhyqUqWKli1bluJ+PvroIw0fPlwBAQHy8fHRo48+qqNHj977B3+XrVu3qmnTpvL29panp6fq1q2rtWvXWpePHj3aGiSHDBmSJsPALBaLXnvtNc2fP1/lypWTu7u79b2NGTNGISEhypMnj3x8fFStWjUtWrRIxphk20hpuGJgYGCyIVE7duxQvXr1lCNHDgUEBGjYsGG6ffu2QzUfPHhQTZs2lZeXl/Lnz6/XXntN0dHR1uVNmzZV2bJlk9VpjFHJkiXVunVrh/Z3t6ThjFOmTNH48eMVFBQkd3d3/fDDD4qJidEbb7yhKlWqyNfXV3ny5FGdOnX09ddfJ9tO0s/9ww8/VLly5eTp6anKlStrzZo1NutdvnxZPXr0UJEiReTu7q78+fOrXr162rhxo3WdDRs2qG3btipcuLBy5MihkiVLqmfPnrpy5Uqy/R45ckTPPfec/Pz85O7urqJFi6pz586KjY3V0qVL1aFDB0lS48aNrb8bS5culZTy0LuYmBgNGzZMQUFByp49uwoVKqQ+ffro+vXrNuslDaFdt26dqlWrJg8PD5UtW1aLFy9+gH+F//Pzzz9bf+/sffDBB7JYLNq5c6e1/pw5c973+JHuHCtz585VlSpV5OHhody5c6t9+/Y6derUv6oXQNqjRwlAhmjVqpVcXFz0008/3XOdM2fOqHXr1qpfv74WL16sXLly6cKFC1q3bp3i4uJUsGBBrVu3Ti1atNDLL7+s7t27S0o+NKZdu3bq2LGjevXqpZs3b/5jXXv37tWAAQM0evRo+fv7a8WKFerfv7/i4uI0aNAgh97j3Llz1aNHD508eVJffvnlfdc/evSo6tatqwIFCmjmzJnKmzevli9frq5du+qvv/7S4MGDbdZ/8803Va9ePb3//vuKjIzUkCFD9MQTT+jw4cNycXG55362bNmiZs2aKTg4WIsWLZK7u7vmzp2rJ554Qh999JGeffZZde/eXZUrV1a7du2sw+lS04uRmJio+Ph4mzYXFxdrQPzqq6/0888/a+TIkfL391eBAgUk3fm37tmzp4oWLSrpTsjp27evLly4oJEjR953v/YOHTqkpk2bKjAwUEuXLpWnp6fmzp2rlStXpnobt2/fVqtWrdSzZ08NHTpU27Zt0/jx43X27Fl98803kqT+/furbdu22rRpk80w0u+++04nT55MFrIfxMyZM1W6dGlNmzZNPj4+KlWqlGJjY/X3339r0KBBKlSokOLi4rRx40a1a9dOS5YsUefOnW22sXbtWu3cuVNjx45Vzpw5NWXKFD311FM6evSoihcvLkl68cUXtWfPHk2YMEGlS5fW9evXtWfPHl29etW6nZMnT6pOnTrq3r27fH19debMGU2fPl2PPPKI9u/fLzc3N0lSWFiYHnnkEeXLl09jx45VqVKldPHiRa1evVpxcXFq3bq1QkND9eabb2rOnDmqVq2apHv3JBlj9OSTT2rTpk0aNmyY6tevr3379mnUqFHavn27tm/fbnN8hoWF6Y033tDQoUPl5+en999/Xy+//LJKliypBg0aPNC/Q/369VW1alXNmTNHzz33nM2y2bNnq2bNmqpZs6a1LTXHjyT17NlTS5cuVb9+/TR58mT9/fffGjt2rOrWrauwsDBrjzuATMAAQBpYsmSJkWR27tx5z3X8/PxMuXLlrM9HjRpl7v4Y+uyzz4wks3fv3ntu4/Lly0aSGTVqVLJlSdsbOXLkPZfdrVixYsZisSTbX7NmzYyPj4+5efOmzXs7ffq0zXo//PCDkWR++OEHa1vr1q1NsWLFUqzdvu6OHTsad3d3c+7cOZv1WrZsaTw9Pc3169dt9tOqVSub9T755BMjyWzfvj3F/SWpXbu2KVCggImKirK2xcfHm4oVK5rChQubxMREY4wxp0+fNpLM1KlT/3F7d6+b0mPDhg3W9+vr62v+/vvvf9xWQkKCuX37thk7dqzJmzevtZ6kbaT0b12sWDHTpUsX6/Nnn33WeHh4mPDwcJv3WLZs2RT/7ex16dLFSDLvvvuuTfuECROMJLN161ZrrcWLFzdt27a1Wa9ly5amRIkSNrXfjyTTp08f6/Okn2mJEiVMXFzcP742Pj7e3L5927z88sumatWqybbr5+dnIiMjrW3h4eEmW7ZsZuLEida2nDlzmgEDBqS63sTERHP79m1z9uxZI8l8/fXX1mVNmjQxuXLlMpcuXbrn6z/99NNkvy9JunTpYvN7s27dOiPJTJkyxWa9VatWGUlm4cKF1rZixYqZHDlymLNnz1rbbt26ZfLkyWN69uyZ6veX9Hv26aefWtuSfvd///13a9tvv/1mJJlly5bZ1J+a42f79u1Gknn77bdt1jt//rzx8PAwgwcPTnW9ANIfQ+8AZBhjN1zJXpUqVZQ9e3b16NFDy5Yte+ChKE8//XSq161QoYIqV65s09apUydFRkZqz549D7T/1Nq8ebOaNm2qIkWK2LR37dpV0dHRyS7+b9Omjc3z4OBgSdLZs2fvuY+bN2/q119/Vfv27W0mWXBxcdGLL76oP/74I9XD91LSv39/7dy50+YREhJiXd6kSRPlzp072es2b96sRx99VL6+vnJxcZGbm5tGjhypq1evpjhD4v388MMPatq0qc1f411cXPTss886tJ3nn3/e5nnSRBU//PCDJClbtmx67bXXtGbNGp07d07SnV6XdevWqXfv3g7P4piSNm3aWHtq7vbpp5+qXr16ypkzp1xdXeXm5qZFixbp8OHDydZt3LixvL29rc/9/PxUoEABm2OlVq1aWrp0qcaPH68dO3akOEzx0qVL6tWrl4oUKWLdZ7FixSTJut/o6Ght2bJFzzzzTJpNfLB582ZJSja8skOHDvLy8tKmTZts2qtUqWLtnZSkHDlyqHTp0v/4u5Eazz33nAoUKKA5c+ZY22bNmqX8+fOneGzd7/hZs2aNLBaLXnjhBcXHx1sf/v7+qly5ssOzeQJIXwQlABni5s2bunr1qgICAu65TokSJbRx40YVKFBAffr0sV5s/e677zq0r4IFC6Z6XX9//3u23T0EKT1cvXo1xVqTfkb2+8+bN6/N86ShR7du3brnPq5duyZjjEP7cUThwoVVo0YNm8fdX9BT2u9vv/2m5s2bS5Lee+89/fLLL9q5c6eGDx9+3/dzL1evXv3Hf8vUcHV1TfYzTulY6Natmzw8PDR//nxJ0pw5c+Th4aFu3bo5XHdKUvqZffHFF3rmmWdUqFAhLV++XNu3b9fOnTvVrVs36yQEd7N/H9Kd4+Xun+2qVavUpUsXvf/++6pTp47y5Mmjzp07Kzw8XNKdYZXNmzfXF198ocGDB2vTpk367bfftGPHDkn/9+907do1JSQkpOlkKVevXpWrq2uy4GWxWOTv73/f342U3u+DcHd3V8+ePbVy5Updv35dly9f1ieffKLu3bsnG5qamuPnr7/+kjFGfn5+cnNzs3ns2LEjxWu/ADgP1ygByBBr165VQkLCfaf0rl+/vurXr6+EhATt2rVLs2bN0oABA+Tn56eOHTumal+O/FU/6UthSm1JX3py5MghSYqNjbVZ799+qcmbN68uXryYrP3PP/+UJOXLl+9fbV+ScufOrWzZsqX7fu4lpX+Ljz/+WG5ublqzZo31ZyspxXs2ubu7J/u5SymHyH/6t0yN+Ph4Xb161ebLrv2xIEm+vr7WgDFo0CAtWbJEnTp1Uq5cuVK9r3+S0s9s+fLlCgoK0qpVq2yWp/SzSa18+fJpxowZmjFjhs6dO6fVq1dr6NChunTpktatW6cDBw4oLCxMS5cuVZcuXayvO3HihM128uTJIxcXF/3xxx8PXIu9vHnzKj4+XpcvX7YJS8YYhYeH21wblN5effVVTZo0SYsXL1ZMTIzi4+NtphVPkprjJ1++fLJYLPr5559TvAYwq89uCDxs6FECkO7OnTunQYMGydfXVz179kzVa1xcXBQSEmId8pI0DC41vSiOOHjwoMLCwmzaVq5cKW9vb+sF50mzce3bt89mvdWrVyfbniN/xW7atKk2b95sDSxJPvjgA3l6eqbJFMVeXl4KCQnRF198YVNXYmKili9frsKFC6t06dL/ej+OsFgscnV1tZmA4tatW/rwww+TrRsYGJjs575582bduHHDpq1x48batGmT/vrrL2tbQkKCVq1a5VBtK1assHmeNBmEfcDv16+frly5ovbt2+v69et67bXXHNqPoywWi7Jnz24TksLDw1Oc9e5BFC1aVK+99pqaNWtm/V1L2pf9l/e7Z66UJA8PDzVs2FCffvrpP/7xwJHf3aTp6ZcvX27T/vnnn+vmzZupnr4+LRQsWFAdOnTQ3LlzNX/+fD3xxBM2w/zudr/j5/HHH5cxRhcuXEjWE1ujRg1VqlQpXd8LAMfQowQgTR04cMA67v7SpUv6+eeftWTJErm4uOjLL7/8x2sY5s+fr82bN6t169YqWrSoYmJirFP8Js0w5u3trWLFiunrr79W06ZNlSdPHuXLl++Bp7IOCAhQmzZtNHr0aBUsWFDLly/Xhg0bNHnyZHl6ekqSatasqTJlymjQoEGKj49X7ty59eWXX2rr1q3JtlepUiV98cUXmjdvnqpXr65s2bLZ3FfqbqNGjdKaNWvUuHFjjRw5Unny5NGKFSu0du1aTZkyRb6+vg/0nuxNnDhRzZo1U+PGjTVo0CBlz55dc+fO1YEDB/TRRx+lyXU1jmjdurWmT5+uTp06qUePHrp69aqmTZuW4l/TX3zxRY0YMUIjR45Uw4YNdejQIc2ePTvZz+att97S6tWr1aRJE40cOVKenp6aM2fOfWc9vFv27Nn19ttv68aNG6pZs6Z11rKWLVvqkUcesVm3dOnSatGihb777js98sgjya5zS2uPP/64vvjiC/Xu3Vvt27fX+fPnNW7cOBUsWFDHjx93eHsRERFq3LixOnXqpLJly8rb21s7d+7UunXr1K5dO0lS2bJlVaJECQ0dOlTGGOXJk0fffPONNmzYkGx7STPhhYSEaOjQoSpZsqT++usvrV69WgsWLJC3t7cqVqwoSVq4cKG8vb2VI0cOBQUFpThsrlmzZnrsscc0ZMgQRUZGql69etZZ76pWraoXX3zR4ff8b/Tv39967d2SJUtSXCc1x0+9evXUo0cPvfTSS9q1a5caNGggLy8vXbx4UVu3blWlSpX06quvZtj7AnAfzpxJAkDWkTQ7VNIje/bspkCBAqZhw4YmNDQ0xdmw7Gei2759u3nqqadMsWLFjLu7u8mbN69p2LChWb16tc3rNm7caKpWrWrc3d2NJOvsZ0nbu3z58n33Zcyd2bJat25tPvvsM1OhQgWTPXt2ExgYaKZPn57s9ceOHTPNmzc3Pj4+Jn/+/KZv375m7dq1yWbx+vvvv0379u1Nrly5jMVisdmnUpjBbf/+/eaJJ54wvr6+Jnv27KZy5cpmyZIlNuukNBuXMf83S5r9+in5+eefTZMmTYyXl5fx8PAwtWvXNt98802K23Nk1rt/Wld2s7rdbfHixaZMmTLG3d3dFC9e3EycONEsWrQo2Qx1sbGxZvDgwaZIkSLGw8PDNGzY0OzduzfZrHfGGPPLL7+Y2rVrG3d3d+Pv72/+97//mYULF6Z61jsvLy+zb98+06hRI+Ph4WHy5MljXn31VXPjxo0UX7N06VIjyXz88cf/uO17sf/53O9nOmnSJBMYGGjc3d1NuXLlzHvvvZficX2vn/vdP7OYmBjTq1cvExwcbHx8fIyHh4cpU6aMGTVqlHW2R2OMOXTokGnWrJnx9vY2uXPnNh06dDDnzp1L8Vg+dOiQ6dChg8mbN6/Jnj27KVq0qOnatauJiYmxrjNjxgwTFBRkXFxcbI5d+1nvjLkzc92QIUNMsWLFjJubmylYsKB59dVXzbVr15K9r9atWyd7vw0bNjQNGzZM8WeZknv9niUJDAy0mbXzbo4eP4sXLzYhISHW38cSJUqYzp07m127dqW6XgDpz2LMfaahAgAAyTz99NPasWOHzpw5k+Isdcg69u3bp8qVK2vOnDnq3bt3suVdu3bVZ599lmxIKICHG0PvAABIpdjYWO3Zs0e//fabvvzyS02fPp2QlIWdPHlSZ8+e1ZtvvqmCBQsmm64cQNZGUAIAIJUuXryounXrysfHRz179lTfvn2dXRLS0bhx4/Thhx+qXLly+vTTT63XLQL4b2DoHQAAAADYYXpwAAAAALBDUAIAAAAAOwQlAAAAALCT5SdzSExM1J9//ilvb+8Mv6kiAAAAgMzDGKOoqCgFBAQoW7Z/7jPK8kHpzz//VJEiRZxdBgAAAIBM4vz58ypcuPA/rpPlg5K3t7ekOz8MHx8fJ1cDAAAAwFkiIyNVpEgRa0b4J1k+KCUNt/Px8SEoAQAAAEjVJTlM5gAAAAAAdghKAAAAAGCHoAQAAAAAdghKAAAAAGCHoAQAAAAAdghKAAAAAGCHoAQAAAAAdghKAAAAAGCHoAQAAAAAdpwalOLj4/XWW28pKChIHh4eKl68uMaOHavExETrOsYYjR49WgEBAfLw8FCjRo108OBBJ1YNAAAAIKtzalCaPHmy5s+fr9mzZ+vw4cOaMmWKpk6dqlmzZlnXmTJliqZPn67Zs2dr586d8vf3V7NmzRQVFeXEygEAAABkZU4NStu3b1fbtm3VunVrBQYGqn379mrevLl27dol6U5v0owZMzR8+HC1a9dOFStW1LJlyxQdHa2VK1c6s3QAAAAAWZhTg9IjjzyiTZs26dixY5KksLAwbd26Va1atZIknT59WuHh4WrevLn1Ne7u7mrYsKG2bduW4jZjY2MVGRlp8wAAAAAAR7g6c+dDhgxRRESEypYtKxcXFyUkJGjChAl67rnnJEnh4eGSJD8/P5vX+fn56ezZsyluc+LEiRozZkz6Fg4AAAAgS3Nqj9KqVau0fPlyrVy5Unv27NGyZcs0bdo0LVu2zGY9i8Vi89wYk6wtybBhwxQREWF9nD9/Pt3qBwAAAJA1ObVH6X//+5+GDh2qjh07SpIqVaqks2fPauLEierSpYv8/f0l3elZKliwoPV1ly5dStbLlMTd3V3u7u7pXzwAAACALMupPUrR0dHKls22BBcXF+v04EFBQfL399eGDRusy+Pi4rRlyxbVrVs3Q2sFAAAA8N/h1B6lJ554QhMmTFDRokVVoUIF/f7775o+fbq6desm6c6QuwEDBig0NFSlSpVSqVKlFBoaKk9PT3Xq1MmZpQMAAADIwpwalGbNmqURI0aod+/eunTpkgICAtSzZ0+NHDnSus7gwYN169Yt9e7dW9euXVNISIjWr18vb29vJ1YOAAAAICuzGGOMs4tIT5GRkfL19VVERIR8fHycXQ4AAAAeMveYQwz/ILMmDEeygVOvUQIAAACAzIigBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYIegBAAAAAB2CEoAAAAAYMepQSkwMFAWiyXZo0+fPpIkY4xGjx6tgIAAeXh4qFGjRjp48KAzSwYAAADwH+DUoLRz505dvHjR+tiwYYMkqUOHDpKkKVOmaPr06Zo9e7Z27twpf39/NWvWTFFRUc4sGwAAAEAW59SglD9/fvn7+1sfa9asUYkSJdSwYUMZYzRjxgwNHz5c7dq1U8WKFbVs2TJFR0dr5cqVziwbAAAAQBaXaa5RiouL0/Lly9WtWzdZLBadPn1a4eHhat68uXUdd3d3NWzYUNu2bbvndmJjYxUZGWnzAAAAAABHZJqg9NVXX+n69evq2rWrJCk8PFyS5OfnZ7Oen5+fdVlKJk6cKF9fX+ujSJEi6VYzAAAAgKwp0wSlRYsWqWXLlgoICLBpt1gsNs+NMcna7jZs2DBFRERYH+fPn0+XegEAAABkXa7OLkCSzp49q40bN+qLL76wtvn7+0u607NUsGBBa/ulS5eS9TLdzd3dXe7u7ulXLAAAAIAsL1P0KC1ZskQFChRQ69atrW1BQUHy9/e3zoQn3bmOacuWLapbt64zygQAAADwH+H0HqXExEQtWbJEXbp0kavr/5VjsVg0YMAAhYaGqlSpUipVqpRCQ0Pl6empTp06ObFiAAAAAFmd04PSxo0bde7cOXXr1i3ZssGDB+vWrVvq3bu3rl27ppCQEK1fv17e3t5OqBQAAADAf4XFGGOcXUR6ioyMlK+vryIiIuTj4+PscgAAAPCQ+Yd5xHAPmTVhOJINMsU1SgAAAACQmRCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7BCUAAAAAMAOQQkAAAAA7Lg6uwAAGcNicXYFDx9jnF0BAABwFnqUAAAAAMCOw0Hp1q1bio6Otj4/e/asZsyYofXr16dpYQAAAADgLA4HpbZt2+qDDz6QJF2/fl0hISF6++231bZtW82bNy/NCwQAAACAjOZwUNqzZ4/q168vSfrss8/k5+ens2fP6oMPPtDMmTPTvEAAAAAAyGgOB6Xo6Gh5e3tLktavX6927dopW7Zsql27ts6ePZvmBQIAAABARnM4KJUsWVJfffWVzp8/r++//17NmzeXJF26dEk+Pj5pXiAAAAAAZDSHg9LIkSM1aNAgBQYGKiQkRHXq1JF0p3epatWqaV4gAAAAAGQ0h4NS+/btde7cOe3atUvr1q2ztjdt2lTvvPOOwwVcuHBBL7zwgvLmzStPT09VqVJFu3fvti43xmj06NEKCAiQh4eHGjVqpIMHDzq8HwAAAABIrQe6j5K/v7+qVq2qbNn+7+W1atVS2bJlHdrOtWvXVK9ePbm5uem7777ToUOH9PbbbytXrlzWdaZMmaLp06dr9uzZ2rlzp/z9/dWsWTNFRUU9SOkAAAAAcF8WYxy79/zNmzc1adIkbdq0SZcuXVJiYqLN8lOnTqV6W0OHDtUvv/yin3/+OcXlxhgFBARowIABGjJkiCQpNjZWfn5+mjx5snr27HnffURGRsrX11cRERFcQ4X/NIvF2RU8fBz7dAQAZFWcQx2XWc+hjmQDV0c33r17d23ZskUvvviiChYsKMu/OHJWr16txx57TB06dNCWLVtUqFAh9e7dW6+88ook6fTp0woPD7dOGCFJ7u7uatiwobZt25ZiUIqNjVVsbKz1eWRk5APXBwAAAOC/yeGg9N1332nt2rWqV6/ev975qVOnNG/ePA0cOFBvvvmmfvvtN/Xr10/u7u7q3LmzwsPDJUl+fn42r0u6d1NKJk6cqDFjxvzr2gAAAAD8dzl8jVLu3LmVJ0+eNNl5YmKiqlWrptDQUFWtWlU9e/bUK6+8onnz5tmsZ99rZYy5Z0/WsGHDFBERYX2cP38+TWoFAAAA8N/hcFAaN26cRo4cqejo6H+984IFC6p8+fI2beXKldO5c+ck3Zk0QpK1ZynJpUuXkvUyJXF3d5ePj4/NAwAAAAAc4fDQu7ffflsnT56Un5+fAgMD5ebmZrN8z549qd5WvXr1dPToUZu2Y8eOqVixYpKkoKAg+fv7a8OGDdZ7NMXFxWnLli2aPHmyo6UDAAAAQKo4HJSefPLJNNv566+/rrp16yo0NFTPPPOMfvvtNy1cuFALFy6UdGfI3YABAxQaGqpSpUqpVKlSCg0Nlaenpzp16pRmdQAAAADA3RyeHjytrVmzRsOGDdPx48cVFBSkgQMHWme9k+5cjzRmzBgtWLBA165dU0hIiObMmaOKFSumavtMDw7cwdSmjsusU5sCADIW51DHZdZzqCPZ4IGD0u7du3X48GFZLBaVL1/eOjQusyEoAXfwIe+4zPohDwDIWJxDHZdZz6Hpeh+lS5cuqWPHjvrxxx+VK1cuGWMUERGhxo0b6+OPP1b+/PkfuHAAAAAAyAwcnvWub9++ioyM1MGDB/X333/r2rVrOnDggCIjI9WvX7/0qBEAAAAAMpTDQ+98fX21ceNG1axZ06b9t99+U/PmzXX9+vW0rO9fY+gdcAfDBhyXWYcNAAAyFudQx2XWc6gj2cDhHqXExMRkU4JLkpubmxITEx3dHAAAAABkOg4HpSZNmqh///76888/rW0XLlzQ66+/rqZNm6ZpcQAAAADgDA4HpdmzZysqKkqBgYEqUaKESpYsqaCgIEVFRWnWrFnpUSMAAAAAZCiHZ70rUqSI9uzZow0bNujIkSMyxqh8+fJ69NFH06M+AAAAAMhwTr/hbHpjMgfgDi5EdVzW/nQEAKQW51DHZdZzaJrfR2nmzJnq0aOHcuTIoZkzZ/7jukwRDgAAAOBhl6oepaCgIO3atUt58+ZVUFDQvTdmsejUqVNpWuC/RY8ScAd/DXNcZv1rGAAgY3EOdVxmPYemeY/S6dOnU/x/AAAAAMiKHJ71buzYsYqOjk7WfuvWLY0dOzZNigIAAAAAZ3J4MgcXFxddvHhRBQoUsGm/evWqChQooISEhDQt8N9i6B1wB8MGHJdZhw0AADIW51DHZdZzqCPZwOEeJWOMLCkcLWFhYcqTJ4+jmwMAAACATCfV91HKnTu3LBaLLBaLSpcubROWEhISdOPGDfXq1StdigQAAACAjJTqoDRjxgwZY9StWzeNGTNGvr6+1mXZs2dXYGCg6tSpky5FAgAAAEBGSnVQ6tKli6Q7U4XXq1dPrq6pfikAAAAAPFQcvkbp5s2b2rRpU7L277//Xt99912aFAUAAAAAzuRwUBo6dGiKM9sZYzR06NA0KQoAAAAAnMnhoHT8+HGVL18+WXvZsmV14sSJNCkKAAAAAJzJ4aDk6+urU6dOJWs/ceKEvLy80qQoAAAAAHAmh4NSmzZtNGDAAJ08edLaduLECb3xxhtq06ZNmhYHAAAAAM7gcFCaOnWqvLy8VLZsWQUFBSkoKEjlypVT3rx5NW3atPSoEQAAAAAylMNzfPv6+mrbtm3asGGDwsLC5OHhoeDgYDVo0CA96gMAAACADGcxxhhnF5GeIiMj5evrq4iICPn4+Di7HMBpLBZnV/DwydqfjgCA1OIc6rjMeg51JBs80F1jb968qS1btujcuXOKi4uzWdavX78H2SQAAAAAZBoOB6Xff/9drVq1UnR0tG7evKk8efLoypUr8vT0VIECBQhKAAAAAB56Dk/m8Prrr+uJJ57Q33//LQ8PD+3YsUNnz55V9erVmcwBAAAAQJbgcFDau3ev3njjDbm4uMjFxUWxsbEqUqSIpkyZojfffDM9agQAAACADOVwUHJzc5Pl/1/R5ufnp3Pnzkm6Mxte0v8DAAAAwMPM4WuUqlatql27dql06dJq3LixRo4cqStXrujDDz9UpUqV0qNGAAAAAMhQDvcohYaGqmDBgpKkcePGKW/evHr11Vd16dIlLVy4MM0LBAAAAICMxn2UgP8I7gHhuKz96QgASC3OoY7LrOdQR7KBwz1Kt27dUnR0tPX52bNnNWPGDK1fv97xSgEAAAAgE3I4KLVt21YffPCBJOn69euqVauW3n77bbVt21bz5s1L8wIBAAAAIKM5HJT27Nmj+vXrS5I+++wz+fv76+zZs/rggw80c+bMNC8QAAAAADKaw0EpOjpa3t7ekqT169erXbt2ypYtm2rXrq2zZ8+meYEAAAAAkNEcDkolS5bUV199pfPnz+v7779X8+bNJUmXLl1isgQAAAAAWYLDQWnkyJEaNGiQAgMDFRISojp16ki607tUtWrVNC8QAAAAADLaA00PHh4erosXL6py5crKlu1O1vrtt9/k4+OjsmXLpnmR/wbTgwN3MLWp4zLr1KYAgIzFOdRxmfUc6kg2cH2QHfj7+8vf39+mrVatWg+yKQAAAADIdBwOSjdv3tSkSZO0adMmXbp0SYmJiTbLT506lWbFAQAAAIAzOByUunfvri1btujFF19UwYIFZaEvEgAAAEAW43BQ+u6777R27VrVq1cvPeoBAAAAAKdzeNa73LlzK0+ePGmy89GjR8tisdg87r72yRij0aNHKyAgQB4eHmrUqJEOHjyYJvsGAAAAgHtxOCiNGzdOI0eOVHR0dJoUUKFCBV28eNH62L9/v3XZlClTNH36dM2ePVs7d+6Uv7+/mjVrpqioqDTZNwAAAACkxOGhd2+//bZOnjwpPz8/BQYGys3NzWb5nj17HCvA1TXZDHrSnd6kGTNmaPjw4WrXrp0kadmyZfLz89PKlSvVs2dPR0sHAAAAgFRxOCg9+eSTaVrA8ePHFRAQIHd3d4WEhCg0NFTFixfX6dOnFR4erubNm1vXdXd3V8OGDbVt27Z7BqXY2FjFxsZan0dGRqZpvQAAAACyPoeD0qhRo9Js5yEhIfrggw9UunRp/fXXXxo/frzq1q2rgwcPKjw8XJLk5+dn8xo/Pz+dPXv2ntucOHGixowZk2Y1AgAAAPjvcfgapbTUsmVLPf3006pUqZIeffRRrV27VtKdIXZJ7KcfN8b845Tkw4YNU0REhPVx/vz59CkeAAAAQJblcFBKSEjQtGnTVKtWLfn7+ytPnjw2j3/Dy8tLlSpV0vHjx63XLSX1LCW5dOlSsl6mu7m7u8vHx8fmAQAAAACOcDgojRkzRtOnT9czzzyjiIgIDRw4UO3atVO2bNk0evTof1VMbGysDh8+rIIFCyooKEj+/v7asGGDdXlcXJy2bNmiunXr/qv9AAAAAMA/cTgorVixQu+9954GDRokV1dXPffcc3r//fc1cuRI7dixw6FtDRo0SFu2bNHp06f166+/qn379oqMjFSXLl1ksVg0YMAAhYaG6ssvv9SBAwfUtWtXeXp6qlOnTo6WDQAAAACp5vBkDuHh4apUqZIkKWfOnIqIiJAkPf744xoxYoRD2/rjjz/03HPP6cqVK8qfP79q166tHTt2qFixYpKkwYMH69atW+rdu7euXbumkJAQrV+/Xt7e3o6WDQAAAACp5nBQKly4sC5evKiiRYuqZMmSWr9+vapVq6adO3fK3d3doW19/PHH/7jcYrFo9OjR/3pIHwAAAAA4wuGhd0899ZQ2bdokSerfv79GjBihUqVKqXPnzurWrVuaFwgAAAAAGc1ijDH/ZgO//vqrfvnlF5UsWVJt2rRJq7rSTGRkpHx9fRUREcEMePhP+4dZ9XEP/+7TEQCQVXAOdVxmPYc6kg0cGnp3+/Zt9ejRQyNGjFDx4sUl3blpbEhIyINXCwAAAACZjEND79zc3PTll1+mVy0AAAAAkCk80DVKX331VTqUAgAAAACZg8Oz3pUsWVLjxo3Ttm3bVL16dXl5edks79evX5oVBwAAAADOkOrJHIoXL66dO3eqRo0a996YxaJTp06lWXFpgckcgDu4ENVxmfVCVABAxuIc6rjMeg5Nl8kczpw5o4SEBJ0+ffpfFwgAAAAAmZnD1ygBAAAAQFbn0DVKhw4dUnh4+D+uExwc/K8KAgAAAABncygoNW3aVCld0mSxWGSMkcViUUJCQpoVBwAAAADO4FBQ+vXXX5U/f/70qgUAAAAAMgWHglLRokVVoECB9KoFAAAAADIFJnMAAAAAADupDkoNGzZU9uzZ07MWAAAAAMgUUj307ocffkjPOgAAAAAg02DoHQAAAADYISgBAAAAgB2CEgAAAADYcTgojR07VtHR0cnab926pbFjx6ZJUQAAAADgTBZjjHHkBS4uLrp48WKy+yldvXpVBQoUUEJCQpoW+G9FRkbK19dXERER8vHxcXY5gNNYLM6u4OHj2KcjACCr4hzquMx6DnUkGzjco2SMkSWFoyUsLEx58uRxdHMAAAAAkOmkenrw3Llzy2KxyGKxqHTp0jZhKSEhQTdu3FCvXr3SpUgAAAAAyEipDkozZsyQMUbdunXTmDFj5Ovra12WPXt2BQYGqk6dOulSJAAAAABkpFQHpS5dukiSgoKCVLduXbm5uaVbUQAAAADgTKkOSkkaNmyoxMREHTt2TJcuXVJiYqLN8gYNGqRZcQAAAADgDA4HpR07dqhTp046e/as7CfMs1gsmW7WOwAAAABwlMNBqVevXqpRo4bWrl2rggULpjgDHgAAAAA8zBwOSsePH9dnn32mkiVLpkc9AAAAAOB0Dt9HKSQkRCdOnEiPWgAAAAAgU3C4R6lv37564403FB4erkqVKiWb/S44ODjNigMAAAAAZ7AY+xkZ7iNbtuSdUBaLRcaYTDmZQ2RkpHx9fRURESEfHx9nlwM4DZcTOs6xT0cAQFbFOdRxmfUc6kg2cLhH6fTp0w9cGAAAAAA8DBwOSsWKFUuPOgAAAAAg03B4MgdJ+vDDD1WvXj0FBATo7NmzkqQZM2bo66+/TtPiAAAAAMAZHA5K8+bN08CBA9WqVStdv37dek1Srly5NGPGjLSuDwAAAAAynMNBadasWXrvvfc0fPhwubi4WNtr1Kih/fv3p2lxAAAAAOAMDgel06dPq2rVqsna3d3ddfPmzTQpCgAAAACcyeGgFBQUpL179yZr/+6771S+fPm0qAkAAAAAnMrhWe/+97//qU+fPoqJiZExRr/99ps++ugjTZw4Ue+//3561AgAAAAAGcrhoPTSSy8pPj5egwcPVnR0tDp16qRChQrp3XffVceOHdOjRgAAAADIUBZjHvy+uVeuXFFiYqIKFCiQljWlKUfuvgtkZdxV3HGZ9a7iAICMxTnUcZn1HOpINnC4R+lu+fLl+zcvBwAAAIBMKVVBqWrVqrKkMkrv2bPnXxUEAAAAAM6WqqD05JNPpnMZAAAAAJB5/KtrlNLSxIkT9eabb6p///6aMWOGJMkYozFjxmjhwoW6du2aQkJCNGfOHFWoUCHV2+UaJeAOxlc7LnN8OgIAnI1zqOMy6znUkWzg8H2U0sPOnTu1cOFCBQcH27RPmTJF06dP1+zZs7Vz5075+/urWbNmioqKclKlAAAAAP4LHA5K2bJlk4uLyz0fjrpx44aef/55vffee8qdO7e13RijGTNmaPjw4WrXrp0qVqyoZcuWKTo6WitXrnR4PwAAAACQWg7Pevfll1/aPL99+7Z+//13LVu2TGPGjHG4gD59+qh169Z69NFHNX78eGv76dOnFR4erubNm1vb3N3d1bBhQ23btk09e/ZMcXuxsbGKjY21Po+MjHS4JgAAAAD/bQ4HpbZt2yZra9++vSpUqKBVq1bp5ZdfTvW2Pv74Y+3Zs0c7d+5Mtiw8PFyS5OfnZ9Pu5+ens2fP3nObEydOfKDABgAAAABJ0uwapZCQEG3cuDHV658/f179+/fX8uXLlSNHjnuuZz8tuTHmH6cqHzZsmCIiIqyP8+fPp7omAAAAAJD+5Q1nk9y6dUuzZs1S4cKFU/2a3bt369KlS6pevbq1LSEhQT/99JNmz56to0ePSrrTs1SwYEHrOpcuXUrWy3Q3d3d3ubu7P8C7AAAAAIA7HA5KuXPntunRMcYoKipKnp6eWr58eaq307RpU+3fv9+m7aWXXlLZsmU1ZMgQFS9eXP7+/tqwYYOqVq0qSYqLi9OWLVs0efJkR8sGAAAAgFRzOCi98847NkEpW7Zsyp8/v0JCQmxmrbsfb29vVaxY0abNy8tLefPmtbYPGDBAoaGhKlWqlEqVKqXQ0FB5enqqU6dOjpYNAAAAAKnmcFDq2rVrOpSRssGDB+vWrVvq3bu39Yaz69evl7e3d4bVAAAAAOC/x2LM/e+bu2/fvlRv0P6msc7myN13gayMu4o7LrPeVRwAkLE4hzous55DHckGqepRqlKliiwWi5Iy1T/NOpeQkOBAqQAAAACQ+aRqevDTp0/r1KlTOn36tL744gsFBQVp7ty5+v333/X7779r7ty5KlGihD7//PP0rhcAAAAA0l2qepSKFStm/f8OHTpo5syZatWqlbUtODhYRYoU0YgRI/Tkk0+meZEAAAAAkJEcvuHs/v37FRQUlKw9KChIhw4dSpOiAAAAAMCZHA5K5cqV0/jx4xUTE2Nti42N1fjx41WuXLk0LQ4AAAAAnMHh6cHnz5+vJ554QkWKFFHlypUlSWFhYbJYLFqzZk2aFwgAAAAAGS1V04Pbi46O1vLly3XkyBEZY1S+fHl16tRJXl5e6VHjv8L04MAdTG3quMw6tSkAIGNxDnVcZj2Hpvn04PY8PT3Vo0ePByoOAAAAADI7h4PSBx988I/LO3fu/MDFAAAAAEBm4PDQu9y5c9s8v337tqKjo5U9e3Z5enrq77//TtMC/y2G3gF3MGzAcZl12AAAIGNxDnVcZj2HOpINHJ717tq1azaPGzdu6OjRo3rkkUf00UcfPXDRAAAAAJBZOByUUlKqVClNmjRJ/fv3T4vNAQAAAIBTpUlQkiQXFxf9+eefabU5AAAAAHAahydzWL16tc1zY4wuXryo2bNnq169emlWGAAAAAA4i8NB6cknn7R5brFYlD9/fjVp0kRvv/12WtUFAAAAAE7jcFBKTExMjzoAAAAAINNIs2uUAAAAACCrcLhHSZL++OMPrV69WufOnVNcXJzNsunTp6dJYQAAAADgLA4HpU2bNqlNmzYKCgrS0aNHVbFiRZ05c0bGGFWrVi09agQAAACADOXw0Lthw4bpjTfe0IEDB5QjRw59/vnnOn/+vBo2bKgOHTqkR40AAAAAkKEcDkqHDx9Wly5dJEmurq66deuWcubMqbFjx2ry5MlpXiAAAAAAZDSHg5KXl5diY2MlSQEBATp58qR12ZUrV9KuMgAAAABwEoevUapdu7Z++eUXlS9fXq1bt9Ybb7yh/fv364svvlDt2rXTo0YAAAAAyFAOB6Xp06frxo0bkqTRo0frxo0bWrVqlUqWLKl33nknzQsEAAAAgIzmUFBKSEjQ+fPnFRwcLEny9PTU3Llz06UwAAAAAHAWh65RcnFx0WOPPabr16+nUzkAAAAA4HwOT+ZQqVIlnTp1Kj1qAQAAAIBMweGgNGHCBA0aNEhr1qzRxYsXFRkZafMAAAAAgIedxRhjHHlBtmz/l60sFov1/40xslgsSkhISLvq0kBkZKR8fX0VEREhHx8fZ5cDOM1dv65IJcc+HQEAWRXnUMdl1nOoI9nA4VnvfvjhhwcuDAAAAAAeBqkOSp07d9acOXPUsGFDSVJYWJjKly8vNze3dCsOAAAAAJwh1dcorVixQrdu3bI+r1+/vs6fP58uRQEAAACAM6U6KNlfyuTgpU0AAAAA8NBweNY7AAAAAMjqHJrM4dChQwoPD5d0p0fpyJEjunHjhs06wcHBaVcdAAAAADhBqqcHz5YtmywWS4pD7pLamR4cyLyY2tRxjDAGAEicQx9EZj2Hpsv04KdPn/7XhQEAAADAwyDVQalYsWLpWQcAAAAAZBpM5gAAAAAAdghKAAAAAGCHoAQAAAAAdlIVlFavXq3bt2+ndy0AAAAAkCmkKig99dRTun79uiTJxcVFly5dSs+aAAAAAMCpUhWU8ufPrx07dkiS9X5JAAAAAJBVpWp68F69eqlt27ayWCyyWCzy9/e/57qZ7YazAAAAAOCoVAWl0aNHq2PHjjpx4oTatGmjJUuWKFeuXP965/PmzdO8efN05swZSVKFChU0cuRItWzZUtKd3qsxY8Zo4cKFunbtmkJCQjRnzhxVqFDhX+8bAAAAAO4l1TecLVu2rMqWLatRo0apQ4cO8vT0/Nc7L1y4sCZNmqSSJUtKkpYtW6a2bdvq999/V4UKFTRlyhRNnz5dS5cuVenSpTV+/Hg1a9ZMR48elbe397/ePwAAAACkxGKMMQ/ywsuXL+vo0aOyWCwqXbq08ufPnyYF5cmTR1OnTlW3bt0UEBCgAQMGaMiQIZKk2NhY+fn5afLkyerZs2eqthcZGSlfX19FRETIx8cnTWoEHkZcWui4B/t0BABkNZxDHZdZz6GOZAOH76MUHR1tDTENGjRQ/fr1FRAQoJdfflnR0dEPXHRCQoI+/vhj3bx5U3Xq1NHp06cVHh6u5s2bW9dxd3dXw4YNtW3btntuJzY2VpGRkTYPAAAAAHCEw0Hp9ddf15YtW7R69Wpdv35d169f19dff60tW7bojTfecLiA/fv3K2fOnHJ3d1evXr305Zdfqnz58goPD5ck+fn52azv5+dnXZaSiRMnytfX1/ooUqSIwzUBAAAA+G9zeOhdvnz59Nlnn6lRo0Y27T/88IOeeeYZXb582aEC4uLidO7cOV2/fl2ff/653n//fW3ZskXXr19XvXr19Oeff6pgwYLW9V955RWdP39e69atS3F7sbGxio2NtT6PjIxUkSJFGHqH/zyGDTgusw4bAABkLM6hjsus51BHht6lejKHJNHR0cl6eSSpQIECDzT0Lnv27NbJHGrUqKGdO3fq3XfftV6XFB4ebhOULl26lOL+k7i7u8vd3d3hOgAAAAAgicND7+rUqaNRo0YpJibG2nbr1i2NGTNGderU+dcFGWMUGxuroKAg+fv7a8OGDdZlcXFx2rJli+rWrfuv9wMAAAAA9+Jwj9K7776rFi1aqHDhwqpcubIsFov27t2rHDly6Pvvv3doW2+++aZatmypIkWKKCoqSh9//LF+/PFHrVu3ThaLRQMGDFBoaKhKlSqlUqVKKTQ0VJ6enurUqZOjZQMAAABAqjkclCpWrKjjx49r+fLlOnLkiIwx6tixo55//nl5eHg4tK2//vpLL774oi5evChfX18FBwdr3bp1atasmSRp8ODBunXrlnr37m294ez69eu5hxIAAACAdPXA91F6WHAfJeAOLkR1XNb+dAQApBbnUMdl1nNout5HCQAAAACyOoISAAAAANghKAEAAACAHYISAAAAANhxOCgVL15cV69eTdZ+/fp1FS9ePE2KAgAAAABncjgonTlzRgkJCcnaY2NjdeHChTQpCgAAAACcKdX3UVq9erX1/7///nv5+vpanyckJGjTpk0KDAxM0+IAAAAAwBlSHZSefPJJSZLFYlGXLl1slrm5uSkwMFBvv/12mhYHAAAAAM6Q6qCUmJgoSQoKCtLOnTuVL1++dCsKAAAAAJwp1UEpyenTp9OjDgAAAADINBwOSpK0adMmbdq0SZcuXbL2NCVZvHhxmhQGAAAAAM7icFAaM2aMxo4dqxo1aqhgwYKyWCzpURcAAAAAOI3DQWn+/PlaunSpXnzxxfSoBwAAAACczuH7KMXFxalu3brpUQsAAAAAZAoOB6Xu3btr5cqV6VELAAAAAGQKDg+9i4mJ0cKFC7Vx40YFBwfLzc3NZvn06dPTrDgAAAAAcAaHg9K+fftUpUoVSdKBAwdsljGxAwAAAICswOGg9MMPP6RHHQAAAACQaTh8jRIAAAAAZHUO9yg1btz4H4fYbd68+V8VBAAAAADO5nBQSro+Kcnt27e1d+9eHThwQF26dEmrugAAAADAaRwOSu+8806K7aNHj9aNGzf+dUEAAAAA4Gxpdo3SCy+8oMWLF6fV5gAAAADAadIsKG3fvl05cuRIq80BAAAAgNM4PPSuXbt2Ns+NMbp48aJ27dqlESNGpFlhAAAAAOAsDgclX19fm+fZsmVTmTJlNHbsWDVv3jzNCgMAAAAAZ3E4KC1ZsiQ96gAAAACATMPhoJRk9+7dOnz4sCwWi8qXL6+qVaumZV0AAAAA4DQOB6VLly6pY8eO+vHHH5UrVy4ZYxQREaHGjRvr448/Vv78+dOjTgAAAADIMA7Pete3b19FRkbq4MGD+vvvv3Xt2jUdOHBAkZGR6tevX3rUCAAAAAAZymKMMY68wNfXVxs3blTNmjVt2n/77Tc1b95c169fT8v6/rXIyEj5+voqIiJCPj4+zi4HcBqLxdkVPHwc+3QEAGRVnEMdl1nPoY5kA4d7lBITE+Xm5pas3c3NTYmJiY5uDgAAAAAyHYeDUpMmTdS/f3/9+eef1rYLFy7o9ddfV9OmTdO0OAAAAABwBoeD0uzZsxUVFaXAwECVKFFCJUuWVFBQkKKiojRr1qz0qBEAAAAAMpTDs94VKVJEe/bs0YYNG3TkyBEZY1S+fHk9+uij6VEfAAAAAGQ4hydzeNgwmQNwBxeiOi5rfzoCAFKLc6jjMus5NF0mc9i8ebPKly+vyMjIZMsiIiJUoUIF/fzzz45XCwAAAACZTKqD0owZM/TKK6+kmLx8fX3Vs2dPTZ8+PU2LAwAAAABnSHVQCgsLU4sWLe65vHnz5tq9e3eaFAUAAAAAzpTqoPTXX3+leP+kJK6urrp8+XKaFAUAAAAAzpTqoFSoUCHt37//nsv37dunggULpklRAAAAAOBMqQ5KrVq10siRIxUTE5Ns2a1btzRq1Cg9/vjjaVocAAAAADhDqqcH/+uvv1StWjW5uLjotddeU5kyZWSxWHT48GHNmTNHCQkJ2rNnj/z8/NK7ZocwPThwB1ObOi6zTm0KAMhYnEMdl1nPoY5kg1TfcNbPz0/btm3Tq6++qmHDhikpX1ksFj322GOaO3dupgtJAAAAAPAgUj30TpKKFSumb7/9VleuXNGvv/6qHTt26MqVK/r2228VGBjo8M4nTpyomjVrytvbWwUKFNCTTz6po0eP2qxjjNHo0aMVEBAgDw8PNWrUSAcPHnR4XwAAAACQWg4FpSS5c+dWzZo1VatWLeXOnfuBd75lyxb16dNHO3bs0IYNGxQfH6/mzZvr5s2b1nWmTJmi6dOna/bs2dq5c6f8/f3VrFkzRUVFPfB+AQAAAOCfpPoapYxw+fJlFShQQFu2bFGDBg1kjFFAQIAGDBigIUOGSJJiY2Pl5+enyZMnq2fPnvfdJtcoAXcwvtpxmefTEQDgTJxDHZdZz6GOZIMH6lFKLxEREZKkPHnySJJOnz6t8PBwNW/e3LqOu7u7GjZsqG3btqW4jdjYWEVGRto8AAAAAMARmSYoGWM0cOBAPfLII6pYsaIkKTw8XJKSTRLh5+dnXWZv4sSJ8vX1tT6KFCmSvoUDAAAAyHIyTVB67bXXtG/fPn300UfJllns+juNMcnakgwbNkwRERHWx/nz59OlXgAAAABZV6qnB09Pffv21erVq/XTTz+pcOHC1nZ/f39Jd3qWChYsaG2/dOnSPacid3d3l7u7e/oWDAAAACBLc2qPkjFGr732mr744gtt3rxZQUFBNsuDgoLk7++vDRs2WNvi4uK0ZcsW1a1bN6PLBQAAAPAf4dQepT59+mjlypX6+uuv5e3tbb3uyNfXVx4eHrJYLBowYIBCQ0NVqlQplSpVSqGhofL09FSnTp2cWToAAACALMypQWnevHmSpEaNGtm0L1myRF27dpUkDR48WLdu3VLv3r117do1hYSEaP369fL29s7gagEAAAD8V2Sq+yilB+6jBNzBPSAcl7U/HQEAqcU51HGZ9Rz60N5HCQAAAAAyA4ISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHYISAAAAANghKAEAAACAHacGpZ9++klPPPGEAgICZLFY9NVXX9ksN8Zo9OjRCggIkIeHhxo1aqSDBw86p1gAAAAA/xlODUo3b95U5cqVNXv27BSXT5kyRdOnT9fs2bO1c+dO+fv7q1mzZoqKisrgSgEAAAD8l7g6c+ctW7ZUy5YtU1xmjNGMGTM0fPhwtWvXTpK0bNky+fn5aeXKlerZs2dGlgoAAADgPyTTXqN0+vRphYeHq3nz5tY2d3d3NWzYUNu2bbvn62JjYxUZGWnzAAAA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Bwfr2LFj1i8V2bJl4zhDmgoLC1P16tWVmJioa9eu6auvvtLt27c51pCmoqOjNXToUCUmJlo/z6Q7PZmS9Oeff+r777/XxYsXFRsb66wy/7MISlnU+vXr9cgjj6hatWp67rnnNGTIEP3www+Ki4tTly5dtGLFCr3//vuaOXMms5PhX9m0aZP69++vDz/8UC+88IJWrVql7NmzKzQ0VN99950SExMJS0gTSUNTBg4cqI0bN2r27NmaOnWq9csFxxnSStI1SSNGjNC1a9esn2lr165VfHw8xxrSjLu7u3r06KEKFSqofv36kqSZM2dq1qxZ6tOnj65fv66JEyeqcuXKevbZZzVq1CgdP37cyVX/d1gMv+lZStI/548//qg+ffro5MmTmjBhgpYvX66bN28qNjZWTz31lDp16qRffvlFEydOVO/evdW5c2eVKFHCydXjYXP+/HmdPHlSPj4+qlatmuLi4pQ9e3Zdv35dbdu2VVxcnIYPH65WrVpZ/wrLMDw8qKlTp+rSpUuaOnWqJCkuLk4rVqxQz5499b///c86DI/jDP9GTEyMevbsqaJFi1qvSbpx44batm2rqKgovfnmm3r88ccZWox/JSwsTL/88ot69+6t+Ph4bd68WQMHDtTff/+tmJgYrVu3TrVq1bKu//HHH+v333/XihUrtG3bNhUtWtSJ1f+HGGQpkZGRxhhjYmJizE8//WSKFi1qnn/+eRMXF2f++OMPM3bsWPPss88aLy8v8/jjjxuLxWIsFouZN2+ekyvHwyYsLMxYLBazaNEik5iYaG2/ffu2McaY69evmwYNGpg6deqYb775xiQkJDirVDzkzpw5Y1555RUTHR1tjPm/Y8wYY+Li4szixYuNm5ubefPNN63tdx+TQGodO3bMbNu2zfz999/Wtri4OGOMMTdu3DBNmjQxNWvWNF9++aX1OORYg6P27t1rLBaLGT58uLUtPj7efPfdd+aRRx4xZcqUsbbHxsbavPbWrVsZVieMIShlIT///LPx8vIy+/fvN8bc+XD/8ccfTb58+UybNm1s1j1x4oT55ptvTJcuXUybNm1svngAqTVw4EDj6elplixZYnMM3R2WGjZsaOrVq2c++eQTwhIeyKpVq0ypUqVMu3btrH8MuldYGjFihLPKRBYwYMAAY7FYzPfff2+M+b8QlHS83R2Wvv76a86dcNje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XzsdlCxZUjdv3tT69evVvHnzFGesW7Vqla5cuaKWLVuqcePGTqgSD6vIyEj5+PjIYrFYpyWdNGmSOnfurNjYWFWtWjXZ+t7e3ipWrJhNOzMpAsgs9u3bp7Zt2ypXrlw6efKkjDFatGiRBg4cqKZNm6pHjx6aPHmy1q5dq7Vr16pq1arq1q2bVq1aZZ3tjs803M++fftUp04d9e/fX3379tWvv/6qZ599VhUqVFCjRo1ksVjk6emphg0bas+ePSpevLgkMfriP4yhd+ng1KlTqlatmh599FFNnz5dRYsWlfR/PQCRkZHq3Lmz2rRpo27dukli4gakzooVK/Tee++pdu3aGjFihLJnz25zrdHdvZfGGEVEROiFF15QZGSkfvjhB44xAJlO0pfXvn37asiQITp27Jhmz56t7777TuvWrdP8+fP1zTffyMvLSx9//LFq1apl/eLKF1ik1uHDhxUcHKz+/ftr2rRp1vayZcvKy8tLP/30k7y8vKztVapUUe3atTV//nxnlItMgk+XdFC8eHHNnz9fa9as0Ztvvqm9e/dKuvPXrj///FMdO3bUlStX1LlzZ+tr+AKL+4mOjtaXX36pnDlzav/+/WrQoIGGDh2q3bt3W9dJCklXr17Vxx9/rI4dO+rPP//Upk2b5OLiooSEBGeVDwDJnD9/Xk2bNlXr1q01adIk5c6dWyEhIWrfvr3i4uLk4uKiOnXq6PLly1q1apVq1aplM2yYkITUSExM1OnTp5WQkKBChQopMjJSkhQaGqpjx45Jknr06KHx48db72FZtWpV/fXXX4qKinJa3XA+ht6lkw4dOujGjRvq3bu3tmzZoooVKyoxMVERERFKTEzUL7/8IldXV3qSkGqenp5q3LixFi5cqLCwMH322Wdat26dWrRooeeff14NGzbUU089JenOhCJLly5V8eLFtWbNGrm6ulqH6QFAZpGQkKCgoCDFxsZq69ateuSRRyRJ+fPnl8ViUbZs2fTyyy/r/fff19KlS1WzZk2G2MEh+/fv17vvvqv3339f7777rvr37y93d3ddvnxZ7777rj788EMVKlRIx48f1/r16zVz5kxNmzZNRYoU0dSpU+Xt7e3stwAnYuhdOtu7d68WL16sY8eOqXDhwqpatap69eolFxcXvrjigTz22GN64okn1LNnT7m5uWnNmjVq06aNvLy8VK9e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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "# Group the data by transaction type and calculate the count of fraudulent transactions for each type\n", + "fraud_by_type = fraud.groupby('type')['isFraud'].sum()\n", + "\n", + "# Plot the distribution of fraud by transaction type\n", + "plt.figure(figsize=(10, 6))\n", + "fraud_by_type.plot(kind='bar', color='blue')\n", + "plt.title('Distribution of Fraud by Transaction Type')\n", + "plt.xlabel('Transaction Type')\n", + "plt.ylabel('Count of Fraudulent Transactions')\n", + "plt.xticks(rotation=45, ha='right')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " step type amount nameOrig oldbalanceOrg newbalanceOrig \\\n", + "0 278 CASH_IN 330218.42 C632336343 20866.0 351084.42 \n", + "\n", + " nameDest oldbalanceDest newbalanceDest isFraud isFlaggedFraud \n", + "0 C834976624 452419.57 122201.15 0 0 \n" + ] + } + ], + "source": [ + "# IsFraud is the most importatnt\n", + "print(fraud.head(1))" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "RangeIndex: 100000 entries, 0 to 99999\n", + "Data columns (total 11 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 step 100000 non-null int64 \n", + " 1 type 100000 non-null object \n", + " 2 amount 100000 non-null float64\n", + " 3 nameOrig 100000 non-null object \n", + " 4 oldbalanceOrg 100000 non-null float64\n", + " 5 newbalanceOrig 100000 non-null float64\n", + " 6 nameDest 100000 non-null object \n", + " 7 oldbalanceDest 100000 non-null float64\n", + " 8 newbalanceDest 100000 non-null float64\n", + " 9 isFraud 100000 non-null int64 \n", + " 10 isFlaggedFraud 100000 non-null int64 \n", + "dtypes: float64(5), int64(3), object(3)\n", + "memory usage: 8.4+ MB\n" + ] + } + ], + "source": [ + "fraud.info()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Clean the dataset. Pre-process it to make it suitable for ML training. Feel free to explore, drop, encode, transform, etc. Whatever you feel will improve the model score." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.impute import SimpleImputer\n", + "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", + "from sklearn.compose import ColumnTransformer\n", + "from sklearn.pipeline import Pipeline\n", + "\n", + "\n", + "# Drop unnecessary columns\n", + "fraud.drop(['nameOrig', 'nameDest', 'isFlaggedFraud'], axis=1, inplace=True)\n", + "\n", + "# Separate numerical and categorical columns\n", + "numerical_cols = ['step', 'amount', 'oldbalanceOrg', 'newbalanceOrig', 'oldbalanceDest', 'newbalanceDest']\n", + "categorical_cols = ['type']\n", + "\n", + "# Create pipelines for numerical and categorical preprocessing steps\n", + "numerical_pipeline = Pipeline([\n", + " ('imputer', SimpleImputer(strategy='mean')),\n", + " ('scaler', StandardScaler())\n", + "])\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "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", + "
steptypeamountoldbalanceOrgnewbalanceOrigoldbalanceDestnewbalanceDestisFraud
0278CASH_IN330218.4220866.00351084.42452419.57122201.150
115PAYMENT11647.0830370.0018722.920.000.000
210CASH_IN152264.21106589.00258853.21201303.0149038.800
3403TRANSFER1551760.630.000.003198359.454750120.080
4206CASH_IN78172.302921331.582999503.88415821.90337649.600
\n", + "
" + ], + "text/plain": [ + " step type amount oldbalanceOrg newbalanceOrig oldbalanceDest \\\n", + "0 278 CASH_IN 330218.42 20866.00 351084.42 452419.57 \n", + "1 15 PAYMENT 11647.08 30370.00 18722.92 0.00 \n", + "2 10 CASH_IN 152264.21 106589.00 258853.21 201303.01 \n", + "3 403 TRANSFER 1551760.63 0.00 0.00 3198359.45 \n", + "4 206 CASH_IN 78172.30 2921331.58 2999503.88 415821.90 \n", + "\n", + " newbalanceDest isFraud \n", + "0 122201.15 0 \n", + "1 0.00 0 \n", + "2 49038.80 0 \n", + "3 4750120.08 0 \n", + "4 337649.60 0 " + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fraud.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run a logisitc regression classifier and evaluate its accuracy." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy: 0.999\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "from sklearn.impute import SimpleImputer\n", + "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", + "from sklearn.compose import ColumnTransformer\n", + "from sklearn.pipeline import Pipeline\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.linear_model import LogisticRegression\n", + "from sklearn.metrics import accuracy_score\n", + "\n", + "# Ensure that 'type' column is in categorical_cols list\n", + "categorical_cols = ['type']\n", + "\n", + "# Ensure that all numerical columns are present in the DataFrame\n", + "numerical_cols = ['step', 'amount', 'oldbalanceOrg', 'newbalanceOrig', 'oldbalanceDest', 'newbalanceDest']\n", + "for col in numerical_cols:\n", + " if col not in fraud.columns:\n", + " raise ValueError(f\"Column '{col}' is not present in the DataFrame.\")\n", + "\n", + "# Create pipelines for numerical and categorical preprocessing steps\n", + "numerical_pipeline = Pipeline([\n", + " ('imputer', SimpleImputer(strategy='mean')),\n", + " ('scaler', StandardScaler())\n", + "])\n", + "\n", + "categorical_pipeline = Pipeline([\n", + " ('encoder', OneHotEncoder())\n", + "])\n", + "\n", + "# Create a column transformer to apply the appropriate preprocessing steps to each column\n", + "preprocessor = ColumnTransformer([\n", + " ('num', numerical_pipeline, numerical_cols),\n", + " ('cat', categorical_pipeline, categorical_cols)\n", + "])\n", + "\n", + "# Fit and transform the data using the preprocessor\n", + "X_processed = preprocessor.fit_transform(fraud.drop('isFraud', axis=1))\n", + "y = fraud['isFraud']\n", + "\n", + "# Split the data into training and testing sets\n", + "X_train, X_test, y_train, y_test = train_test_split(X_processed, y, test_size=0.2, random_state=42)\n", + "\n", + "# Initialize logistic regression classifier\n", + "logistic_reg = LogisticRegression()\n", + "\n", + "# Train the classifier on the training data\n", + "logistic_reg.fit(X_train, y_train)\n", + "\n", + "# Predict the labels for the test set\n", + "y_pred = logistic_reg.predict(X_test)\n", + "\n", + "# Evaluate the accuracy of the model\n", + "accuracy = accuracy_score(y_test, y_pred)\n", + "\n", + "# Print the accuracy score\n", + "print(\"Accuracy:\", accuracy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now pick a model of your choice and evaluate its accuracy." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy (Random Forest): 0.99965\n" + ] + } + ], + "source": [ + "from sklearn.ensemble import RandomForestClassifier\n", + "\n", + "# Initialize Random Forest Classifier\n", + "random_forest = RandomForestClassifier(random_state=42)\n", + "\n", + "# Train the classifier on the training data\n", + "random_forest.fit(X_train, y_train)\n", + "\n", + "# Predict the labels for the test set\n", + "y_pred_rf = random_forest.predict(X_test)\n", + "\n", + "# Evaluate the accuracy of the model\n", + "accuracy_rf = accuracy_score(y_test, y_pred_rf)\n", + "\n", + "# Print the accuracy score\n", + "print(\"Accuracy (Random Forest):\", accuracy_rf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Which model worked better and how do you know?" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "#both model has pretty impressive accuracy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note: before doing the first commit, make sure you don't include the large csv file, either by adding it to .gitignore, or by deleting it." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "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.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}