{ "cells": [ { "cell_type": "markdown", "id": "03d77301", "metadata": {}, "source": [ "# Module 2 — Lab 4: NumPy for Security Metrics\n", "\n", "\n", "**Topics:** array, vectorization, statistics, boolean mask\n", "\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": "33cb0ba1", "metadata": {}, "source": [ "## Scenario\n", "\n", "A network sensor reports packet sizes, latency, and failed authentication attempts for each time window. We use NumPy to calculate efficiently across the entire array.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "d7d3de72", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "packet_sizes = np.array([64, 128, 1500, 512, 1514, 256, 1400, 80])\n", "latency_ms = np.array([12.5, 18.0, 250.0, 33.5, 180.0, 25.0, 95.0, 10.0])\n", "failed_attempts = np.array([0, 1, 8, 2, 10, 1, 6, 0])\n", "\n", "print(packet_sizes.shape, packet_sizes.dtype)\n" ] }, { "cell_type": "markdown", "id": "5d225bd1", "metadata": { "tags": [ "exercise" ] }, "source": [ "## 1. Unit conversion and descriptive statistics\n" ] }, { "cell_type": "code", "execution_count": null, "id": "3da57f45", "metadata": { "tags": [ "solution" ] }, "outputs": [], "source": [ "packet_kb = packet_sizes / 1024\n", "mean_latency = latency_ms.mean()\n", "p95_latency = np.percentile(latency_ms, 95)\n", "\n", "print(\"Packet sizes (KB):\", np.round(packet_kb, 3))\n", "print(f\"Mean latency: {mean_latency:.2f} ms\")\n", "print(f\"P95 latency: {p95_latency:.2f} ms\")\n" ] }, { "cell_type": "markdown", "id": "dddbd812", "metadata": { "tags": [ "exercise" ] }, "source": [ "## 2. Filter with a Boolean mask\n" ] }, { "cell_type": "code", "execution_count": null, "id": "d24785c0", "metadata": { "tags": [ "solution" ] }, "outputs": [], "source": [ "suspicious_mask = (packet_sizes > 1400) | (latency_ms > 150) | (failed_attempts >= 8)\n", "suspicious_indices = np.where(suspicious_mask)[0]\n", "\n", "print(\"Mask:\", suspicious_mask)\n", "print(\"Suspicious indices:\", suspicious_indices)\n", "print(\"Suspicious packet sizes:\", packet_sizes[suspicious_mask])\n" ] }, { "cell_type": "markdown", "id": "ce903e91", "metadata": { "tags": [ "exercise" ] }, "source": [ "## 3. Normalize values and create a risk score\n" ] }, { "cell_type": "code", "execution_count": null, "id": "dcece1eb", "metadata": { "tags": [ "solution" ] }, "outputs": [], "source": [ "def min_max(values):\n", " values = np.asarray(values, dtype=float)\n", " value_range = values.max() - values.min()\n", " if value_range == 0:\n", " return np.zeros_like(values)\n", " return (values - values.min()) / value_range\n", "\n", "\n", "latency_score = min_max(latency_ms)\n", "failure_score = min_max(failed_attempts)\n", "risk_score = 0.4 * latency_score + 0.6 * failure_score\n", "\n", "print(\"Risk scores:\", np.round(risk_score, 3))\n", "print(\"Highest-risk index:\", int(np.argmax(risk_score)))\n" ] }, { "cell_type": "markdown", "id": "65a088f0", "metadata": {}, "source": [ "## Self-check\n" ] }, { "cell_type": "code", "execution_count": null, "id": "a730cc89", "metadata": {}, "outputs": [], "source": [ "assert packet_sizes.shape == (8,)\n", "assert np.isclose(mean_latency, 78.0)\n", "assert suspicious_indices.tolist() == [2, 4]\n", "assert int(np.argmax(risk_score)) == 4\n", "assert np.all((risk_score >= 0) & (risk_score <= 1))\n", "print(\"✓ Lab 4 completed\")\n" ] }, { "cell_type": "markdown", "id": "2c85c6e5", "metadata": {}, "source": [ "## Extension challenge\n", "\n", "Change the weights assigned to latency and failed attempts. Observe whether the highest-risk element changes and explain why.\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 }