{ "cells": [ { "cell_type": "markdown", "id": "2eb3034b", "metadata": {}, "source": [ "# Module 3 — Lab 3: A Random Forest Security Pipeline\n", "\n", "**Topics:** Scikit-learn Pipeline, imputation, Random Forest, fit, predict\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": "7bf6c5fd", "metadata": {}, "source": [ "## Learning objectives\n", "\n", "After completing this lab, you will be able to:\n", "\n", "- create one reusable preprocessing-and-model pipeline;\n", "- train a Random Forest binary classifier;\n", "- generate predictions for unseen data;\n", "- explain why tree models do not require feature standardization.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "c98b721f", "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "import numpy as np\n", "import pandas as pd\n", "\n", "DATA_PATH = Path(\"data/cicids2017_binary_sample.csv\")\n", "RANDOM_STATE = 42\n", "\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.pipeline import Pipeline\n", "from sklearn.impute import SimpleImputer\n", "from sklearn.ensemble import RandomForestClassifier\n" ] }, { "cell_type": "markdown", "id": "3888c4bb", "metadata": {}, "source": [ "## 1. Prepare the binary classification data\n" ] }, { "cell_type": "code", "execution_count": null, "id": "b4c28e44", "metadata": {}, "outputs": [], "source": [ "df = pd.read_csv(DATA_PATH)\n", "df.columns = df.columns.str.strip()\n", "df = df.drop_duplicates().replace([np.inf, -np.inf], np.nan)\n", "\n", "# TODO 1: create numeric X and binary y\n", "X = None\n", "y = None\n", "\n", "# TODO 2: create a stratified 80/20 split\n", "X_train, X_test, y_train, y_test = None, None, None, None\n" ] }, { "cell_type": "markdown", "id": "6aad53d0", "metadata": {}, "source": [ "## 2. Build one pipeline\n" ] }, { "cell_type": "code", "execution_count": null, "id": "e6c00af0", "metadata": {}, "outputs": [], "source": [ "# TODO 3: create a Pipeline with:\n", "# - SimpleImputer(strategy=\"median\")\n", "# - RandomForestClassifier with n_estimators=100, max_depth=12,\n", "# random_state=42, and n_jobs=-1\n", "pipeline = None\n", "\n", "print(pipeline)\n" ] }, { "cell_type": "markdown", "id": "c2111199", "metadata": {}, "source": [ "## Why there is no `StandardScaler`\n", "\n", "Random Forest makes decisions by comparing feature values with thresholds. Scaling a column does not change the ordering of its values, so standardization is not required for this model family. The imputer remains inside the pipeline because the model needs finite values.\n" ] }, { "cell_type": "markdown", "id": "16aa1030", "metadata": {}, "source": [ "## 3. Train and predict\n" ] }, { "cell_type": "code", "execution_count": null, "id": "59b48b8d", "metadata": {}, "outputs": [], "source": [ "# TODO 4: fit the complete pipeline on X_train and y_train\n", "\n", "# TODO 5: predict labels for X_test and store them in y_pred\n", "y_pred = None\n", "\n", "print(\"Predictions:\", None)\n", "print(\"Number of test samples:\", None)\n" ] }, { "cell_type": "markdown", "id": "c0c83354", "metadata": {}, "source": [ "## 4. Predict one flow\n" ] }, { "cell_type": "code", "execution_count": null, "id": "e1910ac4", "metadata": {}, "outputs": [], "source": [ "one_flow = X_test.iloc[[0]]\n", "\n", "# TODO 6: predict one_flow and convert the result to int\n", "one_prediction = None\n", "\n", "print(\"Prediction:\", one_prediction)\n", "print(\"Meaning:\", \"ATTACK\" if one_prediction == 1 else \"BENIGN\")\n" ] }, { "cell_type": "markdown", "id": "a7cdf396", "metadata": {}, "source": [ "## Self-check\n" ] }, { "cell_type": "code", "execution_count": null, "id": "926ba101", "metadata": {}, "outputs": [], "source": [ "assert list(pipeline.named_steps) == [\"imputer\", \"model\"]\n", "assert pipeline.named_steps[\"model\"].n_estimators == 100\n", "assert len(y_pred) == len(y_test)\n", "assert set(np.unique(y_pred)).issubset({0, 1})\n", "assert one_prediction in {0, 1}\n", "print(\"✓ Lab 3 completed\")\n" ] }, { "cell_type": "markdown", "id": "7beedd77", "metadata": {}, "source": [ "## Reflection questions\n", "\n", "1. What problem does the imputer solve inside the pipeline?\n", "2. Why is a pipeline safer than manually transforming train and test data in separate cells?\n", "3. What does `random_state=42` contribute to the experiment?\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 }