Skip to content

Instantly share code, notes, and snippets.

@jedrz
Created August 28, 2024 09:35
Show Gist options
  • Save jedrz/6ac24d10574660d2ff545a1bc6d9d08f to your computer and use it in GitHub Desktop.
Save jedrz/6ac24d10574660d2ff545a1bc6d9d08f to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "24138c5f-e4d7-4105-8dc9-fe59f04f2f35",
"metadata": {},
"source": [
"# Introduction\n",
"\n",
"Second part of credit card fraud data model training."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "da3c715a-151e-4da7-b321-462c4c1f91f8",
"metadata": {},
"outputs": [],
"source": [
"import warnings\n",
"warnings.simplefilter(action='ignore', category=FutureWarning)\n",
"warnings.simplefilter(action='ignore', category=UserWarning)\n",
"\n",
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import sklearn.model_selection\n",
"import sklearn.tree\n",
"import sklearn.svm\n",
"import sklearn.metrics\n",
"import sklearn.pipeline\n",
"import sklearn.preprocessing\n",
"import sklearn.compose\n",
"import mlflow\n",
"import mlflow.models\n",
"import imblearn.over_sampling\n",
"\n",
"random_state = 42\n",
"\n",
"# Comment to use local MLflow.\n",
"mlflow.set_tracking_uri('http://localhost:5000')"
]
},
{
"cell_type": "markdown",
"id": "a5c08ffd-1cd4-45f5-81c8-67195f73398b",
"metadata": {},
"source": [
"# Data preprocessing\n",
"\n",
"Let's say that after some time we get the idea that new features can be extracted from the original dataset.\n",
"\n",
"Using the date of birth and the transaction date, we can calculate how old a customer was and then check whether the new variable correlates with the predicted one. On the other hand, using the transaction date we can leave just the hour and minute since full date seems not to be very useful. "
]
},
{
"cell_type": "markdown",
"id": "be166fba-bc18-4f7a-8842-0fcbaf361442",
"metadata": {},
"source": [
"## Data preparation\n",
"\n",
"Copied from the first notebook."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "61376e51-bb5e-4236-ab73-5e91afacbf84",
"metadata": {},
"outputs": [],
"source": [
"data = pd.read_csv(\"fraud_data.csv\")\n",
"data = data.drop('trans_num', axis='columns', errors='ignore')\n",
"data = data[(data['is_fraud'] == '0') | (data['is_fraud'] == '1')]\n",
"data = data.map(lambda x: x.strip('\"') if isinstance(x, str) else x)\n",
"data = data.copy()\n",
"data['trans_date_trans_time'] = data['trans_date_trans_time'].apply(lambda x: pd.to_datetime(x, dayfirst=True))\n",
"data['dob'] = data['dob'].apply(lambda x: pd.to_datetime(x, dayfirst=True))\n",
"data = data.astype({\n",
" 'merchant': 'category',\n",
" 'category': 'category',\n",
" 'city': 'category',\n",
" 'state': 'category',\n",
" 'job': 'category',\n",
" 'is_fraud': 'int',\n",
"})\n",
"data = data.astype({\n",
" 'is_fraud': 'boolean',\n",
"})"
]
},
{
"cell_type": "markdown",
"id": "81469c9a-ddc4-4fd9-95d5-bc1e745d9611",
"metadata": {},
"source": [
"## Age variable\n",
"\n",
"To calculate the age of a customer, we simply need to subtract the transaction date from the date of birth. The age is approximated in days, although an integer value should be just as good."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "ee1e8f51-80d7-4077-9369-29f031328d20",
"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>trans_date_trans_time</th>\n",
" <th>dob</th>\n",
" <th>age</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2019-01-04 00:58:00</td>\n",
" <td>1939-11-09</td>\n",
" <td>79.208219</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2019-01-04 15:06:00</td>\n",
" <td>1939-11-09</td>\n",
" <td>79.208219</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2019-01-04 22:37:00</td>\n",
" <td>1939-11-09</td>\n",
" <td>79.208219</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2019-01-04 23:06:00</td>\n",
" <td>1939-11-09</td>\n",
" <td>79.208219</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2019-01-04 23:59:00</td>\n",
" <td>1939-11-09</td>\n",
" <td>79.208219</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14441</th>\n",
" <td>2019-01-22 00:37:00</td>\n",
" <td>1976-10-18</td>\n",
" <td>42.290411</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14442</th>\n",
" <td>2019-01-22 00:41:00</td>\n",
" <td>1956-09-01</td>\n",
" <td>62.432877</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14443</th>\n",
" <td>2019-01-22 00:42:00</td>\n",
" <td>1973-05-16</td>\n",
" <td>45.717808</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14444</th>\n",
" <td>2019-01-22 00:48:00</td>\n",
" <td>1939-11-09</td>\n",
" <td>79.257534</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14445</th>\n",
" <td>2019-01-22 00:55:00</td>\n",
" <td>1950-09-15</td>\n",
" <td>68.400000</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>14444 rows × 3 columns</p>\n",
"</div>"
],
"text/plain": [
" trans_date_trans_time dob age\n",
"0 2019-01-04 00:58:00 1939-11-09 79.208219\n",
"1 2019-01-04 15:06:00 1939-11-09 79.208219\n",
"2 2019-01-04 22:37:00 1939-11-09 79.208219\n",
"3 2019-01-04 23:06:00 1939-11-09 79.208219\n",
"4 2019-01-04 23:59:00 1939-11-09 79.208219\n",
"... ... ... ...\n",
"14441 2019-01-22 00:37:00 1976-10-18 42.290411\n",
"14442 2019-01-22 00:41:00 1956-09-01 62.432877\n",
"14443 2019-01-22 00:42:00 1973-05-16 45.717808\n",
"14444 2019-01-22 00:48:00 1939-11-09 79.257534\n",
"14445 2019-01-22 00:55:00 1950-09-15 68.400000\n",
"\n",
"[14444 rows x 3 columns]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"age = data.apply(lambda row: (row['trans_date_trans_time'] - row['dob']).days / 365.0, axis=1)\n",
"data[['trans_date_trans_time', 'dob']].assign(age=age)"
]
},
{
"cell_type": "markdown",
"id": "542b97ab-9f43-4ade-9501-2d8b90387e0f",
"metadata": {},
"source": [
"Show some statistics of age variable."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "ff063723-6134-4a19-87f7-8f781b42985a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"count 14444.000000\n",
"mean 48.122891\n",
"std 17.266586\n",
"min 17.446575\n",
"25% 34.356164\n",
"50% 45.961644\n",
"75% 59.306849\n",
"max 93.375342\n",
"dtype: float64"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"age.describe()"
]
},
{
"cell_type": "markdown",
"id": "472db5dc-5aa5-4863-bc7a-7319033532d1",
"metadata": {},
"source": [
"Looks good, add to the data."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "80aed9d6-5218-45c4-9fa9-3e01e998de49",
"metadata": {},
"outputs": [],
"source": [
"data = data.drop('age', axis='columns', errors='ignore') # remove just in case the cell is executed again \n",
"data.insert(data.shape[1] - 1, 'age', age)"
]
},
{
"cell_type": "markdown",
"id": "a98a307c-2c68-4ee3-86c3-5ace413b86ad",
"metadata": {},
"source": [
"## Transaction time variable\n",
"\n",
"Now extract just time of the encoded as total number of minutes starting from midnight."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "75f4ffed-90ac-4fa1-ad63-78727fd44887",
"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>trans_date_trans_time</th>\n",
" <th>trans_time</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2019-01-04 00:58:00</td>\n",
" <td>58</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2019-01-04 15:06:00</td>\n",
" <td>906</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2019-01-04 22:37:00</td>\n",
" <td>1357</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2019-01-04 23:06:00</td>\n",
" <td>1386</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2019-01-04 23:59:00</td>\n",
" <td>1439</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14441</th>\n",
" <td>2019-01-22 00:37:00</td>\n",
" <td>37</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14442</th>\n",
" <td>2019-01-22 00:41:00</td>\n",
" <td>41</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14443</th>\n",
" <td>2019-01-22 00:42:00</td>\n",
" <td>42</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14444</th>\n",
" <td>2019-01-22 00:48:00</td>\n",
" <td>48</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14445</th>\n",
" <td>2019-01-22 00:55:00</td>\n",
" <td>55</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>14444 rows × 2 columns</p>\n",
"</div>"
],
"text/plain": [
" trans_date_trans_time trans_time\n",
"0 2019-01-04 00:58:00 58\n",
"1 2019-01-04 15:06:00 906\n",
"2 2019-01-04 22:37:00 1357\n",
"3 2019-01-04 23:06:00 1386\n",
"4 2019-01-04 23:59:00 1439\n",
"... ... ...\n",
"14441 2019-01-22 00:37:00 37\n",
"14442 2019-01-22 00:41:00 41\n",
"14443 2019-01-22 00:42:00 42\n",
"14444 2019-01-22 00:48:00 48\n",
"14445 2019-01-22 00:55:00 55\n",
"\n",
"[14444 rows x 2 columns]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def extract_trans_time(row):\n",
" trans_date_time = row['trans_date_trans_time']\n",
" return trans_date_time.hour * 60 + trans_date_time.minute\n",
"trans_time = data.apply(extract_trans_time, axis=1)\n",
"data[['trans_date_trans_time']].assign(trans_time=trans_time)"
]
},
{
"cell_type": "markdown",
"id": "b30668e6-4c42-4785-b689-26d34a2e03de",
"metadata": {},
"source": [
"Looks good, add to the data."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "3acdc473-4670-4a00-b829-f184e4fb9f17",
"metadata": {},
"outputs": [],
"source": [
"data = data.drop('trans_time', axis='columns', errors='ignore') # remove just in case the cell is executed again \n",
"data.insert(data.shape[1] - 1, 'trans_time', trans_time)"
]
},
{
"cell_type": "markdown",
"id": "9d0b2d4d-03fa-47cf-a1a1-c9544c72c54b",
"metadata": {},
"source": [
"Drop irrelevant columns."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "30e5a982-cd5d-483f-907d-54febc5db95b",
"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>merchant</th>\n",
" <th>category</th>\n",
" <th>amt</th>\n",
" <th>city</th>\n",
" <th>state</th>\n",
" <th>lat</th>\n",
" <th>long</th>\n",
" <th>city_pop</th>\n",
" <th>job</th>\n",
" <th>merch_lat</th>\n",
" <th>merch_long</th>\n",
" <th>age</th>\n",
" <th>trans_time</th>\n",
" <th>is_fraud</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Stokes, Christiansen and Sipes</td>\n",
" <td>grocery_net</td>\n",
" <td>14.37</td>\n",
" <td>Wales</td>\n",
" <td>AK</td>\n",
" <td>64.7556</td>\n",
" <td>-165.6723</td>\n",
" <td>145</td>\n",
" <td>Administrator, education</td>\n",
" <td>65.654142</td>\n",
" <td>-164.722603</td>\n",
" <td>79.208219</td>\n",
" <td>58</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Predovic Inc</td>\n",
" <td>shopping_net</td>\n",
" <td>966.11</td>\n",
" <td>Wales</td>\n",
" <td>AK</td>\n",
" <td>64.7556</td>\n",
" <td>-165.6723</td>\n",
" <td>145</td>\n",
" <td>Administrator, education</td>\n",
" <td>65.468863</td>\n",
" <td>-165.473127</td>\n",
" <td>79.208219</td>\n",
" <td>906</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Wisozk and Sons</td>\n",
" <td>misc_pos</td>\n",
" <td>49.61</td>\n",
" <td>Wales</td>\n",
" <td>AK</td>\n",
" <td>64.7556</td>\n",
" <td>-165.6723</td>\n",
" <td>145</td>\n",
" <td>Administrator, education</td>\n",
" <td>65.347667</td>\n",
" <td>-165.914542</td>\n",
" <td>79.208219</td>\n",
" <td>1357</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Murray-Smitham</td>\n",
" <td>grocery_pos</td>\n",
" <td>295.26</td>\n",
" <td>Wales</td>\n",
" <td>AK</td>\n",
" <td>64.7556</td>\n",
" <td>-165.6723</td>\n",
" <td>145</td>\n",
" <td>Administrator, education</td>\n",
" <td>64.445035</td>\n",
" <td>-166.080207</td>\n",
" <td>79.208219</td>\n",
" <td>1386</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Friesen Lt</td>\n",
" <td>health_fitness</td>\n",
" <td>18.17</td>\n",
" <td>Wales</td>\n",
" <td>AK</td>\n",
" <td>64.7556</td>\n",
" <td>-165.6723</td>\n",
" <td>145</td>\n",
" <td>Administrator, education</td>\n",
" <td>65.447094</td>\n",
" <td>-165.446843</td>\n",
" <td>79.208219</td>\n",
" <td>1439</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14441</th>\n",
" <td>Hudson-Grady</td>\n",
" <td>shopping_pos</td>\n",
" <td>122.00</td>\n",
" <td>Athena</td>\n",
" <td>OR</td>\n",
" <td>45.8289</td>\n",
" <td>-118.4971</td>\n",
" <td>1302</td>\n",
" <td>Dealer</td>\n",
" <td>46.442439</td>\n",
" <td>-118.524214</td>\n",
" <td>42.290411</td>\n",
" <td>37</td>\n",
" <td>False</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14442</th>\n",
" <td>Nienow, Ankunding and Collie</td>\n",
" <td>misc_pos</td>\n",
" <td>9.07</td>\n",
" <td>Gardiner</td>\n",
" <td>OR</td>\n",
" <td>43.7857</td>\n",
" <td>-124.1437</td>\n",
" <td>260</td>\n",
" <td>Engineer, maintenance</td>\n",
" <td>42.901265</td>\n",
" <td>-124.995317</td>\n",
" <td>62.432877</td>\n",
" <td>41</td>\n",
" <td>False</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14443</th>\n",
" <td>Pacocha-O'Reilly</td>\n",
" <td>grocery_pos</td>\n",
" <td>104.84</td>\n",
" <td>Alva</td>\n",
" <td>WY</td>\n",
" <td>44.6873</td>\n",
" <td>-104.4414</td>\n",
" <td>110</td>\n",
" <td>Administrator, local government</td>\n",
" <td>45.538062</td>\n",
" <td>-104.542117</td>\n",
" <td>45.717808</td>\n",
" <td>42</td>\n",
" <td>False</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14444</th>\n",
" <td>Bins, Balistreri and Beatty</td>\n",
" <td>shopping_pos</td>\n",
" <td>268.16</td>\n",
" <td>Wales</td>\n",
" <td>AK</td>\n",
" <td>64.7556</td>\n",
" <td>-165.6723</td>\n",
" <td>145</td>\n",
" <td>Administrator, education</td>\n",
" <td>64.081462</td>\n",
" <td>-165.898698</td>\n",
" <td>79.257534</td>\n",
" <td>48</td>\n",
" <td>False</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14445</th>\n",
" <td>Daugherty-Thompson</td>\n",
" <td>food_dining</td>\n",
" <td>50.09</td>\n",
" <td>Unionville</td>\n",
" <td>MO</td>\n",
" <td>40.4815</td>\n",
" <td>-92.9951</td>\n",
" <td>3805</td>\n",
" <td>Investment banker, corporate</td>\n",
" <td>40.387243</td>\n",
" <td>-92.224871</td>\n",
" <td>68.400000</td>\n",
" <td>55</td>\n",
" <td>False</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>14444 rows × 14 columns</p>\n",
"</div>"
],
"text/plain": [
" merchant category amt city \\\n",
"0 Stokes, Christiansen and Sipes grocery_net 14.37 Wales \n",
"1 Predovic Inc shopping_net 966.11 Wales \n",
"2 Wisozk and Sons misc_pos 49.61 Wales \n",
"3 Murray-Smitham grocery_pos 295.26 Wales \n",
"4 Friesen Lt health_fitness 18.17 Wales \n",
"... ... ... ... ... \n",
"14441 Hudson-Grady shopping_pos 122.00 Athena \n",
"14442 Nienow, Ankunding and Collie misc_pos 9.07 Gardiner \n",
"14443 Pacocha-O'Reilly grocery_pos 104.84 Alva \n",
"14444 Bins, Balistreri and Beatty shopping_pos 268.16 Wales \n",
"14445 Daugherty-Thompson food_dining 50.09 Unionville \n",
"\n",
" state lat long city_pop job \\\n",
"0 AK 64.7556 -165.6723 145 Administrator, education \n",
"1 AK 64.7556 -165.6723 145 Administrator, education \n",
"2 AK 64.7556 -165.6723 145 Administrator, education \n",
"3 AK 64.7556 -165.6723 145 Administrator, education \n",
"4 AK 64.7556 -165.6723 145 Administrator, education \n",
"... ... ... ... ... ... \n",
"14441 OR 45.8289 -118.4971 1302 Dealer \n",
"14442 OR 43.7857 -124.1437 260 Engineer, maintenance \n",
"14443 WY 44.6873 -104.4414 110 Administrator, local government \n",
"14444 AK 64.7556 -165.6723 145 Administrator, education \n",
"14445 MO 40.4815 -92.9951 3805 Investment banker, corporate \n",
"\n",
" merch_lat merch_long age trans_time is_fraud \n",
"0 65.654142 -164.722603 79.208219 58 True \n",
"1 65.468863 -165.473127 79.208219 906 True \n",
"2 65.347667 -165.914542 79.208219 1357 True \n",
"3 64.445035 -166.080207 79.208219 1386 True \n",
"4 65.447094 -165.446843 79.208219 1439 True \n",
"... ... ... ... ... ... \n",
"14441 46.442439 -118.524214 42.290411 37 False \n",
"14442 42.901265 -124.995317 62.432877 41 False \n",
"14443 45.538062 -104.542117 45.717808 42 False \n",
"14444 64.081462 -165.898698 79.257534 48 False \n",
"14445 40.387243 -92.224871 68.400000 55 False \n",
"\n",
"[14444 rows x 14 columns]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = data.drop(['trans_date_trans_time', 'dob'], axis='columns', errors='ignore') \n",
"data"
]
},
{
"cell_type": "markdown",
"id": "d7f84860-41a2-494c-8f52-e3edce977d15",
"metadata": {},
"source": [
"We could also try:\n",
"- extracting more features from `trans_date_trans_time`, e.g. day of the week\n",
"- encoding `lat` and `long` as a single feature where lat and long would be rounded up so the values fall into the same area"
]
},
{
"cell_type": "markdown",
"id": "d33932e3-2dbf-4964-88a2-5ec88385aa8a",
"metadata": {},
"source": [
"Finally, visualise how strongly new variables are correlated with the fact that the transaction is fraudulent."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "e90144af-ed42-4415-ba2a-f81de56827a6",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<Axes: >"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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GA0ePNjva0OSZs2apc6dO6tjx46699575fF4mvW+CgsL1adPH11yySVKTEzUuHHjdOLECUmnfwKfk5OjY8eO+c5tBQUFzRqnOcaMGaM1a9boySef9I2/cOFCORwOvfzyy0pNTZXL5dIbb7yhvXv3asSIEYqLi1N0dLSuu+46vfrqq37bS0pK0qOPPqq77rpLMTEx6tKli55++mnf67W1tcrNzVXnzp0VGRmprl27avr06WetMykpSZJ06623yuFw+Ka/fOta/ZX/Rx99VHFxcWrfvr0efvhhnTp1Sg8++KAuvfRSXXnllXrmmWf8tv/RRx9p5MiRat++vS699FKNGDFC+/bta9Y+DQWv16vHHntM3bt3l8vlUpcuXfTII4/43brW1Hnj2WefVceOHVVTU+O3zVtuuUV33nnnWceu38d/+MMflJiYqKioKI0cOVLHjh3zq+/hhx/WlVdeKZfLpZSUFBUVFfler6/zueee06BBgxQZGanevXtrzZo1LbSHWocjR45o9OjR6tChg6KionTTTTfp/fff971ef3V39erVSk5OVnR0tL797W/rwIEDvmVOnTql+++/3/f/+qRJk5Sdnd0q73gx9ZxfXl6uESNGKDo6WrGxsRo5cqQqKyt9r9d/TS1evFhJSUlq166dfvSjH+n48eO+ZY4fP6477rhDl1xyiTp37qwnnngiJFffCTrNdPLkSbndbm3evFklJSVyOp269dZb5fV6fcvk5+frV7/6lbZu3ao2bdpo1KhRmjhxop588kmtXbtWe/bs0ZQpUySdvj1h5MiRvi/4AwcOaNCgQXa9vVbjTH2oqqrS8OHD1adPH23dulXTpk3TpEmT/NY/evSovvWtb6l///7avHmzioqKVFlZqZEjR9r0jszh8Xg0bdo07dixQ8uXL9e+fft8YSYxMVF/+ctfJEllZWU6cOCAnnzySRurPX8WLVqkTp06adOmTbrvvvt0zz336LbbbtOgQYO0detWZWRk6M4771R1dXXAx+eiRYsUERGhdevWad68efrkk0/0jW98Qy6XS6+99pq2bNmiu+66y++qxeuvv669e/fq9ddf16JFi7Rw4UItXLiwWe/J6XTqN7/5jXbu3KlFixbptdde08SJEyVJgwYN0pw5cxQbG+s7t02YMKHZ+y9YTz75pNLT0zV27Fjf+ImJiZKkyZMna8aMGdq1a5f69u2rEydO6Dvf+Y5KSkq0bds2ffvb39bw4cNVXl7ut83Zs2crLS1N27Zt07hx43TPPfeorKxMkvSb3/xGK1as0PPPP6+ysjItWbLEF1rO5K233pIkPfPMMzpw4IBvujGvvfaa9u/fr3/+858qLCxUfn6+br75ZnXo0EEbN27Uz372M/30pz/Vxx9/LOn012JmZqZiYmK0du1arVu3zvcN5oXy0+C8vDzNmDFDDz30kP71r39p6dKliouL81umqfPGbbfdprq6Oq1YscK37MGDB7Vy5UrdddddAY2/Z88ePf/88/r73/+uoqIiX2/rPfnkk5o9e7ZmzZqlt99+W5mZmfre977n9028JD344IP6xS9+oW3btik9PV3Dhw/Xp59+2tzd0uqMGTNGmzdv1ooVK7RhwwZZlqXvfOc7ft9QV1dXa9asWVq8eLH++c9/qry83O+cMHPmTC1ZskTPPPOM1q1bp6qqqga3dLYmpp3zvV6vRowYoc8++0xr1qxRcXGx/v3vfysrK8tvub1792r58uX6xz/+oX/84x9as2aNZsyY4Xvd7XZr3bp1WrFihYqLi7V27Vpt3bo16HrOykKLOHTokCXJeuedd6wPPvjAkmT98Y9/9L3+5z//2ZJklZSU+OZNnz7d6tGjh286OzvbGjFixPks2zhf7MNTTz1ldezY0frPf/7je33+/PmWJGvbtm2WZVnWtGnTrIyMDL9tfPTRR5Ykq6ys7HyWboQhQ4ZY48ePb/S1t956y5JkHT9+3LIsy3r99dctSdaRI0fOX4E2GzJkiPX1r3/dN33q1Cnrkksuse68807fvAMHDliSrA0bNgR0fA4ZMsTq37+/3zJ5eXnWV77yFau2trbROrKzs62uXbtap06d8s277bbbrKysrIDeR9euXa0nnniiyddfeOEFq2PHjr7pZ555xmrXrl1A2w6FLx+X9cfe8uXLz7ruNddcY/32t7/1TXft2tX68Y9/7Jv2er3W5Zdfbj311FOWZVnWfffdZ33rW9+yvF5v0HVKsv72t7/5zcvPz7f69evnm67vXV1dnW9ejx49rMGDB/um64+rP//5z5ZlWdbixYutHj16+NVUU1NjtW3b1lq9enXQdba0qqoqy+VyWfPnz2/wWv3/p/Xn7KbOG/fcc4910003+aZnz55tdevWLaA+5OfnW2FhYdbHH3/sm/fyyy9bTqfTOnDggGVZlnXFFVdYjzzyiN961113nTVu3Di/OmfMmOF73ePxWFdeeaU1c+bMs9bQmtV/fb333nuWJGvdunW+1w4fPmy1bdvWev755y3LOn0ukGTt2bPHt8zcuXOtuLg433RcXJz1+OOP+6ZPnTpldenSpVV+f2TiOf+VV16xwsLCrPLyct/rO3futCRZmzZtsizr9NdUVFSUVVVV5VvmwQcftAYOHGhZ1umv+fDwcOuFF17wvX706FErKiqqye8hmosrOs30/vvv6/bbb1e3bt0UGxvr+4ndF3/y17dvX9+/638y1adPH7959bfyoHnO1IeysjL17dtXkZGRvuUHDBjgt/6OHTv0+uuvKzo62venZ8+ektTgki+Cs2XLFg0fPlxdunRRTEyMhgwZIkkNfjp+sfnieSEsLEwdO3ZscF6QTv9EOtDjMzU11W+M7du3a/DgwQoPD2+yjmuuuUZhYWG+6c6dOzf7fPTqq6/qxhtvVEJCgmJiYnTnnXfq008/VXV1dbO2d76kpaX5TZ84cUITJkxQcnKy2rdvr+joaO3atavBMfvFHjocDsXHx/v23ZgxY7R9+3b16NFD999/v1555ZUWr/uaa66R0/n5f99xcXF+x1D9cVVf044dO7Rnzx7FxMT4jqNLL71U//3vfy+I89yuXbtUU1OjG2+8sdnbGDt2rF555RV98sknkk7fIjVmzBg5HI6A1u/SpYsSEhJ80+np6fJ6vSorK1NVVZX279+v66+/3m+d66+/Xrt27fKbl56e7vt3mzZtlJaW1mAZU+3atUtt2rTRwIEDffM6duyoHj16+O2DqKgoXXXVVb7pL557jh07psrKSr//q8PCwhqc41oT0875u3btUmJiou/KuCT16tVL7du39+tzUlKSYmJiGh3v3//+tzwej1+f27Vrpx49egRdz9nw6b5mGj58uLp27ar58+friiuukNfrVe/evf1uA/jiAVd/sv3yvC/e6obgBdKHMzlx4oSGDx+umTNnNnitc+fOLV3uRePkyZPKzMxUZmamlixZossuu0zl5eXKzMy8YG6VscuX/yNyOByNniu8Xm/Ax+cll1zi91rbtm2bVUdzzkf79u3TzTffrHvuuUePPPKILr30Ur3xxhu6++67VVtbq6ioqKC3eb58eb9NmDBBxcXFmjVrlrp37662bdvqhz/8YYNj9kz77tprr9UHH3ygl19+Wa+++qpGjhypoUOH6sUXX2yxus92DH25phMnTig1NVVLlixpsK3LLrusxepqrkCO17Pp37+/+vXrp2effVYZGRnauXOnVq5c2QLVoaU1dqxalmVTNaFn2jk/UOd7vKZwRacZPv30U5WVlelXv/qVbrzxRiUnJ+vIkSPnvN2IiAjV1dW1QIUXh7P1oUePHnrnnXf8PqD65fver732Wu3cuVNJSUnq3r27358vn0gQuN27d+vTTz/VjBkzNHjwYPXs2bPBT44iIiIkiWP+DJp7fPbt21dr165t9gdNg7FlyxZ5vV7Nnj1bX/va1/TVr35V+/fv91vG7nNboOOvW7dOY8aM0a233qo+ffooPj6+WR/Yj42NVVZWlubPn69ly5bpL3/5iz777LOzrhceHh6S/XTttdfq/fff1+WXX97gOGrXrl2Ljxesq6++Wm3btg3oMdpnOm/85Cc/0cKFC/XMM89o6NChfj9xPpvy8nK/4/bNN9+U0+lUjx49FBsbqyuuuELr1q3zW2fdunXq1auX37w333zT9+9Tp05py5YtSk5ODriO1iw5OVmnTp3Sxo0bffPq/5/+8n5qSrt27RQXF+f3f3VdXV1oPrtxAWoN5/zk5GR99NFH+uijj3zz/vWvf+no0aMB97lbt24KDw/36/OxY8f03nvvtXi9BJ1m6NChgzp27Kinn35ae/bs0WuvvSa3233O201KStLbb7+tsrIyHT58+LwcsK3Z2fowatQoeb1e/c///I927dql1atXa9asWZI+/wnKvffeq88++0y333673nrrLe3du1erV69WTk4O34Cfgy5duigiIkK//e1v9e9//1srVqzQtGnT/Jbp2rWrHA6H/vGPf+jQoUO+p3Thc809PnNzc1VVVaUf/ehH2rx5s95//30tXrzY94H5ltS9e3d5PB5frxcvXqx58+b5LZOUlKQTJ06opKREhw8fPu+3tCUlJWnjxo3at2+fDh8+3ORPFa+++mr99a9/1fbt27Vjxw7fOSQYhYWF+vOf/6zdu3frvffe0wsvvKD4+PiAfo9QUlKSSkpKVFFR0SI/PKt3xx13qFOnThoxYoTWrl2rDz74QKWlpbr//vt9DyywU2RkpCZNmqSJEyfq2Wef1d69e/Xmm2/qT3/6U4Nlz3TeGDVqlD7++GPNnz8/4IcQfLGG7Oxs7dixQ2vXrtX999+vkSNHKj4+XtLphwzMnDlTy5YtU1lZmSZPnqzt27dr/PjxftuZO3eu/va3v2n37t269957deTIkaBraa2uvvpqjRgxQmPHjtUbb7yhHTt26Mc//rESEhI0YsSIgLdz3333afr06XrppZdUVlam8ePH68iRIwHfhtiatYZz/tChQ9WnTx/dcccd2rp1qzZt2qTRo0dryJAhDW4HbkpMTIyys7P14IMP6vXXX9fOnTt19913y+l0tnifCTrN4HQ69dxzz2nLli3q3bu3fv7zn+vxxx8/5+2OHTtWPXr0UFpami677LIGPz2Cv7P1ITY2Vn//+9+1fft2paSk6Je//KXvKXf1n9up/yldXV2dMjIy1KdPHz3wwANq37693z3wCM5ll12mhQsX6oUXXlCvXr00Y8YMX8isl5CQoKlTp2ry5MmKi4tTbm6uTdVeuJp7fHbs2FGvvfaaTpw4oSFDhig1NVXz588/4/3bzdWvXz8VFhZq5syZ6t27t5YsWdLgccqDBg3Sz372M2VlZemyyy7TY4891uJ1nMmECRMUFhamXr16+W6jbExhYaE6dOigQYMGafjw4crMzNS1114b1FgxMTF67LHHlJaWpuuuu0779u3TqlWrAjqfzJ49W8XFxUpMTFT//v2DGvdMoqKi9M9//lNdunTR97//fSUnJ+vuu+/Wf//7X8XGxrbYOOfioYce0i9+8QtNmTJFycnJysrKavTzA2c6b7Rr104/+MEPFB0dHfSjiLt3767vf//7+s53vqOMjAz17dtXv//9732v33///XK73frFL36hPn36qKioSCtWrNDVV1/tt50ZM2ZoxowZ6tevn9544w2tWLFCnTp1Cm5ntGLPPPOMUlNTdfPNNys9PV2WZWnVqlVBnXsmTZqk22+/XaNHj1Z6erqio6OVmZnp93lbU7WGc77D4dBLL72kDh066Bvf+IaGDh2qbt26admyZUFtp7CwUOnp6br55ps1dOhQXX/99UpOTm7xPjssk2+MBL5kyZIlvt/p0RL3hQMALhw33nijrrnmGv3mN78JeJ2CggItX77c7/erBWvfvn36yle+om3btvn93iOcO6/Xq+TkZI0cObLBnQEwx8mTJ5WQkKDZs2fr7rvvbrHt8jACGO3ZZ59Vt27dlJCQoB07dmjSpEkaOXIkIQcADHLkyBGVlpaqtLTU70oMWp8PP/xQr7zyioYMGaKamhr97ne/0wcffKBRo0bZXRpa0LZt27R7924NGDBAx44d08MPPyxJQd3mGAiCDoxWUVGhKVOmqKKiQp07d9Ztt92mRx55xO6ygAvW2rVrddNNNzX5Op+lap4lS5bopz/9aaOvde3aVTt37jzPFZmlf//+OnLkiGbOnNngEbXXXHONPvzww0bX+8Mf/nA+ykMQnE6nFi5cqAkTJsiyLPXu3VuvvvrqRfNQh/PNznP+rFmzVFZWpoiICKWmpmrt2rUtfqsnt64BAHz+85//+H4XSWO6d+9+Hqsxx/Hjx1VZWdnoa+Hh4eratet5ruji8eGHHzb5cJ+4uDi/3/UBXGxMP+cTdAAAAAAYh8dKAQAAADAOQQcAAACAcQg6AAAAAIxD0AEAAABgHIIOAAAAAOMQdAAAAAAYh6ADAAAAwDj/H+n0m3dZBWS/AAAAAElFTkSuQmCC",
"text/plain": [
"<Figure size 1000x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=(10, 6))\n",
"data.corr(numeric_only=True)['is_fraud'].drop(['is_fraud']).sort_values(ascending = False).plot(kind='bar', grid=True, rot=0)"
]
},
{
"cell_type": "markdown",
"id": "a0c7702c-c176-460e-9d5e-2b5a2e841bf3",
"metadata": {},
"source": [
"## Balance the dataset\n",
"\n",
"Prepare train and test data."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "edd9c2f5-3faf-4f8e-9d16-dec5538c58c8",
"metadata": {},
"outputs": [],
"source": [
"train_data, test_data = sklearn.model_selection.train_test_split(data, random_state=random_state)\n",
"train_data_input = train_data.drop('is_fraud', axis='columns')\n",
"test_data_input = test_data.drop('is_fraud', axis='columns')\n",
"train_data_output = train_data['is_fraud']\n",
"test_data_output = test_data['is_fraud']"
]
},
{
"cell_type": "markdown",
"id": "b782191f-7929-4f40-9025-675191d72a01",
"metadata": {},
"source": [
"Since there are many fewer fraudulent transaction we oversample them to prepare balanced test dataset."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "7ec781d5-51e5-4ad7-ab68-5d3997dde8cf",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"is_fraud\n",
"False 9456\n",
"True 1377\n",
"Name: count, dtype: Int64"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Original.\n",
"train_data_output.value_counts()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "1e99c8ad-c3e0-4227-8215-385aa2616f7d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"is_fraud\n",
"False 9456\n",
"True 9456\n",
"Name: count, dtype: Int64"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"over_sampler = imblearn.over_sampling.RandomOverSampler(random_state=random_state)\n",
"train_data_input, train_data_output = over_sampler.fit_resample(train_data_input, train_data_output)\n",
"# Over sampled.\n",
"train_data_output.value_counts()"
]
},
{
"cell_type": "markdown",
"id": "9ad62bca-7432-41a3-8227-e7312c8b3dcb",
"metadata": {},
"source": [
"# Model training - second experiment"
]
},
{
"cell_type": "markdown",
"id": "ac4c9de5-8f7d-4d58-b3d1-c28bbd8f0aa5",
"metadata": {},
"source": [
"First, we can train the model using the same decision tree with the same parameters as in the first experiment and see if the accuracy improves."
]
},
{
"cell_type": "markdown",
"id": "d367bd24-620b-40c6-b464-532964d4ec35",
"metadata": {},
"source": [
"Train the decision tree classifier on the new preprocessed dataset."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "41d3dee4-d7cd-434a-b73b-ab6c4038fa8a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"For parameters: {'criterion': 'gini', 'min_impurity_decrease': 0.0}, accuracy: 0.6271263437784352, precision: 0.8323734485387088 and recall: 0.8332871780670175 was achieved\n",
"For parameters: {'criterion': 'gini', 'min_impurity_decrease': 0.05}, accuracy: 0.5, precision: 0.758071375035556 and recall: 0.8706729437828856 was achieved\n",
"For parameters: {'criterion': 'gini', 'min_impurity_decrease': 0.3}, accuracy: 0.5, precision: 0.758071375035556 and recall: 0.8706729437828856 was achieved\n",
"For parameters: {'criterion': 'entropy', 'min_impurity_decrease': 0.0}, accuracy: 0.6381936157924275, precision: 0.8373859087442732 and recall: 0.8382719468291332 was achieved\n",
"For parameters: {'criterion': 'entropy', 'min_impurity_decrease': 0.05}, accuracy: 0.5, precision: 0.758071375035556 and recall: 0.8706729437828856 was achieved\n",
"For parameters: {'criterion': 'entropy', 'min_impurity_decrease': 0.3}, accuracy: 0.5, precision: 0.758071375035556 and recall: 0.8706729437828856 was achieved\n"
]
}
],
"source": [
"parameter_grid = {\n",
" 'criterion': ['gini', 'entropy'],\n",
" 'min_impurity_decrease': [0.0, 0.05, 0.3]\n",
"}\n",
"\n",
"mlflow.set_experiment(\"Credit card fraud - decision tree and preprocessed dataset\")\n",
"for parameters in sklearn.model_selection.ParameterGrid(parameter_grid):\n",
" criterion = parameters['criterion']\n",
" min_impurity_decrease = parameters['min_impurity_decrease']\n",
"\n",
" # For each parameter combination, we record a new run within a single experiment. \n",
" with mlflow.start_run():\n",
" clr = sklearn.pipeline.make_pipeline(\n",
" sklearn.compose.make_column_transformer(\n",
" (sklearn.preprocessing.OneHotEncoder(sparse_output=True), ['merchant', 'category', 'city', 'state', 'job']),\n",
" ),\n",
" sklearn.tree.DecisionTreeClassifier(criterion=criterion, min_impurity_decrease=min_impurity_decrease, random_state=random_state)\n",
" )\n",
" \n",
" clr.fit(train_data_input, train_data_output)\n",
" test_data_predicted = clr.predict(test_data_input)\n",
" \n",
" accuracy = sklearn.metrics.balanced_accuracy_score(test_data_output, test_data_predicted)\n",
" precision = sklearn.metrics.precision_score(test_data_output, test_data_predicted, average='weighted')\n",
" recall = sklearn.metrics.recall_score(test_data_output, test_data_predicted, average='weighted')\n",
"\n",
" print(f\"For parameters: {parameters}, accuracy: {accuracy}, precision: {precision} and recall: {recall} was achieved\")\n",
"\n",
" # Log all the classifier parameters.\n",
" mlflow.log_param(\"criterion\", criterion)\n",
" mlflow.log_param(\"min_impurity_decrease\", min_impurity_decrease)\n",
" # Log metrics of the trained classifer.\n",
" mlflow.log_metric(\"accuracy\", accuracy)\n",
" mlflow.log_metric(\"precision\", precision)\n",
" mlflow.log_metric(\"recall\", recall)\n",
" # And log the trained classifier itself.\n",
" model_signature = mlflow.models.infer_signature(model_input=train_data_input.iloc[:1], model_output=test_data_predicted[:1])\n",
" model_signature.outputs = mlflow.types.schema.Schema([mlflow.types.schema.ColSpec(\"double\")])\n",
" mlflow.sklearn.log_model(clr, artifact_path=f\"credit-card-fraud-tree-v2\", signature=model_signature)"
]
},
{
"cell_type": "markdown",
"id": "041d96e1-781b-405c-b1c9-9e3be8361de4",
"metadata": {},
"source": [
"Well, we can see that the metrics has not improved. Perhaps this is because the extracted features are not highly correlated with the fact that the transaction is fraudulent."
]
},
{
"cell_type": "markdown",
"id": "eb56490c-a1c2-48ff-ab16-187eb223572a",
"metadata": {},
"source": [
"# Model training - third experiment"
]
},
{
"cell_type": "markdown",
"id": "9a49f5cb-93d9-4062-8b7a-4bf1ee98d7fb",
"metadata": {},
"source": [
"This time we will use a different algorithm - a classifier based on support vector machines (SVMs) method."
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "d4ca530b-7824-4461-93cf-81018281aa89",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"For parameters: {'kernel': 'rbf', 'nu': 0.0005}, accuracy: 0.5135086170728651, precision: 0.7811636255218812 and recall: 0.48463029631680976 was achieved\n",
"For parameters: {'kernel': 'rbf', 'nu': 0.002}, accuracy: 0.5501873661670236, precision: 0.7946433158611632 and recall: 0.6056494045970645 was achieved\n",
"For parameters: {'kernel': 'rbf', 'nu': 0.01}, accuracy: 0.6217481651601092, precision: 0.823948954784356 and recall: 0.7953475491553587 was achieved\n",
"For parameters: {'kernel': 'rbf', 'nu': 0.1}, accuracy: 0.6040536067476339, precision: 0.850064804642781 and recall: 0.8756577125450014 was achieved\n",
"For parameters: {'kernel': 'rbf', 'nu': 0.2}, accuracy: 0.6138373762470646, precision: 0.8479969200478853 and recall: 0.8720576017723622 was achieved\n",
"For parameters: {'kernel': 'rbf', 'nu': 0.5}, accuracy: 0.6714757997286562, precision: 0.8428159779907852 and recall: 0.8089171974522293 was achieved\n",
"For parameters: {'kernel': 'rbf', 'nu': 0.9}, accuracy: 0.6489952651050777, precision: 0.8355923587441608 and recall: 0.6253115480476322 was achieved\n",
"For parameters: {'kernel': 'linear', 'nu': 0.0005}, accuracy: 0.4066785720123576, precision: 0.6994054459708862 and recall: 0.2763777346995292 was achieved\n",
"For parameters: {'kernel': 'linear', 'nu': 0.002}, accuracy: 0.4394594782352845, precision: 0.7323394091294531 and recall: 0.3223483799501523 was achieved\n",
"For parameters: {'kernel': 'linear', 'nu': 0.01}, accuracy: 0.3991035574371632, precision: 0.7080492661564639 and recall: 0.3187482691775131 was achieved\n",
"For parameters: {'kernel': 'linear', 'nu': 0.1}, accuracy: 0.42447903896344485, precision: 0.7183875511255063 and recall: 0.3010246469122127 was achieved\n",
"For parameters: {'kernel': 'linear', 'nu': 0.2}, accuracy: 0.40098947861669143, precision: 0.7065800469215918 and recall: 0.3093325948490722 was achieved\n",
"For parameters: {'kernel': 'linear', 'nu': 0.5}, accuracy: 0.6883527169796928, precision: 0.8463934043808079 and recall: 0.7144835225699252 was achieved\n",
"For parameters: {'kernel': 'linear', 'nu': 0.9}, accuracy: 0.7351326206471931, precision: 0.8651077799101538 and recall: 0.7197452229299363 was achieved\n"
]
}
],
"source": [
"parameter_grid = {\n",
" 'nu': [0.0005, 0.002, 0.01, 0.1, 0.2, 0.5, 0.9],\n",
" 'kernel': ['rbf', 'linear'],\n",
"}\n",
"\n",
"mlflow.set_experiment(\"Credit card fraud - SVM\")\n",
"for parameters in sklearn.model_selection.ParameterGrid(parameter_grid):\n",
" nu = parameters['nu']\n",
" kernel = parameters['kernel']\n",
"\n",
" # For each parameter combination, we record a new run within a single experiment.\n",
" with mlflow.start_run():\n",
" clr = sklearn.pipeline.make_pipeline(\n",
" sklearn.compose.make_column_transformer(\n",
" (sklearn.preprocessing.OneHotEncoder(sparse_output=True), ['merchant', 'category', 'city', 'state', 'job']),\n",
" ),\n",
" sklearn.preprocessing.StandardScaler(with_mean=False), # it is recommended to scale all features before training the SVM model\n",
" sklearn.svm.NuSVC(nu=nu, kernel=kernel, random_state=random_state)\n",
" )\n",
"\n",
" clr.fit(train_data_input, train_data_output)\n",
" test_data_predicted = clr.predict(test_data_input)\n",
"\n",
" accuracy = sklearn.metrics.balanced_accuracy_score(test_data_output, test_data_predicted)\n",
" precision = sklearn.metrics.precision_score(test_data_output, test_data_predicted, average='weighted')\n",
" recall = sklearn.metrics.recall_score(test_data_output, test_data_predicted, average='weighted')\n",
"\n",
" print(f\"For parameters: {parameters}, accuracy: {accuracy}, precision: {precision} and recall: {recall} was achieved\")\n",
"\n",
" # Log all the classifier parameters.\n",
" mlflow.log_param(\"nu\", nu)\n",
" mlflow.log_param(\"kernel\", kernel)\n",
" # Log metrics of the trained classifer.\n",
" mlflow.log_metric(\"accuracy\", accuracy)\n",
" mlflow.log_metric(\"precision\", precision)\n",
" mlflow.log_metric(\"recall\", recall)\n",
" # And log the trained classifier itself.\n",
" model_signature = mlflow.models.infer_signature(model_input=train_data_input.iloc[:1], model_output=test_data_predicted[:1])\n",
" model_signature.outputs = mlflow.types.schema.Schema([mlflow.types.schema.ColSpec(\"double\")])\n",
" mlflow.sklearn.log_model(clr, artifact_path=f\"credit-card-fraud-svm\", signature=model_signature)"
]
},
{
"cell_type": "markdown",
"id": "ea571801-2049-4627-992c-268fe94329a2",
"metadata": {},
"source": [
"The SVM algorithm achieved better metrics. Assume that precision is more important to us as we want to block transactions that appear fraudulent immediately to protect our customers. Log the best model in MLflow UI by comparing the runs."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "nu-ml-demo-20240523",
"language": "python",
"name": "nu-ml-demo-20240523"
},
"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.14"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment