tahamajs's picture
download
raw
40.5 kB
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Read Dataset"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"from sklearn.model_selection import train_test_split\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"from sklearn.metrics import confusion_matrix, accuracy_score\n",
"sns.set()"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Fiscal Year Released</th>\n",
" <th>Recidivism Reporting Year</th>\n",
" <th>Race - Ethnicity</th>\n",
" <th>Age At Release</th>\n",
" <th>Convicting Offense Classification</th>\n",
" <th>Convicting Offense Type</th>\n",
" <th>Convicting Offense Subtype</th>\n",
" <th>Main Supervising District</th>\n",
" <th>Release Type</th>\n",
" <th>Part of Target Population</th>\n",
" <th>Recidivism - Return to Prison numeric</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2010</td>\n",
" <td>2013</td>\n",
" <td>White</td>\n",
" <td>&lt;45</td>\n",
" <td>D Felony</td>\n",
" <td>Violent</td>\n",
" <td>Other</td>\n",
" <td>3JD</td>\n",
" <td>Parole</td>\n",
" <td>Yes</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2010</td>\n",
" <td>2013</td>\n",
" <td>White</td>\n",
" <td>&gt;45</td>\n",
" <td>D Felony</td>\n",
" <td>Other</td>\n",
" <td>Other</td>\n",
" <td>3JD</td>\n",
" <td>Parole</td>\n",
" <td>Yes</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2010</td>\n",
" <td>2013</td>\n",
" <td>White</td>\n",
" <td>&lt;45</td>\n",
" <td>D Felony</td>\n",
" <td>Other</td>\n",
" <td>Other</td>\n",
" <td>5JD</td>\n",
" <td>Parole</td>\n",
" <td>Yes</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2010</td>\n",
" <td>2013</td>\n",
" <td>White</td>\n",
" <td>&gt;45</td>\n",
" <td>Other Felony</td>\n",
" <td>Drug</td>\n",
" <td>Trafficking</td>\n",
" <td>3JD</td>\n",
" <td>Parole</td>\n",
" <td>Yes</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2010</td>\n",
" <td>2013</td>\n",
" <td>Black</td>\n",
" <td>&lt;45</td>\n",
" <td>D Felony</td>\n",
" <td>Drug</td>\n",
" <td>Trafficking</td>\n",
" <td>3JD</td>\n",
" <td>Parole</td>\n",
" <td>Yes</td>\n",
" <td>1</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Fiscal Year Released Recidivism Reporting Year Race - Ethnicity \\\n",
"0 2010 2013 White \n",
"1 2010 2013 White \n",
"2 2010 2013 White \n",
"3 2010 2013 White \n",
"4 2010 2013 Black \n",
"\n",
" Age At Release Convicting Offense Classification Convicting Offense Type \\\n",
"0 <45 D Felony Violent \n",
"1 >45 D Felony Other \n",
"2 <45 D Felony Other \n",
"3 >45 Other Felony Drug \n",
"4 <45 D Felony Drug \n",
"\n",
" Convicting Offense Subtype Main Supervising District Release Type \\\n",
"0 Other 3JD Parole \n",
"1 Other 3JD Parole \n",
"2 Other 5JD Parole \n",
"3 Trafficking 3JD Parole \n",
"4 Trafficking 3JD Parole \n",
"\n",
" Part of Target Population Recidivism - Return to Prison numeric \n",
"0 Yes 1 \n",
"1 Yes 1 \n",
"2 Yes 1 \n",
"3 Yes 1 \n",
"4 Yes 1 "
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.read_csv(\"../data/prison_dataset.csv\")\n",
"target = 'Recidivism - Return to Prison numeric'\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Feature Unique Values\n",
"------- -------------\n",
"Fiscal Year Released [2010 2013 2015]\n",
"Recidivism Reporting Year [2013 2016 2018]\n",
"Race - Ethnicity ['White' 'Black']\n",
"Age At Release ['<45' '>45']\n",
"Convicting Offense Classification ['D Felony' 'Other Felony']\n",
"Convicting Offense Type ['Violent' 'Other' 'Drug']\n",
"Convicting Offense Subtype ['Other' 'Trafficking']\n",
"Main Supervising District ['3JD' '5JD']\n",
"Release Type ['Parole' 'Discharged End of Sentence']\n",
"Part of Target Population ['Yes' 'No']\n",
"Recidivism - Return to Prison numeric [1 0]\n"
]
}
],
"source": [
"print(f\"{'Feature':<38} Unique Values\")\n",
"print(f\"{'-------':<38} -------------\")\n",
"for col in df.columns:\n",
" print(f'{col: <38} {df[col].unique()}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Decision Tree"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"class Node:\n",
" def __init__(self, feature=None, label=None) -> None:\n",
" self.feature = feature\n",
" self.label = label\n",
" self.children = {}\n",
" \n",
" def add_child(self, node, value):\n",
" self.children[value] = node\n",
" \n",
" def get_feature(self):\n",
" return self.feature\n",
" \n",
" def get_label(self):\n",
" return self.label\n",
" \n",
" def get_children(self):\n",
" return self.children.items()\n",
"\n",
"class DecisionTree:\n",
" def __init__(self, max_depth) -> None:\n",
" self.root = None\n",
" self.max_depth = max_depth\n",
" \n",
" def fit(self, X, y):\n",
" self.root = self._build_tree(X, y, self.max_depth)\n",
" \n",
" def predict(self, X):\n",
" return [self._traverse_tree(self.root, X.iloc[i]) for i in range(X.shape[0])]\n",
" \n",
" def _traverse_tree(self, root, x):\n",
" if root.get_feature() == None:\n",
" return root.get_label() \n",
" for value, child in root.get_children():\n",
" if value == x[root.get_feature()]:\n",
" return self._traverse_tree(child, x)\n",
" \n",
" def _build_tree(self, X, y, max_depth):\n",
" if (max_depth == 0 or self._target_entropy(y) == 0):\n",
" return Node(label=np.argmax(np.bincount(y)))\n",
" \n",
" best_feature = self._best_feature(X, y)\n",
" root = Node(feature=best_feature)\n",
" for value, group in self._split_data(X, y, best_feature).items():\n",
" child_node = self._build_tree(*group, max_depth - 1)\n",
" root.add_child(child_node, value)\n",
" \n",
" return root\n",
" \n",
" def _split_data(self, X, y, feature):\n",
" groups = {}\n",
" for value in X[feature].unique():\n",
" groups[value] = tuple([\n",
" X[X[feature] == value].drop(feature, axis=1), \n",
" y[X[feature] == value]\n",
" ])\n",
" return groups\n",
" \n",
" def _best_feature(self, X, y):\n",
" conditional_entropies = []\n",
" columns = X.columns\n",
" for col in columns:\n",
" entropies = [self._target_entropy(y[df[col] == value]) for value in df[col].unique()]\n",
" conditional_entropies.append(\n",
" np.average(entropies, weights=df[col].value_counts())\n",
" )\n",
" return columns[np.argmin(conditional_entropies)]\n",
" \n",
" def _target_entropy(self, y):\n",
" return self._entropy(y.value_counts().tolist())\n",
" \n",
" def _entropy(self, probs):\n",
" probs /= np.sum(probs)\n",
" if 1 in probs: \n",
" return 0\n",
" return -np.sum(probs * np.log2(probs))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Train and Test"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"X = df.drop(target, axis=1) \n",
"y = df[target] \n",
"\n",
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"model = DecisionTree(3)\n",
"model.fit(X_train, y_train)\n",
"y_pred = model.predict(X_test)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Evaluation"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def plt_confusion_matrix(y_true, y_pred, labels, title):\n",
" \n",
" cm = confusion_matrix(y_true, y_pred, labels=labels)\n",
" sns.heatmap(\n",
" cm.T, \n",
" square=True, \n",
" annot=True, \n",
" fmt='d', \n",
" cbar=True,\n",
" xticklabels=labels, \n",
" yticklabels=labels, \n",
" cmap=plt.cm.Blues\n",
" )\n",
" plt.xlabel('Predicted Label')\n",
" plt.ylabel('True Label')\n",
" plt.title(title + \" - Confusion Matrix\")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accuracy: 0.72\n"
]
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 640x480 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"accuracy = accuracy_score(y_test, y_pred)\n",
"print(f\"Accuracy: {accuracy:.2f}\")\n",
"plt_confusion_matrix(y_test, y_pred, [0, 1], \"Decision Tree\")\n",
"\n",
"plt.savefig('../assets/Q6_cm.png')\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"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.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

Xet Storage Details

Size:
40.5 kB
·
Xet hash:
4288608df1e208911aad0eb3d076f3b8fffb4709e76b0c896a9d75c6f2e851a7

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.