228 lines
5.3 KiB
Plaintext
228 lines
5.3 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ce4d0249",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Module 3 — Lab 1: Security Features and Binary Labels\n",
|
|
"\n",
|
|
" \n",
|
|
"**Topics:** samples, features, labels, class distribution\n",
|
|
"\n",
|
|
"> **Solution version:** This notebook contains the complete solution. Run the cells in order and compare the results with your Lab notebook.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c70b2987",
|
|
"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": "dd82f5a2",
|
|
"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": "6345844b",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 1. Load and inspect the flow table\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "b8d885cb",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"df = pd.read_csv(DATA_PATH)\n",
|
|
"\n",
|
|
"print(\"Shape:\", df.shape)\n",
|
|
"df.head()\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "19535e33",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 2. Identify the label and numeric features\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "f87f05f8",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"y_text = df[\"Label\"].astype(str).str.strip()\n",
|
|
"X = df.drop(columns=\"Label\").select_dtypes(include=\"number\")\n",
|
|
"\n",
|
|
"print(\"Feature matrix shape:\", X.shape)\n",
|
|
"print(\"Original labels:\")\n",
|
|
"print(y_text.value_counts())\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "59f3f674",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 3. Create a binary security target\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "b4d0c24e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"normalized_labels = y_text.str.strip().str.upper()\n",
|
|
"y_binary = normalized_labels.ne(\"BENIGN\").astype(int)\n",
|
|
"class_counts = y_binary.value_counts().sort_index()\n",
|
|
"\n",
|
|
"print(class_counts.rename(index={0: \"BENIGN\", 1: \"ATTACK\"}))\n",
|
|
"print(\"Attack rate:\", round(y_binary.mean(), 3))\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "28d40643",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 4. Connect rows to feature vectors\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "b0506346",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"sample_index = 0\n",
|
|
"sample_features = X.iloc[sample_index]\n",
|
|
"sample_target = int(y_binary.iloc[sample_index])\n",
|
|
"\n",
|
|
"print(\"Selected feature vector:\")\n",
|
|
"print(sample_features)\n",
|
|
"print(\"Binary target:\", sample_target)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "3d4855d6",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Self-check\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "4159047f",
|
|
"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": "a66bcc4e",
|
|
"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"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "5b4575cc-2166-474b-bd0e-b49d94d1cfc2",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "5d03b205-5584-41c8-baaf-272b32bdf0b2",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "3ecfa6b2-cb34-45cc-98b4-5417f48f9f82",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "40ddd666-9f13-46bd-8a58-45bef952bfa2",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"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
|
|
}
|