Skip to content

Commit 9bb4a06

Browse files
committed
chore: add anomaly detection Jupyter notebook
1 parent 6e3235b commit 9bb4a06

File tree

1 file changed

+30
-27
lines changed

1 file changed

+30
-27
lines changed

jupyter/anomaly_detection_creditcard.ipynb

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
"Thus, you can run this notebook from either of the Azure AI Machine Learning web console, or locally, assuming that you've created and activated the [Python virtual environment](https://realpython.com/python-virtual-environments-a-primer/) provided in the course [GitHub repository](https://github.com/FullStackWithLawrence/azureml-example) for Python 3.9\n",
2121
"\n",
2222
"\n",
23-
"## Step 1: import the PyPi packages\n"
23+
"## Workflow\n",
24+
"\n",
25+
"### Step 1: import the PyPi packages\n"
2426
]
2527
},
2628
{
@@ -43,27 +45,27 @@
4345
"cell_type": "markdown",
4446
"metadata": {},
4547
"source": [
46-
"## Step 2: Load the Credit Card Fraud Dataset from Azure ML\n",
48+
"### Step 2: Load the Credit Card Fraud Dataset from Azure ML\n",
4749
"\n",
4850
"Retrieve the dataset from our existing workspace, and set this up for use with Pandas.\n",
4951
"\n",
5052
"**IMPORTANT: be mindful of the size of the dataset that you're working with. For example, if you run this notebook locally then be aware that you're downloading around 150Mib from your Azure workspace. When running locally this snippet will take approximately 4 minutes to run.**\n",
5153
"\n",
52-
"### What This Code Does\n",
54+
"#### What This Code Does\n",
5355
"\n",
5456
"- **`Workspace.from_config()`** connects to your Azure ML workspace using the `config.json` file (you should already have this if you followed earlier lectures).\n",
5557
"- **`Dataset.get_by_name(...)`** loads the dataset you previously uploaded and registered in the Azure ML web interface.\n",
5658
"- **`.to_pandas_dataframe()`** converts the Azure Dataset into a standard pandas DataFrame so you can explore and manipulate it with Python.\n",
5759
"- **`df.head()`** shows the first 5 rows of the data — this is just a quick preview to confirm that the dataset loaded correctly.\n",
5860
"\n",
59-
"### Why This Matters\n",
61+
"#### Why This Matters\n",
6062
"\n",
6163
"This is the standard pattern you’ll use throughout Azure ML when working with registered datasets in notebooks. It keeps your workflow consistent and lets you:\n",
6264
"- Avoid re-uploading data every time.\n",
6365
"- Ensure reproducibility across experiments and pipelines.\n",
6466
"- Easily switch to remote compute environments without changing your code.\n",
6567
"\n",
66-
"### Console output\n",
68+
"#### Console output\n",
6769
"\n",
6870
"You might (probably) see a few console output messages. This is expected. They come from Azure’s background systems for logging and monitoring. \n",
6971
"Unless you see an actual `ERROR` or `Traceback`, you can **safely ignore** any of the following.\n",
@@ -338,11 +340,11 @@
338340
"cell_type": "markdown",
339341
"metadata": {},
340342
"source": [
341-
"## Step 3: Prepare the Data\n",
343+
"### Step 3: Prepare the Data\n",
342344
"\n",
343345
"we're going to normalize the distribution of the transaction $ amount column, which helps the model treat transaction amounts on the same scale as the other features (which are already normalized).\n",
344346
"\n",
345-
"### What This Code Does\n",
347+
"#### What This Code Does\n",
346348
"\n",
347349
"- **Standardizes the `Amount` column**: \n",
348350
" We scale the `Amount` feature so that it has a mean of 0 and a standard deviation of 1. \n",
@@ -353,7 +355,7 @@
353355
"\n",
354356
"- We also drop the `Time` column since it doesn't contribute meaningfully to anomaly detection in this context.\n",
355357
"\n",
356-
"### Why This Matters\n",
358+
"#### Why This Matters\n",
357359
"\n",
358360
"Many machine learning algorithms — including Isolation Forest — perform better when numeric features are on a similar scale. \n",
359361
"Also, splitting the data into `X` and `y` is a standard step that prepares it for training and evaluation."
@@ -374,7 +376,7 @@
374376
"cell_type": "markdown",
375377
"metadata": {},
376378
"source": [
377-
"## Train the model\n",
379+
"### Step 4: Train the model\n",
378380
"\n",
379381
"The **Isolation Forest** algorithm is a popular unsupervised method for **detecting anomalies** in high-dimensional datasets. Instead of learning what “normal” looks like, it works by **isolating outliers** — rare points that are easier to separate from the rest of the data. It does this by randomly splitting the dataset using decision trees and measuring how quickly a data point can be isolated. The idea is that **anomalies require fewer splits to isolate**, because they are different from everything else. Isolation Forest is widely used in **fraud detection**, **network security**, and **industrial monitoring** because it is **fast, efficient**, and handles **large datasets** with many features. In our code, we set the `contamination` parameter to roughly match the known fraction of fraud cases in the dataset."
380382
]
@@ -406,30 +408,25 @@
406408
"| **F1-Score** | A balance between precision and recall — like a combined performance score |\n",
407409
"| **Support** | The number of examples in each group (normal or fraud) in the real data |\n",
408410
"\n",
409-
"### Results Summary\n",
411+
"#### Results Summary\n",
410412
"\n",
411413
"| Class | Description | Precision | Recall | F1-Score | Support |\n",
412414
"|-------|------------------------|-----------|--------|----------|---------|\n",
413415
"| `0` | Normal transactions | **1.00** | **1.00** | **1.00** | 284,315 |\n",
414416
"| `1` | Fraudulent transactions| **0.29** | **0.28** | **0.28** | 492 |\n",
415417
"\n",
416-
"### Interpretation (In Simple Terms)\n",
418+
"#### Interpretation (In Simple Terms)\n",
417419
"\n",
418420
"- The model is **excellent at recognizing normal transactions** — it almost never makes a mistake with those.\n",
419421
"- However, it **struggles to correctly catch fraud**:\n",
420422
" - When it says a transaction is fraud, it’s **only right 29% of the time**.\n",
421423
" - It **only finds 28% of the real fraud cases** — it misses most of them.\n",
422424
"\n",
423-
"### Overall Accuracy\n",
425+
"#### Overall Accuracy\n",
424426
"\n",
425427
"- The model is **99.9% accurate**, but this is misleading.\n",
426428
"- Because **fraud cases are very rare**, the model can look “perfect” just by saying everything is normal.\n",
427-
"- That’s why we look at **precision**, **recall**, and **F1-score** for a fuller picture.\n",
428-
"\n",
429-
"### Conclusion\n",
430-
"\n",
431-
"- Our model is great at recognizing normal behavior.\n",
432-
"- But we need to **improve how it detects fraud** — maybe by tuning parameters or using a different method like autoencoders or SMOTE (for balancing the data)."
429+
"- That’s why we look at **precision**, **recall**, and **F1-score** for a fuller picture.\n"
433430
]
434431
},
435432
{
@@ -458,13 +455,19 @@
458455
"print(classification_report(y, y_pred))"
459456
]
460457
},
458+
{
459+
"cell_type": "markdown",
460+
"metadata": {},
461+
"source": [
462+
"### Step 6 (Optional): Register the Model\n"
463+
]
464+
},
461465
{
462466
"cell_type": "code",
463467
"execution_count": null,
464468
"metadata": {},
465469
"outputs": [],
466470
"source": [
467-
"# Step 6 (Optional): Register the Model\n",
468471
"joblib.dump(model, 'isolation_forest.pkl')\n",
469472
"Model.register(model_path='isolation_forest.pkl',\n",
470473
" model_name='creditcard_if_model',\n",
@@ -484,14 +487,14 @@
484487
" - `1` means the model thinks the transaction is **fraud** or **anomalous**.\n",
485488
"- **Y-axis**: The total number of transactions in each category.\n",
486489
"\n",
487-
"### How to Interpret This Chart\n",
490+
"#### How to Interpret This Chart\n",
488491
"\n",
489492
"- You will (hopefully) see a **very tall bar for `0`** and a **very short bar for `1`**.\n",
490493
"- This is because **fraud is rare** in the dataset (only 492 out of 284,807 transactions).\n",
491494
"- The model is trained to detect outliers, so it **flags a small number of transactions as anomalies** (which is expected).\n",
492495
"- If the number of predicted frauds is **close to the actual number** (around 500), that’s a good sign that the model is well-calibrated.\n",
493496
"\n",
494-
"### Why This Matters\n",
497+
"#### Why This Matters\n",
495498
"\n",
496499
"- This simple chart gives a **quick health check** of how aggressive or conservative the model is in flagging anomalies.\n",
497500
"- If the model predicts **too many anomalies**, it might be overreacting.\n",
@@ -542,20 +545,20 @@
542545
" - `1` = predicted fraud/anomaly\n",
543546
"- **Y-axis**: The dollar **amount** of each transaction (standardized)\n",
544547
"\n",
545-
"### How to Interpret This Chart\n",
548+
"#### How to Interpret This Chart\n",
546549
"\n",
547550
"- Each box shows how transaction amounts are distributed for each prediction class.\n",
548551
"- The **line in the middle** of each box is the **median** transaction amount.\n",
549552
"- The **height of the box** shows where most transaction amounts fall.\n",
550553
"- **Dots outside the box** are **outliers** — unusual values far from the average.\n",
551554
"\n",
552-
"### What This Tells Us\n",
555+
"#### What This Tells Us\n",
553556
"\n",
554557
"- You may see that predicted frauds (`1`) tend to have **more extreme** or **variable amounts**.\n",
555558
"- This could suggest that the model is flagging **unusually high or low transaction amounts** as suspicious.\n",
556559
"- If the fraud predictions have a **much wider range**, it means the model may be reacting to extreme values — which is common in anomaly detection.\n",
557560
"\n",
558-
"### Usefulness\n",
561+
"#### Usefulness\n",
559562
"\n",
560563
"This chart helps you:\n",
561564
"- Understand what kinds of amounts the model thinks are suspicious.\n",
@@ -594,7 +597,7 @@
594597
"\n",
595598
"The beeswarm plot below is generated using **SHAP** (SHapley Additive exPlanations). It helps explain **which features influenced the model's decisions**, and **how strongly**. We only analyze the first 100 transactions here in order to keep the visualization fast and readable.\n",
596599
"\n",
597-
"### How to Read the SHAP Beeswarm Plot\n",
600+
"#### How to Read the SHAP Beeswarm Plot\n",
598601
"\n",
599602
"- **Each dot** represents a single transaction.\n",
600603
"- **Each row** is one feature (like `V1`, `V2`, `Amount`, etc.).\n",
@@ -605,14 +608,14 @@
605608
" - Dots farther to the right **push the model toward predicting fraud**.\n",
606609
" - Dots farther to the left **push the model toward predicting normal**.\n",
607610
"\n",
608-
"### What This Tells Us\n",
611+
"#### What This Tells Us\n",
609612
"\n",
610613
"- The **topmost features** are the most important ones in the model’s decisions.\n",
611614
"- For example, if `V14` is at the top and its red dots are far right, it means:\n",
612615
" - High values of `V14` increase the chance that the model flags a transaction as fraud.\n",
613616
"- This plot helps us understand **why** the model flagged certain transactions as anomalies.\n",
614617
"\n",
615-
"### Why Use SHAP?\n",
618+
"#### Why Use SHAP?\n",
616619
"\n",
617620
"- SHAP adds transparency to the model, even for complex algorithms like Isolation Forest.\n",
618621
"- Helps **build trust**, especially in sensitive tasks like fraud detection.\n",

0 commit comments

Comments
 (0)