{ "nbformat": 4, "nbformat_minor": 5, "metadata": { "name": "FDP_Student_Stress_Prediction", "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python", "version": "3.10.0" }, "accelerator": "CPU", "colab": { "provenance": [] } }, "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# ๐ŸŽ“ FDP: Student Stress Level Prediction\n", "## Data Science Pipeline โ€” Hands-on with Google Colab\n", "\n", "**Speaker:** Kapil Panwar | **Gyannetra Pvt Ltd**\n", "\n", "---\n", "### ๐Ÿ” What We'll Do Today:\n", "1. Load & explore a college student dataset\n", "2. Handle categorical data using **One-Hot Encoding** (including Favorite Colors! ๐ŸŒˆ)\n", "3. Train a Machine Learning model to predict student stress\n", "4. Evaluate how accurate our model is\n", "5. Interpret results\n", "\n", "> **No installation needed. Just press Shift+Enter on each cell!**" ] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 1: Import Libraries\n", "import pandas as pd\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.ensemble import RandomForestClassifier\n", "from sklearn.metrics import accuracy_score, classification_report, confusion_matrix\n", "\n", "print(\"โœ… All libraries loaded successfully!\")\n", "print(f\"pandas: {pd.__version__}\")\n", "print(f\"numpy: {np.__version__}\")" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Step 1: Load the Dataset ๐Ÿ“‚\n", "\n", "We're using a dataset of **300 college students**. It contains information about their department,\n", "attendance, favorite color, study habits, and whether they have high stress or not." ] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 2: Load Data\n", "# Option A: From GitHub (recommended)\n", "url = \"https://raw.githubusercontent.com/gnpl_admin/fdp-data-science-pipeline/main/fdp-colab-content/student_stress_data.csv\"\n", "\n", "# Option B: If you have the file locally (upload to Colab)\n", "# from google.colab import files\n", "# uploaded = files.upload()\n", "# df = pd.read_csv('student_stress_data.csv')\n", "\n", "df = pd.read_csv(url)\n", "print(f\"โœ… Dataset loaded! Shape: {df.shape[0]} rows ร— {df.shape[1]} columns\")\n", "df.head(10)" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ๐Ÿ“Š What does each column mean?\n", "\n", "| Column | Type | Description |\n", "|--------|------|-------------|\n", "| Student_ID | ID | Unique student identifier |\n", "| Department | Categorical | Science, Commerce, Arts, Engineering |\n", "| Attendance_Level | Categorical | Regular, Irregular, Borderline |\n", "| Favorite_Color | Categorical | Red, Blue, Green, Yellow, Purple, Orange |\n", "| Weekly_Study_Hours | Numerical | Hours studied per week (2-25) |\n", "| Assignment_Submission_Pct | Numerical | Assignment submission rate (40-100%) |\n", "| Backlogs_Count | Numerical | Number of pending backlogs (0-5) |\n", "| Stress_Level | **Target** | 0 = Low Stress, 1 = High Stress |" ] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 3: Explore Data Types & Missing Values\n", "print(\"๐Ÿ“‹ Data Info:\")\n", "print(\"-\" * 40)\n", "df.info()\n", "print()\n", "print(\"๐Ÿ“Š Missing values:\")\n", "print(df.isnull().sum())\n", "print()\n", "print(\"โœ… No missing values! Clean data.\")" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 4: Statistical Summary\n", "print(\"๐Ÿ“ˆ Statistical Summary (Numerical Columns):\")\n", "print(\"-\" * 40)\n", "df.describe()" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Step 2: Exploratory Data Analysis (EDA) ๐Ÿ”\n", "\n", "Let's understand our data before building a model." ] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 5: Target Distribution\n", "stress_counts = df['Stress_Level'].value_counts()\n", "print(\"๐ŸŽฏ Stress Level Distribution:\")\n", "print(f\"Low Stress (0): {stress_counts[0]} students\")\n", "print(f\"High Stress (1): {stress_counts[1]} students\")\n", "print()\n", "\n", "# Simple bar chart\n", "plt.figure(figsize=(6, 4))\n", "colors = ['#4CAF50', '#F44336']\n", "bars = plt.bar(['Low Stress (0)', 'High Stress (1)'], [stress_counts[0], stress_counts[1]], color=colors)\n", "plt.title('Student Stress Level Distribution', fontsize=14, fontweight='bold')\n", "plt.ylabel('Number of Students')\n", "for bar in bars:\n", " height = bar.get_height()\n", " plt.text(bar.get_x() + bar.get_width()/2, height, f'{int(height)}', ha='center', va='bottom')\n", "plt.show()" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 6: Favorite Color Distribution\n", "print(\"๐ŸŒˆ Favorite Color Distribution:\")\n", "color_counts = df['Favorite_Color'].value_counts()\n", "print(color_counts)\n", "print()\n", "\n", "# Bar chart with actual colors\n", "plt.figure(figsize=(8, 4))\n", "color_map = {'Red': '#FF0000', 'Blue': '#2196F3', 'Green': '#4CAF50',\n", " 'Yellow': '#FFEB3B', 'Purple': '#9C27B0', 'Orange': '#FF9800'}\n", "bar_colors = [color_map[c] for c in color_counts.index]\n", "bars = plt.bar(color_counts.index, color_counts.values, color=bar_colors, edgecolor='black', linewidth=0.5)\n", "plt.title('Favorite Color Distribution', fontsize=14, fontweight='bold')\n", "plt.ylabel('Number of Students')\n", "for bar in bars:\n", " height = bar.get_height()\n", " plt.text(bar.get_x() + bar.get_width()/2, height, f'{int(height)}', ha='center', va='bottom')\n", "plt.show()" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 7: Department vs Stress Level\n", "print(\"๐Ÿซ Stress by Department:\")\n", "dept_stress = pd.crosstab(df['Department'], df['Stress_Level'])\n", "print(dept_stress)\n", "print()\n", "\n", "# Stacked bar chart\n", "dept_stress.plot(kind='bar', stacked=True, color=['#4CAF50', '#F44336'], figsize=(8, 4))\n", "plt.title('Stress Level by Department', fontsize=14, fontweight='bold')\n", "plt.xlabel('Department')\n", "plt.ylabel('Number of Students')\n", "plt.legend(['Low Stress', 'High Stress'])\n", "plt.xticks(rotation=0)\n", "plt.show()" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Step 3: Feature Engineering โ€” One-Hot Encoding ๐Ÿ”„\n", "\n", "### ๐ŸŽฏ Why Do We Need This?\n", "\n", "Machine learning models understand **numbers**, not words like \"Red\" or \"Science\".\n", "But we can't just assign Red=1, Blue=2 because that implies an order (Blue > Red).\n", "\n", "### โœ… Solution: One-Hot Encoding\n", "\n", "Creates a separate column for each category with 0 or 1.\n", "\n", "**Example โ€” Favorite Color encoding:**\n", "\n", "| Original | Red | Blue | Green | Yellow | Purple | Orange |\n", "|----------|-----|------|-------|--------|--------|--------|\n", "| Red | 1 | 0 | 0 | 0 | 0 | 0 |\n", "| Blue | 0 | 1 | 0 | 0 | 0 | 0 |\n", "| Green | 0 | 0 | 1 | 0 | 0 | 0 |\n", "\n", "**Think of it like a light switch panel** โ€” each color has its own switch, exactly one is ON!" ] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 8: One-Hot Encode Categorical Columns\n", "print(\"๐Ÿ”„ Before One-Hot Encoding โ€” Categorical columns:\")\n", "print(df[['Department', 'Attendance_Level', 'Favorite_Color']].head())\n", "print()\n", "\n", "# Apply one-hot encoding\n", "categorical_cols = ['Department', 'Attendance_Level', 'Favorite_Color']\n", "df_encoded = pd.get_dummies(df, columns=categorical_cols, drop_first=False)\n", "\n", "print(f\"โœ… After encoding: {df_encoded.shape[1]} columns (was {df.shape[1]})\")\n", "print()\n", "\n", "# Show the new columns that start with 'Favorite_Color'\n", "color_cols = [c for c in df_encoded.columns if c.startswith('Favorite_Color')]\n", "print(f\"๐ŸŒˆ New one-hot columns for Favorite_Color ({len(color_cols)} total):\")\n", "print(color_cols)\n", "print()\n", "\n", "# Show a sample of the encoded color columns\n", "print(\"Sample of one-hot encoded colors:\")\n", "df_encoded[['Student_ID', 'Favorite_Color_Red', 'Favorite_Color_Blue', \n", " 'Favorite_Color_Green', 'Favorite_Color_Yellow',\n", " 'Favorite_Color_Purple', 'Favorite_Color_Orange']].head(10)" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 9: Visualize One-Hot Encoding\n", "print(\"๐ŸŽฏ Let's see which colors have more stressed students:\")\n", "\n", "# Create a cross-tabulation\n", "color_stress = pd.crosstab(df['Favorite_Color'], df['Stress_Level'])\n", "color_stress['Stress_Rate'] = (color_stress[1] / (color_stress[0] + color_stress[1]) * 100).round(1)\n", "color_stress = color_stress.sort_values('Stress_Rate', ascending=False)\n", "print(color_stress)\n", "print()\n", "\n", "# Bar chart\n", "plt.figure(figsize=(8, 4))\n", "ax = color_stress['Stress_Rate'].plot(kind='bar', color=['#FF0000', '#2196F3', '#4CAF50', '#FFEB3B', '#9C27B0', '#FF9800'],\n", " edgecolor='black', linewidth=0.5)\n", "plt.title('Stress Rate by Favorite Color', fontsize=14, fontweight='bold')\n", "plt.xlabel('Favorite Color')\n", "plt.ylabel('Stress Rate (%)')\n", "plt.xticks(rotation=0)\n", "for i, v in enumerate(color_stress['Stress_Rate']):\n", " plt.text(i, v + 0.5, f'{v}%', ha='center', fontweight='bold')\n", "plt.ylim(0, 100)\n", "plt.show()" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Step 4: Train a Machine Learning Model ๐Ÿค–\n", "\n", "We'll use a **Random Forest Classifier** โ€” it's like asking 100 mini-experts to vote, then taking the majority decision. Easy to understand and very powerful!" ] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 10: Prepare Features & Target\n", "# Drop Student_ID (not useful) and Stress_Level (our target)\n", "X = df_encoded.drop(['Student_ID', 'Stress_Level'], axis=1)\n", "y = df_encoded['Stress_Level']\n", "\n", "print(f\"Features (X): {X.shape[1]} columns, {X.shape[0]} rows\")\n", "print(f\"Target (y): {y.shape[0]} values\")\n", "print(f\"\\nFeature columns: {list(X.columns)[:10]}... (+ {len(X.columns)-10} more)\")\n", "print(f\"\\nTarget distribution:\\n{y.value_counts().to_string()}\")" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 11: Split Data into Train & Test\n", "X_train, X_test, y_train, y_test = train_test_split(\n", " X, y, test_size=0.3, random_state=42, stratify=y\n", ")\n", "\n", "print(f\"๐Ÿ“š Training set: {X_train.shape[0]} students ({X_train.shape[0]/len(df)*100:.0f}%)\")\n", "print(f\"๐Ÿงช Test set: {X_test.shape[0]} students ({X_test.shape[0]/len(df)*100:.0f}%)\")\n", "print()\n", "print(\"โœ… Training target distribution:\")\n", "print(y_train.value_counts().to_string())\n", "print()\n", "print(\"โœ… Test target distribution:\")\n", "print(y_test.value_counts().to_string())" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 12: Train Random Forest Model\n", "model = RandomForestClassifier(n_estimators=100, random_state=42)\n", "model.fit(X_train, y_train)\n", "\n", "print(\"๐ŸŒฒโœ… Model trained successfully!\")\n", "print(f\"Using {model.n_estimators} decision trees\")" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Step 5: Evaluate the Model ๐Ÿ“Š" ] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 13: Make Predictions\n", "y_pred = model.predict(X_test)\n", "accuracy = accuracy_score(y_test, y_pred)\n", "\n", "print(f\"๐ŸŽฏ Model Accuracy: {accuracy*100:.1f}%\")\n", "print()\n", "print(\"๐Ÿ“‹ Classification Report:\")\n", "print(classification_report(y_test, y_pred, target_names=['Low Stress', 'High Stress']))" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 14: Confusion Matrix\n", "cm = confusion_matrix(y_test, y_pred)\n", "\n", "plt.figure(figsize=(6, 5))\n", "sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', \n", " xticklabels=['Low Stress', 'High Stress'],\n", " yticklabels=['Low Stress', 'High Stress'])\n", "plt.title('Confusion Matrix', fontsize=14, fontweight='bold')\n", "plt.xlabel('Predicted')\n", "plt.ylabel('Actual')\n", "plt.show()\n", "\n", "print(\"๐Ÿ“Š Confusion Matrix Breakdown:\")\n", "print(f\"โœ… True Low Stress: {cm[0][0]} students correctly predicted\")\n", "print(f\"โŒ False High Stress: {cm[0][1]} low-stress students predicted as high\")\n", "print(f\"โŒ False Low Stress: {cm[1][0]} high-stress students predicted as low\")\n", "print(f\"โœ… True High Stress: {cm[1][1]} students correctly predicted\")" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Step 6: Feature Importance ๐Ÿ”‘\n", "\n", "What factors most influence student stress? Let's find out!" ] }, { "cell_type": "code", "metadata": {}, "source": [ "# Cell 15: Feature Importance\n", "importance = pd.DataFrame({\n", " 'Feature': X.columns,\n", " 'Importance': model.feature_importances_\n", "}).sort_values('Importance', ascending=False)\n", "\n", "print(\"๐Ÿ”‘ Top 10 Most Important Factors:\")\n", "print(\"-\" * 40)\n", "for i, row in importance.head(10).iterrows():\n", " bar = 'โ–ˆ' * int(row['Importance'] * 50)\n", " print(f\"{row['Feature']:40s} {bar} {row['Importance']*100:.1f}%\")\n", "print()\n", "\n", "# Plot top 10\n", "plt.figure(figsize=(10, 6))\n", "top10 = importance.head(10)\n", "bars = plt.barh(range(len(top10)), top10['Importance'].values, color='#8ab4f8')\n", "plt.yticks(range(len(top10)), top10['Feature'].values)\n", "plt.xlabel('Importance Score')\n", "plt.title('Top 10 Features Influencing Student Stress', fontsize=14, fontweight='bold')\n", "plt.gca().invert_yaxis()\n", "for i, v in enumerate(top10['Importance']):\n", " plt.text(v + 0.005, i, f'{v*100:.1f}%', va='center', fontweight='bold')\n", "plt.tight_layout()\n", "plt.show()" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## ๐ŸŽฏ Summary โ€” What We Learned Today\n", "\n", "| Step | What We Did | Key Takeaway |\n", "|------|-------------|--------------|\n", "| 1 | Loaded data | CSV files are the standard format |\n", "| 2 | EDA | Visualized patterns before modeling |\n", "| 3 | **One-Hot Encoding** | Converted colors (Red/Blue/Green) to numbers ๐Ÿ“Œ |\n", "| 4 | Trained model | Random Forest โ€” simple yet powerful |\n", "| 5 | Evaluated | Measured accuracy & confusion matrix |\n", "| 6 | Interpreted | Found most influential factors |\n", "\n", "### ๐Ÿ“Œ Key Concept: One-Hot Encoding\n", "- Categorical data (like **Favorite Color**) cannot directly go into ML models\n", "- One-hot encoding creates **separate 0/1 columns** for each category\n", "- In pandas: pd.get_dummies(df['Favorite_Color'])\n", "- Think of it as a **light switch panel** โ€” one switch per color!\n", "\n", "---\n", "### ๐Ÿ™ Thank You!\n", "\n", "**Kapil Panwar** \n", "Gyannetra Pvt Ltd, Pune, Maharashtra \n", "*India's Premier AI Consultancy*" ] } ] }