diff --git a/your-code/lab_imbalance.ipynb b/your-code/lab_imbalance.ipynb index dbb15e1..a667451 100644 --- a/your-code/lab_imbalance.ipynb +++ b/your-code/lab_imbalance.ipynb @@ -1,147 +1,814 @@ -{ - "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": 54, + "metadata": {}, + "outputs": [], + "source": [ + "# Your code here\n", + "\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "import numpy as np\n", + "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", + "from sklearn.compose import ColumnTransformer\n", + "from sklearn.pipeline import Pipeline\n", + "from sklearn.impute import SimpleImputer\n", + "from sklearn.linear_model import LogisticRegression\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import accuracy_score, confusion_matrix, classification_report\n", + "from sklearn.ensemble import RandomForestClassifier\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "# Load the dataset\n", + "data = pd.read_csv('/Users/anna/iron_hack/lab-imbalance/data_imbalance.csv')\n", + "\n", + "# Sample 100,000 entries\n", + "sample_data = data.sample(n=100000, random_state=1)\n", + "\n", + "# Display basic statistics\n", + "# print(sample_data.describe())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following features are likely to be significant in determining the outcome of fraud detection:\n", + "1. Transaction Amount\n", + "Larger transaction amounts may correlate with higher fraud risk.\n", + "2. Old and New Balances\n", + "The differences between oldbalanceOrg and newbalanceOrig can indicate unusual activity, especially if a large amount is withdrawn or transferred.\n", + "3. Account Activity\n", + "The frequency of transactions and the patterns of account usage (e.g., sudden spikes in transaction amounts or frequency) can be strong indicators of potential fraud.\n", + "4. Account Age\n", + "If available, the age of the accounts (how long they have been active) may provide insights, as newer accounts may be more susceptible to fraud.\n", + "5. Destination Account Characteristics\n", + "Analyzing the destination account's balance and transaction history could reveal potential red flags.\n", + "6. Transaction Type\n", + "Different transaction types (CASH_IN, CASH_OUT, PAYMENT) may have varying risks associated with them." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "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", + "
steptypeamountnameOrigoldbalanceOrgnewbalanceOrignameDestoldbalanceDestnewbalanceDestisFraudisFlaggedFraud
6322570688CASH_IN23557.12C8677505338059.0031616.12C1026934669169508.66145951.5300
3621196274PAYMENT6236.13C6010990700.000.00M7012834110.000.0000
1226256133PAYMENT33981.87C27954093118745.720.00M5779057760.000.0000
2803274225CASH_OUT263006.42C1167553120072.000.00C529577791390253.56653259.9800
3201247249CASH_OUT152013.74C53064921420765.000.00C1304175579252719.19404732.9300
\n", + "
" + ], + "text/plain": [ + " step type amount nameOrig oldbalanceOrg newbalanceOrig \\\n", + "6322570 688 CASH_IN 23557.12 C867750533 8059.00 31616.12 \n", + "3621196 274 PAYMENT 6236.13 C601099070 0.00 0.00 \n", + "1226256 133 PAYMENT 33981.87 C279540931 18745.72 0.00 \n", + "2803274 225 CASH_OUT 263006.42 C11675531 20072.00 0.00 \n", + "3201247 249 CASH_OUT 152013.74 C530649214 20765.00 0.00 \n", + "\n", + " nameDest oldbalanceDest newbalanceDest isFraud isFlaggedFraud \n", + "6322570 C1026934669 169508.66 145951.53 0 0 \n", + "3621196 M701283411 0.00 0.00 0 0 \n", + "1226256 M577905776 0.00 0.00 0 0 \n", + "2803274 C529577791 390253.56 653259.98 0 0 \n", + "3201247 C1304175579 252719.19 404732.93 0 0 " + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sample_data.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### What is the distribution of the outcome? " + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 99876\n", + "1 124\n", + "Name: isFraud, dtype: int64\n" + ] + }, + { + "data": { + "image/png": "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D+3Zs0enTp3SqVOntHv3btntdg0cOLCkewQAAACcSrHORCclJemLL75QaGioOVavXj3NmjWLGwsBAABwyyvWmei8vDyVKVOmwHiZMmWUl5f3l5sCAAAAnFmxQvTDDz+sQYMG6dixY+bY0aNHNWTIELVu3brEmgMAAACcUbFC9MyZM2W32xUcHKyaNWuqZs2aCgkJkd1u14wZM0q6RwAAAMCpFOua6KCgIH333Xf64osvlJaWJkkKDQ1VZGRkiTYHAAAAOCNLZ6KTk5NVr1492e122Ww2/f3vf9dzzz2n5557Tk2bNtXdd9+tjRs3Xq9eAQAAAKdgKURPmzZN/fr1k4+PT4Flvr6+euqppzR16tQSaw4AAABwRpZC9Pfff6+2bdtecXmbNm2Umpr6l5sCAAAAnJmlEJ2RkVHo1Hb53NzcdPLkyb/cFAAAAODMLIXoO+64Q7t3777i8p07d6patWp/uSkAAADAmVkK0e3bt9eYMWN0/vz5AsvOnTunsWPHqmPHjiXWHAAAAOCMLE1xN3r0aH366ae66667FB8frzp16kiS0tLSNGvWLOXm5uqll166Lo0CAAAAzsJSiPb399c333yjZ555RqNGjZJhGJIkm82mqKgozZo1S/7+/telUQAAAMBZWP6ylRo1amjlypU6ffq0fv75ZxmGodq1a6tChQrXoz8AAADA6RTrGwslqUKFCmratGlJ9gIAAADcFCzdWAgAAACAEA0AAABYRogGAAAALCJEAwAAABYRogEAAACLCNEAAACARYRoAAAAwCJCNAAAAGARIRoAAACwiBANAAAAWESIBgAAACwiRAMAAAAWEaIBAAAAiwjRAAAAgEWEaAAAAMAiQjQAAABgESEaAAAAsIgQDQAAAFhEiAYAAAAsuqlC9GuvvSabzabBgwebY+fPn9eAAQNUqVIllStXTl27dlVGRobDeocPH1aHDh1UtmxZVa1aVc8//7wuXbrkULN+/Xrde++98vDwUK1atZSYmFhg/7NmzVJwcLA8PT0VHh6uLVu2XI+XCQAAACd304TorVu36t///rfuueceh/EhQ4bo888/16JFi/TVV1/p2LFj6tKli7k8NzdXHTp0UE5Ojr755hvNnTtXiYmJSkhIMGsOHDigDh06qFWrVtqxY4cGDx6svn37avXq1WbNggULNHToUI0dO1bfffedGjRo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AblOnTpq27atnnrqKW3evFmpqanq27evvLy8rrrvVq1a6cyZMw5TQYWGhqpt27bq16+ftmzZok2bNik+Pl4xMTEO109/++238vDwUERERMkcCABOpVatWrp48aJmzJihX375RfPmzTNvOMz30EMP6eTJk5o8ebL279+vWbNmadWqVQ41gwYN0muvvaalS5cqLS1Nzz777DX/B79KlSq699579fXXXzuMnzp1Sjt27DDD9b59+7Rjx44C92ts3LhRbdq0KeYrx62OEA0U04QJEwp80969996rhQsX6pNPPlH9+vWVkJCgCRMmOFzXPGHCBB08eFA1a9Ys0T8TPvXUU+rSpYsee+wxhYeH6/fff9ezzz7rUPPkk0+qV69e6tmzpx588EHdeeedatWqlUPNBx98oMDAQD344IPq0qWL+vfvf82bcipVqqTOnTsXmA7vo48+Ut26ddW6dWu1b99eLVq00DvvvONQ8/HHHys2NrZI10UCuPk0aNBAU6dO1euvv6769evro48+KjBVaGhoqGbPnq1Zs2apQYMG2rJlS4H7ToYNG6YePXqoV69eioiIUPny5dW5c+dr7r9v374FPpuWLVumRo0amdNyxsTEqFGjRg7hPiUlRVlZWerWrVtxXzpucTbjWpMsAkAR7Ny5U3//+9+1f/9+h7v2r+a3335TnTp1tG3btkK/qAEA/qpz586pTp06WrBggaW/eD322GNq0KCBXnzxxevYHW5mnIkGUCLuuecevf766zpw4ECR1zl48KBmz55NgAZw3Xh5eek///mPpcvncnJyFBYWpiFDhlzHznCz40w0AAAAYBFnogEAAACLCNEAAACARYRoAAAAwCJCNAAAAGARIRoAAACwiBANAHBqBw8elM1mc/gaaAAobYRoALhF9e7dW9HR0cVaNz+4/vnxxBNPlGyTAHCTcivtBgAAzuuLL77Q3XffbT738vIqUGMYhnJzc+Xmxj8pAG4fnIkGgNvE4sWLFRYWJi8vL1WqVEmRkZHKzs6+6jqVKlVSQECA+fD19dX69etls9m0atUqNW7cWB4eHvr666+1f/9+/eMf/5C/v7/KlSunpk2b6osvvnDYns1m09KlSx3G/Pz8lJiYaD7fsmWLGjVqJE9PTzVp0kTbt28vqUMAACWGEA0At4Hjx4+re/fuevLJJ7V3716tX79eXbp00V/50tqRI0fqtdde0969e3XPPffozJkzat++vdatW6ft27erbdu26tSpkw4fPlzkbZ45c0YdO3ZUvXr1lJqaqnHjxmn48OHF7hEArhf+9gYAt4Hjx4/r0qVL6tKli2rUqCFJCgsLu+Z6zZs3l4vL/z/fsnHjRvPnCRMm6O9//7v5vGLFimrQoIH5/OWXX9aSJUu0bNkyxcfHF6nP+fPnKy8vT++99548PT11991369dff9UzzzxTpPUB4EYhRAPAbaBBgwZq3bq1wsLCFBUVpTZt2qhbt26qUKHCVddbsGCBQkNDzedBQUFKSUmRJDVp0sSh9syZMxo3bpxWrFhhhvZz585ZOhOdf1bb09PTHIuIiCjy+gBwo3A5BwDcBlxdXbV27VqtWrVK9erV04wZM1SnTh0dOHDgqusFBQWpVq1a5sPDw8Nc5u3t7VA7fPhwLVmyRBMnTtTGjRu1Y8cOhYWFKScnx6yx2WwFLiG5ePFiCbxCALixCNEAcJuw2Wy6//77NX78eG3fvl3u7u5asmRJiW1/06ZN6t27tzp37qywsDAFBATo4MGDDjVVqlTR8ePHzec//fSTzp49az4PDQ3Vzp07df78eXPs22+/LbEeAaCkEKIB4DawefNmTZw4Udu2bdPhw4f16aef6uTJkw6XavxVtWvX1qeffqodO3bo+++/1+OPP668vDyHmocfflgzZ87U9u3btW3bNj399NMqU6aMufzxxx+XzWZTv3799MMPP2jlypX617/+VWI9AkBJIUQDwG3Ax8dHGzZsUPv27XXXXXdp9OjRmjJlitq1a1di+5g6daoqVKig5s2bq1OnToqKitK9997rUDNlyhQFBQXpgQce0OOPP67hw4erbNmy5vJy5crp888/165du9SoUSO99NJLev3110usRwAoKTbjr8xvBAAAANyGOBMNAAAAWESIBgAAACwiRAMAAAAWEaIBAAAAiwjRAAAAgEWEaAAAAMAiQjQAAABgESEaAAAAsIgQDQAAAFhEiAYAAAAsIkQDAAAAFv0/lEXf83/RL44AAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Your response here\n", + "# Count the occurrences of each outcome\n", + "outcome_counts = sample_data['isFraud'].value_counts()\n", + "\n", + "# Print the outcome counts\n", + "print(outcome_counts)\n", + "\n", + "# Plotting the distribution of the outcome\n", + "plt.figure(figsize=(8, 5))\n", + "sns.countplot(x='isFraud', data=sample_data, palette='Set2')\n", + "plt.title('Distribution of Fraud Outcomes')\n", + "plt.xlabel('Is Fraud')\n", + "plt.ylabel('Count')\n", + "plt.xticks([0, 1], ['Not Fraud (0)', 'Fraud (1)'])\n", + "plt.show()" + ] + }, + { + "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": 31, + "metadata": {}, + "outputs": [], + "source": [ + "fraud_data = data[data['isFraud'] == 1]\n", + "non_fraud_data = data[data['isFraud'] == 0]\n", + "\n", + "total_data_count = len(data)\n", + "fraud_data_count = len(fraud_data)\n", + "\n", + "sampled_non_fraud_data = non_fraud_data.sample(n=fraud_data_count, random_state=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "balanced_data = pd.concat([sampled_non_fraud_data, fraud_data], ignore_index=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "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", + "
steptypeamountnameOrigoldbalanceOrgnewbalanceOrignameDestoldbalanceDestnewbalanceDestisFraudisFlaggedFraud
0159CASH_IN290448.64C68393327249671.00340119.64C94875193434047.630.0000
119PAYMENT7521.26C14342205110.000.00M20981893660.000.0000
2210PAYMENT12043.69C16325750260.000.00M833468070.000.0000
3357CASH_IN120116.21C83572709197688.68217804.90C2084926563849069.38728953.1700
4211CASH_OUT115161.12C16567397050.000.00C778089718576802.51691963.6300
\n", + "
" + ], + "text/plain": [ + " step type amount nameOrig oldbalanceOrg newbalanceOrig \\\n", + "0 159 CASH_IN 290448.64 C683933272 49671.00 340119.64 \n", + "1 19 PAYMENT 7521.26 C1434220511 0.00 0.00 \n", + "2 210 PAYMENT 12043.69 C1632575026 0.00 0.00 \n", + "3 357 CASH_IN 120116.21 C835727091 97688.68 217804.90 \n", + "4 211 CASH_OUT 115161.12 C1656739705 0.00 0.00 \n", + "\n", + " nameDest oldbalanceDest newbalanceDest isFraud isFlaggedFraud \n", + "0 C948751934 34047.63 0.00 0 0 \n", + "1 M2098189366 0.00 0.00 0 0 \n", + "2 M83346807 0.00 0.00 0 0 \n", + "3 C2084926563 849069.38 728953.17 0 0 \n", + "4 C778089718 576802.51 691963.63 0 0 " + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "balanced_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "16426\n" + ] + } + ], + "source": [ + "print(len(balanced_data))" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 8213\n", + "1 8213\n", + "Name: isFraud, dtype: int64\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAsAAAAHWCAYAAAB5SD/0AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAABMh0lEQVR4nO3deVgVdf//8dcBZBEFXEGShNQUDfdSyiyVRMXKrbLIFTUNM7XU7GtkVlqW+3p3t2CllXqnleaCexpuFKm4VOZWClgGxxUU5vdHF/PzBCoacsh5Pq5rrovzmffMvOccOr4aPmeOzTAMQwAAAIBFuDi7AQAAAKA4EYABAABgKQRgAAAAWAoBGAAAAJZCAAYAAIClEIABAABgKQRgAAAAWAoBGAAAAJZCAAYAAIClEIABXJMxY8bIZrMVy7Huv/9+3X///ebj9evXy2azadGiRcVy/F69eik4OLhYjnW9Tp8+rb59+yogIEA2m01Dhgxxdkv/SN5rvH79eme3AuAmRgAGLCw+Pl42m81cPD09FRgYqMjISE2bNk2nTp0qkuMcO3ZMY8aMUXJycpHsryiV5N4KY9y4cYqPj9fAgQP10UcfqXv37petDQ4Odni9L13Onz9fjF0XnZSUFD355JO65ZZb5OHhocDAQEVHRyslJeUf7XfcuHFasmRJ0TQJoMRxc3YDAJxv7NixCgkJ0YULF5Samqr169dryJAhmjRpkr788kvVq1fPrB09erReeOGFa9r/sWPH9Morryg4OFgNGjQo9HarVq26puNcjyv19t///le5ubk3vId/Yu3atWrWrJlefvnlQtU3aNBAzz33XL5xd3f3om7thvv888/1+OOPq3z58oqJiVFISIgOHTqk9957T4sWLdKnn36qTp06Xde+x40bp65du6pjx45F2zSAEoEADEDt2rVTkyZNzMejRo3S2rVr1aFDBz300EPau3evvLy8JElubm5yc7uxbx1nz55V6dKlnR7KSpUq5dTjF0Z6errq1KlT6PpbbrlFTz75ZKHr816LkubAgQPq3r27brvtNm3cuFGVKlUy1z377LO699571b17d+3cuVO33XabEzsFUBIxBQJAgVq1aqWXXnpJhw8f1scff2yOFzQHOCEhQc2bN5efn5/KlCmjWrVq6cUXX5T015zOO++8U5LUu3dv80/u8fHxkv6a53vH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Ju/5ad++vbZt26bExERz3ZkzZ/TOO+8oODj4mu7bfCWdO3eWq6urXnnllXz/I2EYhvm82O12c95wnrCwMLm4uBT6tnPAzYYpEAC0fPly7du3TxcvXlRaWprWrl2rhIQEVatWTV9++aU8PT0vu+3YsWO1ceNGRUVFqVq1akpPT9esWbNUtWpV80NA1atXl5+fn+bMmaOyZcvK29tbTZs2VUhIyHX1W758eTVv3ly9e/dWWlqapkyZoho1ajjcqq1v375atGiR2rZtq0cffVQHDhzQxx9/7PChtGvt7cEHH1TLli31f//3fzp06JDq16+vVatW6YsvvtCQIUPy7ft69e/fX//5z3/Uq1cvJSUlKTg4WIsWLdLmzZs1ZcqUIpvTWlh33323ypUrp549e2rw4MGy2Wz66KOPCpzKUdjnvV+/fpoxY4Z69OihpKQkValSRR999FGhv3SjZs2amjt3rqKjoxUWFpbvm+B+//13ffLJJw7H7datm0aOHKlOnTpp8ODBOnv2rGbPnq3bb79d3333ncP+GzdurNWrV2vSpEkKDAxUSEiImjZtqnHjxmnVqlW677771L9/f4WGhur48eNauHChNm3aJD8/P73wwgv65JNP1K5dOw0ePFjly5fX3LlzdfDgQf3vf//LN7f7elWvXl2vvfaaRo0apUOHDqljx44qW7asDh48qMWLF6t///56/vnntXbtWg0aNEiPPPKIbr/9dl28eFEfffSRXF1d1aVLlyLpBfjXccq9JwCUCHm3Qctb3N3djYCAAOOBBx4wpk6d6nC7rTx/v2XUmjVrjIcfftgIDAw03N3djcDAQOPxxx83fvzxR4ftvvjiC6NOnTqGm5ubw23H7rvvPqNu3boF9ne526B98sknxqhRo4zKlSsbXl5eRlRUlHH48OF820+cONG45ZZbDA8PD+Oee+4xduzYkW+fV+qtoNtmnTp1yhg6dKgRGBholCpVyqhZs6bx1ltvmbfAyiPJiI2NzdfT5W4T9ndpaWlG7969jYoVKxru7u5GWFhYgbdqu9bboF2p9kqvxebNm41mzZoZXl5eRmBgoDFixAhj5cqVBd6yrLDP++HDh42HHnrIKF26tFGxYkXj2WefNVasWHHV26BdaufOncbjjz9uVKlSxShVqpQREBBgPP7448auXbsKrF+1apVxxx13GO7u7katWrWMjz/+uMDboO3bt89o0aKF4eXlZUhyeM0OHz5s9OjRw6hUqZLh4eFh3HbbbUZsbKyRlZVl1hw4cMDo2rWr4efnZ3h6ehp33XWXsXTpUodj5P0+//32ZJe7PWFen3+/5eD//vc/o3nz5oa3t7fh7e1t1K5d24iNjTX2799vGIZh/PLLL0afPn2M6tWrG56enkb58uWNli1bGqtXry7UcwzcjGyGUYI/jQEAAAAUMeYAAwAAwFIIwAAAALAUAjAAAAAshQAMAAAASyEAAwAAwFIIwAAAALAUvgijEHJzc3Xs2DGVLVu2yL/SFQAAAP+cYRg6deqUAgMDr/qFMwTgQjh27JiCgoKc3QYAAACu4ujRo6pateoVawjAhZD3taNHjx6Vj4+Pk7sBAADA39ntdgUFBRXq6+IJwIWQN+3Bx8eHAAwAAFCCFWa6Kh+CAwAAgKUQgAEAAGApBGAAAABYCgEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYCgEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYCgEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYipuzG8DVPbf8Q2e3AOAGmdiuh7NbcIr02SOc3QKAG6TywAnObuGquAIMAAAASyEAAwAAwFIIwAAAALAUAjAAAAAshQAMAAAAS3FqAM7JydFLL72kkJAQeXl5qXr16nr11VdlGIZZYxiG4uLiVKVKFXl5eSkiIkI//fSTw35Onjyp6Oho+fj4yM/PTzExMTp9+rRDzc6dO3XvvffK09NTQUFBmjCh5H9CEQAAAEXPqQH4zTff1OzZszVjxgzt3btXb775piZMmKDp06ebNRMmTNC0adM0Z84cbd26Vd7e3oqMjNT58+fNmujoaKWkpCghIUFLly7Vxo0b1b9/f3O93W5XmzZtVK1aNSUlJemtt97SmDFj9M477xTr+QIAAMD5nHof4G+//VYPP/ywoqKiJEnBwcH65JNPtG3bNkl/Xf2dMmWKRo8erYcffliS9OGHH8rf319LlixRt27dtHfvXq1YsULbt29XkyZNJEnTp09X+/bt9fbbbyswMFDz5s1Tdna23n//fbm7u6tu3bpKTk7WpEmTHIIyAAAAbn5OvQJ89913a82aNfrxxx8lST/88IM2bdqkdu3aSZIOHjyo1NRURUREmNv4+vqqadOmSkxMlCQlJibKz8/PDL+SFBERIRcXF23dutWsadGihdzd3c2ayMhI7d+/X3/++We+vrKysmS32x0WAAAA3BycegX4hRdekN1uV+3ateXq6qqcnBy9/vrrio6OliSlpqZKkvz9/R228/f3N9elpqaqcuXKDuvd3NxUvnx5h5qQkJB8+8hbV65cOYd148eP1yuvvFJEZwkAAICSxKlXgBcsWKB58+Zp/vz5+u677zR37ly9/fbbmjt3rjPb0qhRo5SZmWkuR48edWo/AAAAKDpOvQI8fPhwvfDCC+rWrZskKSwsTIcPH9b48ePVs2dPBQQESJLS0tJUpUoVc7u0tDQ1aNBAkhQQEKD09HSH/V68eFEnT540tw8ICFBaWppDTd7jvJpLeXh4yMPDo2hOEgAAACWKU68Anz17Vi4uji24uroqNzdXkhQSEqKAgACtWbPGXG+327V161aFh4dLksLDw5WRkaGkpCSzZu3atcrNzVXTpk3Nmo0bN+rChQtmTUJCgmrVqpVv+gMAAABubk4NwA8++KBef/11LVu2TIcOHdLixYs1adIkderUSZJks9k0ZMgQvfbaa/ryyy+1a9cu9ejRQ4GBgerYsaMkKTQ0VG3btlW/fv20bds2bd68WYMGDVK3bt0UGBgoSXriiSfk7u6umJgYpaSk6LPPPtPUqVM1bNgwZ506AAAAnMSpUyCmT5+ul156SU8//bTS09MVGBiop556SnFxcWbNiBEjdObMGfXv318ZGRlq3ry5VqxYIU9PT7Nm3rx5GjRokFq3bi0XFxd16dJF06ZNM9f7+vpq1apVio2NVePGjVWxYkXFxcVxCzQAAAALshmXfu0aCmS32+Xr66vMzEz5+PgU+/GfW/5hsR8TQPGY2K6Hs1twivTZI5zdAoAbpPJA53zb7rXkNadOgQAAAACKGwEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYCgEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYCgEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYCgEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYCgEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYCgEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYCgEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYCgEYAAAAlkIABgAAgKUQgAEAAGApBGAAAABYilMDcHBwsGw2W74lNjZWknT+/HnFxsaqQoUKKlOmjLp06aK0tDSHfRw5ckRRUVEqXbq0KleurOHDh+vixYsONevXr1ejRo3k4eGhGjVqKD4+vrhOEQAAACWMUwPw9u3bdfz4cXNJSEiQJD3yyCOSpKFDh+qrr77SwoULtWHDBh07dkydO3c2t8/JyVFUVJSys7P17bffau7cuYqPj1dcXJxZc/DgQUVFRally5ZKTk7WkCFD1LdvX61cubJ4TxYAAAAlgpszD16pUiWHx2+88YaqV6+u++67T5mZmXrvvfc0f/58tWrVSpL0wQcfKDQ0VFu2bFGzZs20atUq7dmzR6tXr5a/v78aNGigV199VSNHjtSYMWPk7u6uOXPmKCQkRBMnTpQkhYaGatOmTZo8ebIiIyOL/ZwBAADgXCVmDnB2drY+/vhj9enTRzabTUlJSbpw4YIiIiLMmtq1a+vWW29VYmKiJCkxMVFhYWHy9/c3ayIjI2W325WSkmLWXLqPvJq8fRQkKytLdrvdYQEAAMDNocQE4CVLligjI0O9evWSJKWmpsrd3V1+fn4Odf7+/kpNTTVrLg2/eevz1l2pxm6369y5cwX2Mn78ePn6+ppLUFDQPz09AAAAlBAlJgC/9957ateunQIDA53dikaNGqXMzExzOXr0qLNbAgAAQBFx6hzgPIcPH9bq1av1+eefm2MBAQHKzs5WRkaGw1XgtLQ0BQQEmDXbtm1z2FfeXSIurfn7nSPS0tLk4+MjLy+vAvvx8PCQh4fHPz4vAAAAlDwl4grwBx98oMqVKysqKsoca9y4sUqVKqU1a9aYY/v379eRI0cUHh4uSQoPD9euXbuUnp5u1iQkJMjHx0d16tQxay7dR15N3j4AAABgLU4PwLm5ufrggw/Us2dPubn9/wvSvr6+iomJ0bBhw7Ru3TolJSWpd+/eCg8PV7NmzSRJbdq0UZ06ddS9e3f98MMPWrlypUaPHq3Y2FjzCu6AAQP0yy+/aMSIEdq3b59mzZqlBQsWaOjQoU45XwAAADiX06dArF69WkeOHFGfPn3yrZs8ebJcXFzUpUsXZWVlKTIyUrNmzTLXu7q6aunSpRo4cKDCw8Pl7e2tnj17auzYsWZNSEiIli1bpqFDh2rq1KmqWrWq3n33XW6BBgAAYFE2wzAMZzdR0tntdvn6+iozM1M+Pj7Ffvznln9Y7McEUDwmtuvh7BacIn32CGe3AOAGqTxwglOOey15zelTIAAAAIDiRAAGAACApRCAAQAAYCkEYAAAAFgKARgAAACWQgAGAACApRCAAQAAYCkEYAAAAFgKARgAAACWQgAGAACApRCAAQAAYCkEYAAAAFgKARgAAACWQgAGAACApRCAAQAAYCkEYAAAAFgKARgAAACWQgAGAACApRCAAQAAYCkEYAAAAFgKARgAAACWQgAGAACApRCAAQAAYCkEYAAAAFgKARgAAACWQgAGAACApRCAAQAAYCkEYAAAAFgKARgAAACWQgAGAACApRCAAQAAYCkEYAAAAFgKARgAAACWQgAGAACApTg9AP/222968sknVaFCBXl5eSksLEw7duww1xuGobi4OFWpUkVeXl6KiIjQTz/95LCPkydPKjo6Wj4+PvLz81NMTIxOnz7tULNz507de++98vT0VFBQkCZMmFAs5wcAAICSxakB+M8//9Q999yjUqVKafny5dqzZ48mTpyocuXKmTUTJkzQtGnTNGfOHG3dulXe3t6KjIzU+fPnzZro6GilpKQoISFBS5cu1caNG9W/f39zvd1uV5s2bVStWjUlJSXprbfe0pgxY/TOO+8U6/kCAADA+dycefA333xTQUFB+uCDD8yxkJAQ82fDMDRlyhSNHj1aDz/8sCTpww8/lL+/v5YsWaJu3bpp7969WrFihbZv364mTZpIkqZPn6727dvr7bffVmBgoObNm6fs7Gy9//77cnd3V926dZWcnKxJkyY5BGUAAADc/Jx6BfjLL79UkyZN9Mgjj6hy5cpq2LCh/vvf/5rrDx48qNTUVEVERJhjvr6+atq0qRITEyVJiYmJ8vPzM8OvJEVERMjFxUVbt241a1q0aCF3d3ezJjIyUvv379eff/6Zr6+srCzZ7XaHBQAAADcHpwbgX375RbNnz1bNmjW1cuVKDRw4UIMHD9bcuXMlSampqZIkf39/h+38/f3NdampqapcubLDejc3N5UvX96hpqB9XHqMS40fP16+vr7mEhQUVARnCwAAgJLAqQE4NzdXjRo10rhx49SwYUP1799f/fr105w5c5zZlkaNGqXMzExzOXr0qFP7AQAAQNFxagCuUqWK6tSp4zAWGhqqI0eOSJICAgIkSWlpaQ41aWlp5rqAgAClp6c7rL94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hMm8OpvN5rBUrVr1mo5VnObMmaOQkBDdfffd5tjJkycVHR0tHx8f+fn5KSYmRqdPnzbXt23bVqVKldK8efOc0TKA65D3fvj35eeff3Z2awX64Ycf9PXXX2vw4MHm2Oeff642bdqoQoUKstlsSk5OdtjG3d1dzz//vEaOHFnM3eLfhAAMS/D09NSbb76pP//8s9iOOXbsWB0/ftxcvv/++wLrLly4UGw9FcQwDM2YMUMxMTEO49HR0UpJSVFCQoKWLl2qjRs3qn///g41vXr10rRp04qzXQD/UNu2bR3em44fP66QkJB8ddnZ2U7oztH06dP1yCOPqEyZMubYmTNn1Lx5c7355puX3S46OlqbNm1SSkpKcbSJfyECMCwhIiJCAQEBGj9+/BXr/ve//6lu3bry8PBQcHCwJk6caK67//77dfjwYQ0dOtS8anIlZcuWVUBAgLlUqlRJkmSz2TR79mw99NBD8vb21uuvv66cnBzFxMQoJCREXl5eqlWrlqZOneqwv/vvv19DhgxxGOvYsaN69eplPk5PT9eDDz4oLy8vhYSEFOrqbFJSkg4cOKCoqChzbO/evVqxYoXeffddNW3aVM2bN9f06dP16aef6tixY2bdgw8+qB07dujAgQNXPQ6AksHDw8PhvSkgIECurq66//77NWjQIA0ZMkQVK1ZUZGSkJGnSpEkKCwuTt7e3goKC9PTTTzv8NWjMmDFq0KCBwzGmTJmi4OBg83FOTo6GDRsmPz8/VahQQSNGjNDVvoYgJydHixYt0oMPPugw3r17d8XFxSkiIuKy25YrV0733HOPPv3000I+K7AaAjAswdXVVePGjdP06dP166+/FliTlJSkRx99VN26ddOuXbs0ZswYvfTSS4qPj5f015/dqlat6nBl93qNGTNGnTp10q5du9SnTx/l5uaqatWqWrhwofbs2aO4uDi9+OKLWrBgwTXtt1evXjp69KjWrVunRYsWadasWUpPT7/iNt98841uv/12lS1b1hxLTEyUn5+fmjRpYo5FRETIxcVFW7duNcduvfVW+fv765tvvrmmPgGUTHPnzpW7u7s2b96sOXPmSJJcXFw0bdo0paSkaO7cuVq7dq1GjBhxTfudOHGi4uPj9f7772vTpk06efKkFi9efMVtdu7cqczMTIf3oWtx11138d6Ey7LMVyEDnTp1UoMGDfTyyy/rvffey7d+0qRJat26tV566SVJ0u233649e/borbfeUq9evVS+fHm5urqaV3avZuTIkRo9erT5eNy4ceY8tieeeEK9e/d2qH/llVfMn0NCQpSYmKgFCxbo0UcfLdT5/fjjj1q+fLm2bdumO++8U5L03nvvKTQ09IrbHT58WIGBgQ5jqampqly5ssOYm5ubypcvr9TUVIfxwMBAHT58uFA9AnC+pUuXOkwpaNeunRYuXChJqlmzpiZMmOBQf+lfnoKDg/Xaa69pwIABmjVrVqGPOWXKFI0aNUqdO3eW9NfnDlauXHnFbQ4fPixXV9d870WFxXsTroQADEt588031apVKz3//PP51u3du1cPP/yww9g999yjKVOmKCcnR66urtd0rOHDhztMT6hYsaL5c0FXNGbOnKn3339fR44c0blz55SdnZ3vz4pXsnfvXrm5ualx48bmWO3ateXn53fF7c6dOydPT89CH+fvvLy8dPbs2eveHkDxatmypWbPnm0+9vb2Nn++9P0jz+rVqzV+/Hjt27dPdrtdFy9e1Pnz53X27FmVLl36qsfLzMzU8ePH1bRpU3PMzc1NTZo0ueI0iHPnzsnDw+OaP6ych/cmXAlTIGApLVq0UGRkpEaNGnXDj1WxYkXVqFHDXC4Nopf+gyNJn376qZ5//nnFxMRo1apVSk5OVu/evR0+hOLi4pLvH4ui+ABdxYoV8304MCAgIN/UiYsXL+rkyZP5rn6fPHnSnN8MoOTz9vZ2eG+qUqWKw7pLHTp0SB06dFC9evX0v//9T0lJSZo5c6ak//8huRv53nT27Nnr/jAe7024EgIwLOeNN97QV199pcTERIfx0NBQbd682WFs8+bNuv32282rv+7u7srJySnynjZv3qy7775bTz/9tBo2bKgaNWrk+2BZpUqVHOYd5+TkaPfu3ebj2rVr6+LFi0pKSjLH9u/fr4yMjCseu2HDhtq3b5/DP2Dh4eHKyMhw2NfatWuVm5vrcBXn/PnzOnDggBo2bHjN5wyg5EtKSlJubq4mTpyoZs2a6fbbb3f4IKz013tTamqqw3vIpbcm8/X1VZUqVRw+P/D396qC5P0FbM+ePdfV++7du3lvwmURgGE5YWFhio6Oznf7rueee05r1qzRq6++qh9//FFz587VjBkzHKZLBAcHa+PGjfrtt9/0+++/F1lPNWvW1I4dO7Ry5Ur9+OOPeumll7R9+3aHmlatWmnZsmVatmyZ9u3bp4EDBzqE21q1aqlt27Z66qmntHXrViUlJalv377y8vK64rFbtmyp06dPO9wuKDQ0VG3btlW/fv20bds2bd68WYMGDVK3bt0c5gtv2bJFHh4eCg8PL5onAkCJUqNGDV24cEHTp0/XL7/8oo8++sj8cFye+++/XydOnNCECRN04MABzZw5U8uXL3eoefbZZ/XGG29oyZIl2rdvn55++umr/s95pUqV1KhRI23atMlh/OTJk0pOTjaD8f79+5WcnJzv8wnffPON2rRpc51njpsdARiWNHbs2HzfYNaoUSMtWLBAn376qe644w7FxcVp7NixDvN4x44dq0OHDql69epF+qe1p556Sp07d9Zjjz2mpk2b6o8//tDTTz/tUNOnTx/17NlTPXr00H333afbbrtNLVu2dKj54IMPFBgYqPvuu0+dO3dW//79r/oBkgoVKqhTp075bpk2b9481a5dW61bt1b79u3VvHlzvfPOOw41n3zyiaKjows1DxDAv0/9+vU1adIkvfnmm7rjjjs0b968fLeTDA0N1axZszRz5kzVr19f27Zty/c5i+eee07du3dXz549FR4errJly6pTp05XPX7fvn3zvTd9+eWXatiwoXnrxm7duqlhw4YOwTwxMVGZmZnq2rXr9Z46bnI242o34gNw09u5c6ceeOABHThwwOHT4Vfy+++/q1atWtqxY0eBN9EHgH/q3LlzqlWrlj777LNr+kvTY489pvr16+vFF1+8gd3h34wrwABUr149vfnmmzp48GChtzl06JBmzZpF+AVww3h5eenDDz+8piln2dnZCgsL09ChQ29gZ/i34wowAAAALIUrwAAAALAUAjAAAAAshQAMAAAASyEAAwAAwFIIwAAAALAUAjAA4IY4dOiQbDabw9fiAkBJQAAGgBKmV69e6tix43Vtmxc6/748+eSTRdskAPyLuTm7AQBA0Vu9erXq1q1rPvby8spXYxiGcnJy5ObGPwUArIUrwABQwi1atEhhYWHy8vJShQoVFBERoTNnzlxxmwoVKiggIMBcfH19tX79etlsNi1fvlyNGzeWh4eHNm3apAMHDujhhx+Wv7+/ypQpozvvvFOrV6922J/NZtOSJUscxvz8/BQfH28+3rZtmxo2bChPT081adJE33//fVE9BQBQpAjAAFCCHT9+XI8//rj69OmjvXv3av369ercubP+yZd4vvDCC3rjjTe0d+9e1atXT6dPn1b79u21Zs0aff/992rbtq0efPBBHTlypND7PH36tDp06KA6deooKSlJY8aM0fPPP3/dPQLAjcTfvQCgBDt+/LguXryozp07q1q1apKksLCwq2539913y8Xl/1/j+Oabb8yfx44dqwceeMB8XL58edWvX998/Oqrr2rx4sX68ssvNWjQoEL1OX/+fOXm5uq9996Tp6en6tatq19//VUDBw4s1PYAUJwIwABQgtWvX1+tW7dWWFiYIiMj1aZNG3Xt2lXlypW74nafffaZQkNDzcdBQUFKTEyUJDVp0sSh9vTp0xozZoyWLVtmBu5z585d0xXgvKvJnp6e5lh4eHihtweA4sQUCAAowVxdXZWQkKDly5erTp06mj59umrVqqWDBw9ecbugoCDVqFHDXDw8PMx13t7eDrXPP/+8Fi9erHHjxumbb75RcnKywsLClJ2dbdbYbLZ80y4uXLhQBGcIAMWPAAwAJZzNZtM999yjV155Rd9//73c3d21ePHiItv/5s2b1atXL3Xq1ElhYWEKCAjQoUOHHGoqVaqk48ePm49/+uknnT171nwcGhqqnTt36vz58+bYli1biqxHAChKBGAAKMG2bt2qcePGaceOHTpy5Ig+//xznThxwmF6wz9Vs2ZNff7550pOTtYPP/ygJ554Qrm5uQ41rVq10owZM/T9999rx44dGjBggEqVKmWuf+KJJ2Sz2dSvXz/t2bNHX3/9td5+++0i6xEAihIBGABKMB8fH23cuFHt27fX7bffrtGjR2vixIlq165dkR1j0qRJKleunO6++249+OCDioyMVKNGjRxqJk6cqKCgIN1777164okn9Pzzz6t06dLm+jJlyuirr77Srl271LBhQ/3f//2f3nzzzSLrEQCKks34J/fSAQAAAP5luAIMAAAASyEAAwAAwFIIwAAAALAUAjAAAAAshQAMAAAASyEAAwAAwFIIwAAAALAUAjAAAAAshQAMAAAASyEAAwAAwFIIwAAAALCU/wcA9dROX8hp3AAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Your response here\n", + "# Count the occurrences of each outcome in balanced data\n", + "outcome_counts = balanced_data['isFraud'].value_counts()\n", + "\n", + "# Print the outcome counts in balanced data\n", + "print(outcome_counts)\n", + "\n", + "# Plotting the distribution of the outcome in balanced data\n", + "plt.figure(figsize=(8, 5))\n", + "sns.countplot(x='isFraud', data=balanced_data, palette='Set2')\n", + "plt.title('Distribution of Fraud Outcomes')\n", + "plt.xlabel('Is Fraud')\n", + "plt.ylabel('Count')\n", + "plt.xticks([0, 1], ['Not Fraud (0)', 'Fraud (1)'])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "type 0\n", + "amount 0\n", + "oldbalanceOrg 0\n", + "newbalanceOrig 0\n", + "oldbalanceDest 0\n", + "newbalanceDest 0\n", + "isFraud 0\n", + "isFlaggedFraud 0\n", + "dtype: int64\n" + ] + } + ], + "source": [ + "# Your code here\n", + "# Drop unnecessary columns \n", + "balanced_data.drop(columns=['step', 'nameOrig', 'nameDest'], inplace=True) \n", + "\n", + "# Check for missing values\n", + "print(balanced_data.isnull().sum())\n", + "\n", + "# Handle missing values \n", + "balanced_data.dropna(inplace=True)\n", + "\n", + "# Check for duplicates\n", + "balanced_data.drop_duplicates(inplace=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a feature for balance change\n", + "balanced_data['balance_change'] = balanced_data['newbalanceOrig'] - balanced_data['oldbalanceOrg']" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [], + "source": [ + "# One-hot encode the 'type' column\n", + "balanced_data = pd.get_dummies(balanced_data, columns=['type'], drop_first=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [], + "source": [ + "# Define features and target variable\n", + "X = balanced_data.drop(columns=['isFraud', 'isFlaggedFraud']) # Features\n", + "y = balanced_data['isFraud'] # Target\n", + "\n", + "# Scale numerical features\n", + "scaler = StandardScaler()\n", + "X_scaled = scaler.fit_transform(X)" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [], + "source": [ + "X_final = pd.DataFrame(X_scaled, columns=X.columns)\n", + "y_final = y.reset_index(drop=True)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run a logisitc regression classifier and evaluate its accuracy." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "# Your code here\n", + "\n", + "# Split the dataset into training and testing sets\n", + "X_train, X_test, y_train, y_test = train_test_split(X_final, y_final, test_size=0.2, random_state=42)" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Create and fit the logistic regression model\n", + "model = LogisticRegression()\n", + "model.fit(X_train, y_train)\n", + "\n", + "# Make predictions on the test set\n", + "y_pred = model.predict(X_test)\n", + "\n", + "# Evaluate the model's accuracy\n", + "accuracy = accuracy_score(y_test, y_pred)\n", + "conf_matrix = confusion_matrix(y_test, y_pred)\n", + "class_report = classification_report(y_test, y_pred)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.9156736938588451" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1532, 103],\n", + " [ 173, 1465]])" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conf_matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "' precision recall f1-score support\\n\\n 0 0.90 0.94 0.92 1635\\n 1 0.93 0.89 0.91 1638\\n\\n accuracy 0.92 3273\\n macro avg 0.92 0.92 0.92 3273\\nweighted avg 0.92 0.92 0.92 3273\\n'" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "class_report" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now pick a model of your choice and evaluate its accuracy." + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Prediction Accuracy: 0.9942\n", + "Confusion Matrix:\n", + "[[1620 15]\n", + " [ 4 1634]]\n", + "Classification Report:\n", + " precision recall f1-score support\n", + "\n", + " 0 1.00 0.99 0.99 1635\n", + " 1 0.99 1.00 0.99 1638\n", + "\n", + " accuracy 0.99 3273\n", + " macro avg 0.99 0.99 0.99 3273\n", + "weighted avg 0.99 0.99 0.99 3273\n", + "\n" + ] + } + ], + "source": [ + "# Your code here\n", + "# Preprocess the dataset\n", + "X = balanced_data.drop(columns=['isFraud', 'isFlaggedFraud'])\n", + "y = balanced_data['isFraud']\n", + "\n", + "# Split the dataset into training and testing sets\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n", + "\n", + "# Create and train the Random Forest model\n", + "model = RandomForestClassifier(n_estimators=100, random_state=42)\n", + "model.fit(X_train, y_train)\n", + "\n", + "# Make predictions on the test set\n", + "y_pred = model.predict(X_test)\n", + "\n", + "# Evaluate the model's performance\n", + "accuracy = accuracy_score(y_test, y_pred)\n", + "conf_matrix = confusion_matrix(y_test, y_pred)\n", + "class_report = classification_report(y_test, y_pred)\n", + "\n", + "# Print the results\n", + "print(f\"Prediction Accuracy: {accuracy:.4f}\")\n", + "print(\"Confusion Matrix:\")\n", + "print(conf_matrix)\n", + "print(\"Classification Report:\")\n", + "print(class_report)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Which model worked better and how do you know?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Your response here\n", + "Based on Prediction Accuracy Random Forest worked better than logistic regression model" + ] + }, + { + "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.10.6" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}