205 lines
4.9 KiB
Plaintext
205 lines
4.9 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "578d1d03",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Module 3 — Lab 1: Security Features and Binary Labels\n",
|
|
" \n",
|
|
"**Topics:** samples, features, labels, class distribution\n",
|
|
"\n",
|
|
"> **Instructions:** Run the cells in order. Complete every `TODO`, then run the **Self-check** cell. Do not open the Solution notebook before attempting the tasks yourself.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "a79a9968",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Learning objectives\n",
|
|
"\n",
|
|
"After completing this lab, you will be able to:\n",
|
|
"\n",
|
|
"- identify samples, features, and labels in a security dataset;\n",
|
|
"- inspect the schema and data types of a network-flow table;\n",
|
|
"- convert multiple attack names into one binary target;\n",
|
|
"- explain why class distribution matters before model training.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "7981983b",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from pathlib import Path\n",
|
|
"import numpy as np\n",
|
|
"import pandas as pd\n",
|
|
"\n",
|
|
"DATA_PATH = Path(\"data/synthetic_security_flows.csv\")\n",
|
|
"RANDOM_STATE = 42\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "7b199e34",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 1. Load and inspect the flow table\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "7a13f6b9",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# TODO 1: load DATA_PATH into a DataFrame named df\n",
|
|
"df = None\n",
|
|
"\n",
|
|
"# TODO 2: display the first five rows\n",
|
|
"print(\"Shape:\", None)\n",
|
|
"df\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "8eed67bf",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 2. Identify the label and numeric features\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "509572c0",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# TODO 3: store the original label column in y_text\n",
|
|
"y_text = None\n",
|
|
"\n",
|
|
"# TODO 4: create X using only numeric columns and exclude Label\n",
|
|
"X = None\n",
|
|
"\n",
|
|
"print(\"Feature matrix shape:\", None)\n",
|
|
"print(\"Original labels:\")\n",
|
|
"print(None)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "a312a6cd",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 3. Create a binary security target\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "c24823de",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# BENIGN becomes 0. Every attack family becomes 1.\n",
|
|
"# TODO 5: normalize labels with strip() and upper(), then create y_binary\n",
|
|
"y_binary = None\n",
|
|
"\n",
|
|
"# TODO 6: calculate class_counts sorted by class index\n",
|
|
"class_counts = None\n",
|
|
"\n",
|
|
"print(class_counts)\n",
|
|
"print(\"Attack rate:\", None)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "123f407c",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 4. Connect rows to feature vectors\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "f85c4106",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"sample_index = 0\n",
|
|
"\n",
|
|
"# TODO 7: select one row from X as sample_features and its target as sample_target\n",
|
|
"sample_features = None\n",
|
|
"sample_target = None\n",
|
|
"\n",
|
|
"print(\"Selected feature vector:\")\n",
|
|
"print(sample_features)\n",
|
|
"print(\"Binary target:\", sample_target)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0d228da1",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Self-check\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "37f4f448",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"assert isinstance(df, pd.DataFrame)\n",
|
|
"assert \"Label\" not in X.columns\n",
|
|
"assert set(y_binary.unique()) == {0, 1}\n",
|
|
"assert len(X) == len(y_binary)\n",
|
|
"assert class_counts.loc[0] > class_counts.loc[1]\n",
|
|
"assert len(sample_features) == X.shape[1]\n",
|
|
"print(\"✓ Lab 1 completed\")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "499400fe",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Reflection questions\n",
|
|
"\n",
|
|
"1. Why is each row considered one sample while each column is considered one feature?\n",
|
|
"2. What information is lost when several attack families are mapped to one `ATTACK` class?\n",
|
|
"3. Why could high accuracy be misleading when `BENIGN` is the majority class?\n"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.11.6"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|