{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "ef003c425c914f079729b3d34cb796bb": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "TextModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "TextModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "TextView",
            "continuous_update": true,
            "description": "Text:",
            "description_tooltip": null,
            "disabled": false,
            "layout": "IPY_MODEL_bb671a6a50bf47019f1f4dd1d81626ed",
            "placeholder": "Enter a short social-media-style message...",
            "style": "IPY_MODEL_5e6430ae7eb6443bac91bfb496040d38",
            "value": "I feel completely useless and I just want to disappear."
          }
        },
        "bb671a6a50bf47019f1f4dd1d81626ed": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": "80%"
          }
        },
        "5e6430ae7eb6443bac91bfb496040d38": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "c3701de6e3424ecda35111fcdfbba229": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ButtonModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ButtonModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ButtonView",
            "button_style": "",
            "description": "Classify",
            "disabled": false,
            "icon": "",
            "layout": "IPY_MODEL_1442a77588894285a72372993edf936c",
            "style": "IPY_MODEL_7eaba2df78a641679b3f997cc58deac6",
            "tooltip": ""
          }
        },
        "1442a77588894285a72372993edf936c": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "7eaba2df78a641679b3f997cc58deac6": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ButtonStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ButtonStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "button_color": null,
            "font_weight": ""
          }
        },
        "bef778b2738744bebfb29f706f15c0ab": {
          "model_module": "@jupyter-widgets/output",
          "model_name": "OutputModel",
          "model_module_version": "1.0.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/output",
            "_model_module_version": "1.0.0",
            "_model_name": "OutputModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/output",
            "_view_module_version": "1.0.0",
            "_view_name": "OutputView",
            "layout": "IPY_MODEL_c3076368624544ec94a4950b89924006",
            "msg_id": "",
            "outputs": [
              {
                "output_type": "stream",
                "name": "stdout",
                "text": [
                  "Predicted categories (for triage, not automated enforcement):\n",
                  "\n",
                  "Emotion:\n",
                  "  predicted : Sadness (class 0)\n",
                  "  confidence: 0.990\n",
                  "\n",
                  "Violence / Abuse Risk:\n",
                  "  predicted : emotional_violence (class 3)\n",
                  "  confidence: 0.607\n",
                  "\n",
                  "Hate / Offensive Content:\n",
                  "  predicted : Neither (class 2)\n",
                  "  confidence: 0.740\n",
                  "\n",
                  "Note: These predictions are intended to assist human review of potentially high-risk content.\n",
                  "They are not a final moderation decision or a clinical assessment.\n",
                  "\n"
                ]
              }
            ]
          }
        },
        "c3076368624544ec94a4950b89924006": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        }
      }
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "# Multi-Task Learning for Safety-Relevant Text Classification\n",
        "**Research Portfolio – Rifky Setiawan, Universitas Gadjah Mada (UGM)**\n",
        "\n",
        "This notebook presents a multi-task neural classifier for safety-related text analysis.  \n",
        "The model jointly predicts:\n",
        "\n",
        "1. **Emotion state** (e.g., anger, fear, sadness),\n",
        "2. **Violence / abuse risk** (e.g., threat, self-harm intent, harmful behavior),\n",
        "3. **Hate / offensive content** (e.g., hate speech, harassment, abusive language).\n",
        "\n",
        "The goal is to prioritize high-risk content for human review.  \n",
        "The system is intended for triage and analysis support, not for automated enforcement.\n",
        "\n",
        "This notebook is submitted as part of a research internship application.\n"
      ],
      "metadata": {
        "id": "11zYC32G5z8a"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Abstract\n",
        "\n",
        "High-risk social media content (explicit threats, self-harm indications, hate speech) appears in large volume and is difficult to screen manually.  \n",
        "This work explores a practical multi-task approach in which a single shared text encoder feeds three task-specific heads:\n",
        "\n",
        "- emotion recognition,\n",
        "- violence / abuse risk assessment,\n",
        "- hate / offense detection.\n",
        "\n",
        "The pipeline includes:\n",
        "1. Dataset preparation and label normalization,\n",
        "2. Class rebalancing to reduce extreme skew,\n",
        "3. Text normalization and stopword filtering,\n",
        "4. Shared tokenization and sequence construction,\n",
        "5. Aligned multi-task subset construction,\n",
        "6. Joint supervised training of a multi-head model,\n",
        "7. Quantitative evaluation on a held-out validation split,\n",
        "8. Qualitative interactive inference using a small widget.\n",
        "\n",
        "\n",
        "The model is designed for analyst assistance.  \n",
        "It is not intended to autonomously moderate users or make final safety decisions.\n"
      ],
      "metadata": {
        "id": "oerT4h5A57fR"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 1. Problem Statement and Motivation\n",
        "\n",
        "Online platforms face two simultaneous challenges:\n",
        "- detecting emotionally escalated language (anger, fear, despair),\n",
        "- detecting explicit or implied risk (self-harm, threats, harassment, hateful targeting).\n",
        "\n",
        "These signals often co-occur in the same post. Training task-specific models in isolation can miss shared cues such as tone, intensity, or target.\n",
        "\n",
        "This notebook investigates a multi-task formulation:  \n",
        "a shared encoder (embedding + recurrent layer) learns general language features,  \n",
        "and three smaller classification heads specialize for each safety dimension.\n",
        "\n",
        "This approach:\n",
        "- encourages transfer of shared signal across tasks,\n",
        "- reduces deployment cost (one encoder instead of three),\n",
        "- allows joint inspection of emotional state and explicit harm signals.\n",
        "\n",
        "The intended use is analyst triage.  \n",
        "Outputs highlight content that may deserve human escalation.  \n",
        "Outputs are not final moderation or legal evidence.\n"
      ],
      "metadata": {
        "id": "14xsk_lb584K"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 2. Pipeline Overview\n",
        "\n",
        "The workflow in this notebook is structured as follows:\n",
        "\n",
        "1. **Setup and Imports**  \n",
        "   Core libraries are imported, reproducibility seeds are fixed, and Google Drive is mounted for dataset access.\n",
        "\n",
        "2. **Dataset Preparation and Label Normalization**  \n",
        "   Three task-specific datasets are loaded (emotion, violence / abuse, hate / offense).  \n",
        "   Columns are normalized to a common (`text`, `label`) schema.  \n",
        "   Severe class imbalance is reduced via controlled downsampling so that each class contributes similarly.\n",
        "\n",
        "3. **Train / Validation Split and Text Normalization**  \n",
        "   Each dataset is split into train and held-out validation subsets.  \n",
        "   Light normalization (lowercasing, stopword removal) is applied consistently.\n",
        "\n",
        "4. **Shared Tokenization and Sequence Construction**  \n",
        "   A single tokenizer is fit on all training text across tasks.  \n",
        "   Each sentence is converted into integer token IDs and padded/truncated to a fixed maximum length.\n",
        "\n",
        "5. **Aligned Multi-Task Subset Construction**  \n",
        "   Because each task has a different dataset size, a balanced “aligned” subset is built by sampling the same number of examples per task.  \n",
        "   This makes joint multi-head training feasible.\n",
        "\n",
        "6. **Multi-Task Model Architecture and Joint Training**  \n",
        "   A shared encoder (embedding + sequential layer) feeds three softmax heads (emotion, violence, hate).  \n",
        "   All heads are optimized together with `sparse_categorical_crossentropy`, and validation metrics are tracked per head.\n",
        "\n",
        "7. **Quantitative Evaluation on the Validation Split**  \n",
        "   Per-class precision, recall, and F1-score are reported, and confusion matrices are visualized.\n",
        "\n",
        "8. **Qualitative Interactive Inference**  \n",
        "   A simple inference widget runs the trained model on free-text input and returns predicted categories with confidence.\n",
        "\n",
        "9. **Responsible Use and Limitations**  \n",
        "   The model is positioned as a triage assistant for human review, not an automated moderation authority.\n"
      ],
      "metadata": {
        "id": "z2CrRHqi5_Vy"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 3. Setup and Imports\n",
        "\n",
        "This section performs the following:\n",
        "- imports required libraries,\n",
        "- defines a fixed random seed (`RANDOM_STATE`) for reproducibility,\n",
        "- mounts Google Drive (Colab runtime),\n",
        "- suppresses non-critical warnings for readability.\n",
        "\n",
        "Only this cell imports libraries.  \n",
        "Later cells reuse these imports and do not re-import modules, to keep the notebook presentation clean.\n"
      ],
      "metadata": {
        "id": "yjZ8e_KG6Aw6"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 3. Setup and Imports\n",
        "\n",
        "import warnings\n",
        "warnings.filterwarnings('ignore')\n",
        "\n",
        "# Numerical / data handling\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "import re\n",
        "import math\n",
        "\n",
        "# NLP preprocessing\n",
        "import nltk\n",
        "from nltk.corpus import stopwords\n",
        "\n",
        "# Tokenization / sequence formatting\n",
        "from tensorflow.keras.preprocessing.text import Tokenizer\n",
        "from tensorflow.keras.preprocessing.sequence import pad_sequences\n",
        "\n",
        "# Model / training (Keras / TensorFlow)\n",
        "import tensorflow as tf\n",
        "from tensorflow import keras\n",
        "from tensorflow.keras import layers\n",
        "\n",
        "# Evaluation utilities\n",
        "from sklearn.preprocessing import LabelEncoder\n",
        "from sklearn.model_selection import train_test_split\n",
        "from sklearn.metrics import classification_report, confusion_matrix\n",
        "\n",
        "# Visualization\n",
        "import matplotlib.pyplot as plt\n",
        "import seaborn as sns\n",
        "\n",
        "# Interactive demo\n",
        "import ipywidgets as widgets\n",
        "from IPython.display import display, clear_output\n",
        "\n",
        "# Reproducibility helper\n",
        "RANDOM_STATE = 42\n",
        "np.random.seed(RANDOM_STATE)\n",
        "tf.random.set_seed(RANDOM_STATE)\n",
        "\n",
        "# Colab Drive access (for dataset CSVs)\n",
        "from google.colab import drive\n",
        "drive.mount('/content/drive')"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "U_zB-XXg57Ka",
        "outputId": "180c0f18-1afd-4aca-d8da-92196b81f935"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Mounted at /content/drive\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 4. Data Preparation\n",
        "\n",
        "Three labeled datasets are used, one for each task:\n",
        "\n",
        "- **Emotion recognition**  \n",
        "  Each row contains a short post and an emotion label (e.g. anger, fear, sadness, joy).\n",
        "\n",
        "- **Violence / abuse risk**  \n",
        "  Each row is annotated for the presence of threat, self-harm intent, harassment, or related high-risk content.\n",
        "\n",
        "- **Hate / offensive content**  \n",
        "  Each row is annotated for hate speech or abusive/offensive language.\n",
        "\n",
        "To make training feasible on limited hardware, classes are downsampled toward the minority class size.  \n",
        "This prevents the model from collapsing to the majority label and keeps total training size manageable.\n",
        "\n",
        "After balancing:\n",
        "1. Column names are standardized to `text` and `label`.\n",
        "2. Labels are encoded as integer class IDs using `LabelEncoder`, so that each prediction head can be trained with `sparse_categorical_crossentropy`.\n",
        "\n",
        "The code below assumes that the original CSVs live under Google Drive.  \n",
        "The exact file paths are environment-dependent but should follow the schema \"text\" (free-form string) and \"label\" (categorical class for that task).\n"
      ],
      "metadata": {
        "id": "GHS92CN76G66"
      }
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "x-GiUFFm5k5i",
        "outputId": "1a54372a-08f0-49bd-9d0d-a62181eb6cfe"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Emotion classes: [np.int64(0), np.int64(1), np.int64(2), np.int64(3), np.int64(4), np.int64(5)]\n",
            "Violence / abuse classes: ['Harmful_Traditional_practice', 'Physical_violence', 'economic_violence', 'emotional_violence', 'sexual_violence']\n",
            "Hate / offensive classes: [np.int64(0), np.int64(1), np.int64(2)]\n",
            "\n",
            "Balanced sizes (after downsampling):\n",
            "Emotion: 89832\n",
            "Violence: 940\n",
            "Hate: 4290\n"
          ]
        }
      ],
      "source": [
        "# 4. Data Preparation (loading, balancing, encoding)\n",
        "\n",
        "# Paths to task-specific datasets on Drive.\n",
        "# Each CSV is expected to contain:\n",
        "# - a column with raw text (tweet / post / message),\n",
        "# - a column with the associated class label for that task.\n",
        "#\n",
        "# These paths reflect the current workspace layout.\n",
        "EMOTION_CSV_PATH  = \"/content/drive/MyDrive/Dataset/Dataset Multi-task NLP/emotions.csv\"\n",
        "VIOLENCE_CSV_PATH = \"/content/drive/MyDrive/Dataset/Dataset Multi-task NLP/violence.csv\"\n",
        "HATE_CSV_PATH     = \"/content/drive/MyDrive/Dataset/Dataset Multi-task NLP/hatespeech.csv\"\n",
        "\n",
        "\n",
        "def standardize_task_dataframe(df_raw: pd.DataFrame) -> pd.DataFrame:\n",
        "    \"\"\"\n",
        "    Normalize an annotated dataset into a common two-column schema:\n",
        "    'text' (string free-form content) and 'label' (categorical class).\n",
        "\n",
        "    The function attempts to infer which columns of the raw dataframe correspond\n",
        "    to the message text and which correspond to the label, based on common\n",
        "    column name patterns encountered in emotion / abuse / hate datasets.\n",
        "\n",
        "    This makes the pipeline robust to variations such as:\n",
        "    - 'text', 'tweet', 'content', 'post', ...\n",
        "    - 'label', 'class', 'category', 'type', ...\n",
        "\n",
        "    Returns\n",
        "    -------\n",
        "    df_std : pd.DataFrame with columns ['text', 'label'] and no missing rows.\n",
        "    \"\"\"\n",
        "\n",
        "    # Candidate column names for the raw text\n",
        "    text_candidates = [\n",
        "        \"text\", \"Text\",\n",
        "        \"tweet\", \"Tweet\",\n",
        "        \"content\", \"Content\",\n",
        "        \"post\", \"Post\",\n",
        "        \"sentence\", \"Sentence\",\n",
        "        \"comment\", \"Comment\",\n",
        "        \"message\", \"Message\"\n",
        "    ]\n",
        "\n",
        "    # Candidate column names for the categorical label\n",
        "    label_candidates = [\n",
        "        \"label\", \"Label\",\n",
        "        \"class\", \"Class\",\n",
        "        \"category\", \"Category\",\n",
        "        \"type\", \"Type\",               # <-- added to support violence.csv\n",
        "        \"hs_class\", \"hate_label\",\n",
        "        \"violence_label\", \"abusiveness\"\n",
        "    ]\n",
        "\n",
        "    text_col = None\n",
        "    for cand in text_candidates:\n",
        "        if cand in df_raw.columns:\n",
        "            text_col = cand\n",
        "            break\n",
        "\n",
        "    label_col = None\n",
        "    for cand in label_candidates:\n",
        "        if cand in df_raw.columns:\n",
        "            label_col = cand\n",
        "            break\n",
        "\n",
        "    if text_col is None or label_col is None:\n",
        "        raise ValueError(\n",
        "            \"Could not automatically infer text/label columns.\\n\"\n",
        "            f\"Available columns: {list(df_raw.columns)}\\n\"\n",
        "            f\"Inferred text_col={text_col}, label_col={label_col}\"\n",
        "        )\n",
        "\n",
        "    # Build standardized dataframe\n",
        "    df_std = df_raw[[text_col, label_col]].copy()\n",
        "    df_std.columns = [\"text\", \"label\"]\n",
        "\n",
        "    # Drop missing\n",
        "    df_std = df_std.dropna(subset=[\"text\", \"label\"]).reset_index(drop=True)\n",
        "    return df_std\n",
        "\n",
        "\n",
        "# Load raw CSVs\n",
        "emotion_raw  = pd.read_csv(EMOTION_CSV_PATH)\n",
        "violence_raw = pd.read_csv(VIOLENCE_CSV_PATH)\n",
        "hate_raw     = pd.read_csv(HATE_CSV_PATH)\n",
        "\n",
        "# Standardize to ['text', 'label']\n",
        "emotion_df  = standardize_task_dataframe(emotion_raw)\n",
        "violence_df = standardize_task_dataframe(violence_raw)\n",
        "hate_df     = standardize_task_dataframe(hate_raw)\n",
        "\n",
        "\n",
        "def balanced_downsample(\n",
        "    df: pd.DataFrame,\n",
        "    label_col: str = \"label\",\n",
        "    random_state: int = RANDOM_STATE\n",
        ") -> pd.DataFrame:\n",
        "    \"\"\"\n",
        "    Downsample each class to match the minority class size.\n",
        "\n",
        "    This has two goals:\n",
        "    (1) reduce class imbalance so the model does not trivially predict\n",
        "        the dominant class for every input,\n",
        "    (2) keep the overall training set size moderate so that training\n",
        "        remains feasible within limited runtime.\n",
        "\n",
        "    The result is then shuffled to avoid grouped-by-class ordering.\n",
        "    \"\"\"\n",
        "    counts = df[label_col].value_counts()\n",
        "    target_n = counts.min()\n",
        "\n",
        "    subsets = []\n",
        "    for cls_name in counts.index:\n",
        "        subset_cls = df[df[label_col] == cls_name]\n",
        "        subsets.append(\n",
        "            subset_cls.sample(\n",
        "                n=target_n,\n",
        "                random_state=random_state\n",
        "            )\n",
        "        )\n",
        "\n",
        "    df_bal = pd.concat(subsets, axis=0)\n",
        "    df_bal = df_bal.sample(frac=1.0, random_state=random_state).reset_index(drop=True)\n",
        "    return df_bal\n",
        "\n",
        "\n",
        "# Apply controlled downsampling per task\n",
        "emotion_df_bal  = balanced_downsample(emotion_df,  \"label\", RANDOM_STATE)\n",
        "violence_df_bal = balanced_downsample(violence_df, \"label\", RANDOM_STATE)\n",
        "hate_df_bal     = balanced_downsample(hate_df,     \"label\", RANDOM_STATE)\n",
        "\n",
        "# Encode categorical string labels -> integer class IDs for each task.\n",
        "# These encoders are saved for:\n",
        "# - model training (sparse_categorical_crossentropy),\n",
        "# - validation reporting (classification_report),\n",
        "# - inference demo (mapping back to human-readable labels).\n",
        "emotion_encoder  = LabelEncoder()\n",
        "violence_encoder = LabelEncoder()\n",
        "hate_encoder     = LabelEncoder()\n",
        "\n",
        "emotion_df_bal[\"label_id\"]  = emotion_encoder.fit_transform(emotion_df_bal[\"label\"])\n",
        "violence_df_bal[\"label_id\"] = violence_encoder.fit_transform(violence_df_bal[\"label\"])\n",
        "hate_df_bal[\"label_id\"]     = hate_encoder.fit_transform(hate_df_bal[\"label\"])\n",
        "\n",
        "# Store class name lists for later use (evaluation, confusion matrices, inference UI)\n",
        "emotion_classes  = list(emotion_encoder.classes_)\n",
        "violence_classes = list(violence_encoder.classes_)\n",
        "hate_classes     = list(hate_encoder.classes_)\n",
        "\n",
        "print(\"Emotion classes:\", emotion_classes)\n",
        "print(\"Violence / abuse classes:\", violence_classes)\n",
        "print(\"Hate / offensive classes:\", hate_classes)\n",
        "\n",
        "print(\"\\nBalanced sizes (after downsampling):\")\n",
        "print(\"Emotion:\",  len(emotion_df_bal))\n",
        "print(\"Violence:\", len(violence_df_bal))\n",
        "print(\"Hate:\",     len(hate_df_bal))"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 5. Train / Validation Split and Text Normalization\n",
        "\n",
        "After class balancing and label encoding, each task dataset is partitioned into:\n",
        "- a training split used for optimization,\n",
        "- a validation split held out for evaluation.\n",
        "\n",
        "A light text normalization step is then applied:\n",
        "1. Convert to lowercase,\n",
        "2. Remove punctuation-like artifacts,\n",
        "3. Remove standard English stopwords.\n",
        "\n",
        "The same normalization is re-used during inference to ensure consistency.\n",
        "\n",
        "Note: The split is stratified on the class label, so each class remains represented in both training and validation subsets.\n"
      ],
      "metadata": {
        "id": "fkqhXuL86Mfy"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 5. Split (train / validation) and text normalization\n",
        "\n",
        "# Stratified splits per task\n",
        "emo_train_df, emo_val_df = train_test_split(\n",
        "    emotion_df_bal,\n",
        "    test_size=0.2,\n",
        "    random_state=RANDOM_STATE,\n",
        "    stratify=emotion_df_bal['label_id']\n",
        ")\n",
        "\n",
        "vio_train_df, vio_val_df = train_test_split(\n",
        "    violence_df_bal,\n",
        "    test_size=0.2,\n",
        "    random_state=RANDOM_STATE,\n",
        "    stratify=violence_df_bal['label_id']\n",
        ")\n",
        "\n",
        "hate_train_df, hate_val_df = train_test_split(\n",
        "    hate_df_bal,\n",
        "    test_size=0.2,\n",
        "    random_state=RANDOM_STATE,\n",
        "    stratify=hate_df_bal['label_id']\n",
        ")\n",
        "\n",
        "# Download NLTK resources if not already available\n",
        "nltk.download('stopwords', quiet=True)\n",
        "nltk.download('punkt', quiet=True)\n",
        "# Some newer NLTK versions use punkt_tab internally; attempt a silent fetch\n",
        "try:\n",
        "    nltk.download('punkt_tab', quiet=True)\n",
        "except:\n",
        "    pass\n",
        "\n",
        "stop_words = set(stopwords.words('english'))\n",
        "\n",
        "def normalize_text(s: str) -> str:\n",
        "    \"\"\"\n",
        "    Basic normalization for social media text.\n",
        "\n",
        "    - Lowercase\n",
        "    - Remove non-alphanumeric punctuation-like runs\n",
        "    - Trim whitespace\n",
        "    \"\"\"\n",
        "    s = s.lower()\n",
        "    s = re.sub(r\"[^a-z0-9\\s]+\", \" \", s)\n",
        "    s = re.sub(r\"\\s+\", \" \", s).strip()\n",
        "    return s\n",
        "\n",
        "def remove_stopwords(s: str) -> str:\n",
        "    \"\"\"\n",
        "    Tokenize and remove common English stopwords. Falls back to regex split\n",
        "    if punkt tokenization is not available.\n",
        "    \"\"\"\n",
        "    try:\n",
        "        tokens = nltk.word_tokenize(s)\n",
        "    except LookupError:\n",
        "        tokens = re.split(r\"\\s+\", s)\n",
        "    filtered = [w for w in tokens if w not in stop_words]\n",
        "    return \" \".join(filtered)\n",
        "\n",
        "def preprocess_text_series(series: pd.Series) -> pd.Series:\n",
        "    \"\"\"Apply normalization + stopword removal at scale.\"\"\"\n",
        "    return series.apply(lambda t: remove_stopwords(normalize_text(t)))\n",
        "\n",
        "# Apply normalization to train/validation splits for each task\n",
        "emo_train_df['proc_text']  = preprocess_text_series(emo_train_df['text'])\n",
        "emo_val_df['proc_text']    = preprocess_text_series(emo_val_df['text'])\n",
        "\n",
        "vio_train_df['proc_text']  = preprocess_text_series(vio_train_df['text'])\n",
        "vio_val_df['proc_text']    = preprocess_text_series(vio_val_df['text'])\n",
        "\n",
        "hate_train_df['proc_text'] = preprocess_text_series(hate_train_df['text'])\n",
        "hate_val_df['proc_text']   = preprocess_text_series(hate_val_df['text'])\n",
        "\n",
        "print(\"Sample normalized text (emotion task):\")\n",
        "print(emo_train_df['proc_text'].head(3).tolist())"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "xoIFTfdM6NyS",
        "outputId": "ace86583-66c2-4018-bcf1-5daebcb07a00"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Sample normalized text (emotion task):\n",
            "['im sure get feeling shes point anger even something darker feel part vulnerable', 'agree feelings unimportant commitment', 'think thing makes feel insecure writer control work send world']\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 6. Tokenization and Sequence Construction\n",
        "\n",
        "A single tokenizer is fit on the union of all training text across tasks.  \n",
        "This enforces a shared vocabulary and allows the model to learn a single embedding space.\n",
        "\n",
        "Steps:\n",
        "1. Fit `Tokenizer` on all training `proc_text`,\n",
        "2. Convert each sample into a sequence of token IDs,\n",
        "3. Pad / truncate sequences to a fixed maximum length (`MAX_LEN = 50`).\n",
        "\n",
        "For each task, separate padded matrices are created for the training split and the validation split.  \n",
        "Corresponding label arrays (`*_y_train`, `*_y_val`) store the integer class IDs from `LabelEncoder`.\n"
      ],
      "metadata": {
        "id": "q5Zp6_ga6PGx"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 6. Tokenization and padded sequences\n",
        "\n",
        "# Fit a single tokenizer on *training* text only (to avoid validation leakage)\n",
        "tokenizer = Tokenizer()\n",
        "tokenizer.fit_on_texts(pd.concat([\n",
        "    emo_train_df['proc_text'],\n",
        "    vio_train_df['proc_text'],\n",
        "    hate_train_df['proc_text']\n",
        "], axis=0).tolist())\n",
        "\n",
        "MAX_LEN = 50\n",
        "\n",
        "def to_padded_sequences(text_series: pd.Series) -> np.ndarray:\n",
        "    \"\"\"Convert text to integer token IDs and pad/truncate to MAX_LEN.\"\"\"\n",
        "    seqs = tokenizer.texts_to_sequences(text_series.tolist())\n",
        "    return pad_sequences(seqs, maxlen=MAX_LEN, padding=\"post\", truncating=\"post\")\n",
        "\n",
        "# Emotion task\n",
        "emo_train_pad = to_padded_sequences(emo_train_df['proc_text'])\n",
        "emo_val_pad   = to_padded_sequences(emo_val_df['proc_text'])\n",
        "emo_y_train   = emo_train_df['label_id'].to_numpy()\n",
        "emo_y_val     = emo_val_df['label_id'].to_numpy()\n",
        "\n",
        "# Violence / abuse task\n",
        "vio_train_pad = to_padded_sequences(vio_train_df['proc_text'])\n",
        "vio_val_pad   = to_padded_sequences(vio_val_df['proc_text'])\n",
        "vio_y_train   = vio_train_df['label_id'].to_numpy()\n",
        "vio_y_val     = vio_val_df['label_id'].to_numpy()\n",
        "\n",
        "# Hate / offensive task\n",
        "hate_train_pad = to_padded_sequences(hate_train_df['proc_text'])\n",
        "hate_val_pad   = to_padded_sequences(hate_val_df['proc_text'])\n",
        "hate_y_train   = hate_train_df['label_id'].to_numpy()\n",
        "hate_y_val     = hate_val_df['label_id'].to_numpy()\n",
        "\n",
        "# Convenience dicts for model.fit and evaluation\n",
        "train_inputs = {\n",
        "    \"emotion_input\":  emo_train_pad,\n",
        "    \"violence_input\": vio_train_pad,\n",
        "    \"hate_input\":     hate_train_pad,\n",
        "}\n",
        "train_outputs = {\n",
        "    \"emotion_output\":  emo_y_train,\n",
        "    \"violence_output\": vio_y_train,\n",
        "    \"hate_output\":     hate_y_train,\n",
        "}\n",
        "\n",
        "val_inputs = {\n",
        "    \"emotion_input\":  emo_val_pad,\n",
        "    \"violence_input\": vio_val_pad,\n",
        "    \"hate_input\":     hate_val_pad,\n",
        "}\n",
        "val_outputs = {\n",
        "    \"emotion_output\":  emo_y_val,\n",
        "    \"violence_output\": vio_y_val,\n",
        "    \"hate_output\":     hate_y_val,\n",
        "}\n",
        "\n",
        "vocab_size = len(tokenizer.word_index) + 1\n",
        "print(\"Vocabulary size:\", vocab_size)\n",
        "print(\"Emotion train shape:\", emo_train_pad.shape)\n",
        "print(\"Violence train shape:\", vio_train_pad.shape)\n",
        "print(\"Hate train shape:\", hate_train_pad.shape)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Ws-rLwgK6QEK",
        "outputId": "6d6252f1-4680-4e05-9126-8a3ac4ba3fa8"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Vocabulary size: 38451\n",
            "Emotion train shape: (71865, 50)\n",
            "Violence train shape: (752, 50)\n",
            "Hate train shape: (3432, 50)\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 7. Multi-Task Model Architecture\n",
        "\n",
        "The classifier uses a shared text encoder followed by task-specific heads:\n",
        "\n",
        "1. **Shared encoder**  \n",
        "   - Input (token IDs) → Embedding layer  \n",
        "   - Bidirectional LSTM  \n",
        "   - Global max pooling and dropout\n",
        "\n",
        "   This encoder captures general linguistic and emotional cues that may apply to all safety tasks.\n",
        "\n",
        "2. **Task-specific heads**  \n",
        "   - A small dense layer + softmax for each task:\n",
        "     - Emotion category prediction  \n",
        "     - Violence / abuse risk prediction  \n",
        "     - Hate / offensive content prediction\n",
        "\n",
        "The loss is the sum of the per-head classification losses.  \n",
        "All heads are trained jointly so that the shared encoder receives gradient signals from all tasks.\n"
      ],
      "metadata": {
        "id": "cJstZPBz6RPj"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 7. Multi-task model definition\n",
        "\n",
        "# Clear any existing graph so layer names remain unique when re-running this cell\n",
        "tf.keras.backend.clear_session()\n",
        "\n",
        "EMBED_DIM    = 64\n",
        "LSTM_UNITS   = 64\n",
        "DROPOUT_RATE = 0.3\n",
        "\n",
        "# Inputs for each task (sequence of token IDs, same length constraint)\n",
        "emotion_input  = layers.Input(shape=(MAX_LEN,), name=\"emotion_input\")\n",
        "violence_input = layers.Input(shape=(MAX_LEN,), name=\"violence_input\")\n",
        "hate_input     = layers.Input(shape=(MAX_LEN,), name=\"hate_input\")\n",
        "\n",
        "# Shared text encoder:\n",
        "# - Embedding with mask_zero=True so padding tokens are ignored\n",
        "# - Bidirectional LSTM to capture context in both directions\n",
        "shared_embedding = layers.Embedding(\n",
        "    input_dim=vocab_size,\n",
        "    output_dim=EMBED_DIM,\n",
        "    mask_zero=True,\n",
        "    name=\"shared_embedding\"\n",
        ")\n",
        "\n",
        "shared_bilstm = layers.Bidirectional(\n",
        "    layers.LSTM(LSTM_UNITS, return_sequences=True),\n",
        "    name=\"shared_bilstm\"\n",
        ")\n",
        "\n",
        "def encode_branch(x, branch_name: str):\n",
        "    \"\"\"\n",
        "    Shared encoder forward pass for a given task branch.\n",
        "    The same embedding and BiLSTM are reused, then the branch\n",
        "    applies its own pooling + dropout.\n",
        "    \"\"\"\n",
        "    x = shared_embedding(x)\n",
        "    x = shared_bilstm(x)\n",
        "    x = layers.GlobalMaxPooling1D(name=f\"{branch_name}_pool\")(x)\n",
        "    x = layers.Dropout(DROPOUT_RATE, name=f\"{branch_name}_dropout\")(x)\n",
        "    return x\n",
        "\n",
        "# Extract task-specific representations from the shared encoder\n",
        "emo_feat  = encode_branch(emotion_input,  \"emotion\")\n",
        "vio_feat  = encode_branch(violence_input, \"violence\")\n",
        "hate_feat = encode_branch(hate_input,     \"hate\")\n",
        "\n",
        "# Task-specific classification heads (softmax over each task's label space)\n",
        "emotion_output = layers.Dense(\n",
        "    len(emotion_classes),\n",
        "    activation=\"softmax\",\n",
        "    name=\"emotion_output\"\n",
        ")(emo_feat)\n",
        "\n",
        "violence_output = layers.Dense(\n",
        "    len(violence_classes),\n",
        "    activation=\"softmax\",\n",
        "    name=\"violence_output\"\n",
        ")(vio_feat)\n",
        "\n",
        "hate_output = layers.Dense(\n",
        "    len(hate_classes),\n",
        "    activation=\"softmax\",\n",
        "    name=\"hate_output\"\n",
        ")(hate_feat)\n",
        "\n",
        "# Assemble the functional model\n",
        "model = keras.Model(\n",
        "    inputs=[emotion_input, violence_input, hate_input],\n",
        "    outputs=[emotion_output, violence_output, hate_output],\n",
        "    name=\"multitask_safety_model\"\n",
        ")\n",
        "\n",
        "# Joint training objective:\n",
        "# each head uses sparse_categorical_crossentropy with integer labels,\n",
        "# and accuracy is tracked separately per head.\n",
        "model.compile(\n",
        "    optimizer=keras.optimizers.Adam(learning_rate=1e-3),\n",
        "    loss={\n",
        "        \"emotion_output\":  \"sparse_categorical_crossentropy\",\n",
        "        \"violence_output\": \"sparse_categorical_crossentropy\",\n",
        "        \"hate_output\":     \"sparse_categorical_crossentropy\",\n",
        "    },\n",
        "    metrics={\n",
        "        \"emotion_output\":  [\"accuracy\"],\n",
        "        \"violence_output\": [\"accuracy\"],\n",
        "        \"hate_output\":     [\"accuracy\"],\n",
        "    },\n",
        ")\n",
        "\n",
        "model.summary()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000
        },
        "id": "nt5G1yUR6SeK",
        "outputId": "1379843c-2aec-49e9-84fc-be66d8304465"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1mModel: \"multitask_safety_model\"\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"multitask_safety_model\"</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n",
              "┃\u001b[1m \u001b[0m\u001b[1mLayer (type)       \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape     \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m   Param #\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mConnected to     \u001b[0m\u001b[1m \u001b[0m┃\n",
              "┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩\n",
              "│ emotion_input       │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m50\u001b[0m)        │          \u001b[38;5;34m0\u001b[0m │ -                 │\n",
              "│ (\u001b[38;5;33mInputLayer\u001b[0m)        │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ violence_input      │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m50\u001b[0m)        │          \u001b[38;5;34m0\u001b[0m │ -                 │\n",
              "│ (\u001b[38;5;33mInputLayer\u001b[0m)        │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ hate_input          │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m50\u001b[0m)        │          \u001b[38;5;34m0\u001b[0m │ -                 │\n",
              "│ (\u001b[38;5;33mInputLayer\u001b[0m)        │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ shared_embedding    │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m50\u001b[0m, \u001b[38;5;34m64\u001b[0m)    │  \u001b[38;5;34m2,460,864\u001b[0m │ emotion_input[\u001b[38;5;34m0\u001b[0m]… │\n",
              "│ (\u001b[38;5;33mEmbedding\u001b[0m)         │                   │            │ violence_input[\u001b[38;5;34m0\u001b[0m… │\n",
              "│                     │                   │            │ hate_input[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m]  │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ not_equal           │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m50\u001b[0m)        │          \u001b[38;5;34m0\u001b[0m │ emotion_input[\u001b[38;5;34m0\u001b[0m]… │\n",
              "│ (\u001b[38;5;33mNotEqual\u001b[0m)          │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ not_equal_1         │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m50\u001b[0m)        │          \u001b[38;5;34m0\u001b[0m │ violence_input[\u001b[38;5;34m0\u001b[0m… │\n",
              "│ (\u001b[38;5;33mNotEqual\u001b[0m)          │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ not_equal_2         │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m50\u001b[0m)        │          \u001b[38;5;34m0\u001b[0m │ hate_input[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m]  │\n",
              "│ (\u001b[38;5;33mNotEqual\u001b[0m)          │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ shared_bilstm       │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m50\u001b[0m, \u001b[38;5;34m128\u001b[0m)   │     \u001b[38;5;34m66,048\u001b[0m │ shared_embedding… │\n",
              "│ (\u001b[38;5;33mBidirectional\u001b[0m)     │                   │            │ not_equal[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m],  │\n",
              "│                     │                   │            │ shared_embedding… │\n",
              "│                     │                   │            │ not_equal_1[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m… │\n",
              "│                     │                   │            │ shared_embedding… │\n",
              "│                     │                   │            │ not_equal_2[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m] │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ emotion_pool        │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m128\u001b[0m)       │          \u001b[38;5;34m0\u001b[0m │ shared_bilstm[\u001b[38;5;34m0\u001b[0m]… │\n",
              "│ (\u001b[38;5;33mGlobalMaxPooling1…\u001b[0m │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ violence_pool       │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m128\u001b[0m)       │          \u001b[38;5;34m0\u001b[0m │ shared_bilstm[\u001b[38;5;34m1\u001b[0m]… │\n",
              "│ (\u001b[38;5;33mGlobalMaxPooling1…\u001b[0m │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ hate_pool           │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m128\u001b[0m)       │          \u001b[38;5;34m0\u001b[0m │ shared_bilstm[\u001b[38;5;34m2\u001b[0m]… │\n",
              "│ (\u001b[38;5;33mGlobalMaxPooling1…\u001b[0m │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ emotion_dropout     │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m128\u001b[0m)       │          \u001b[38;5;34m0\u001b[0m │ emotion_pool[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m…\u001b[0m │\n",
              "│ (\u001b[38;5;33mDropout\u001b[0m)           │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ violence_dropout    │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m128\u001b[0m)       │          \u001b[38;5;34m0\u001b[0m │ violence_pool[\u001b[38;5;34m0\u001b[0m]… │\n",
              "│ (\u001b[38;5;33mDropout\u001b[0m)           │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ hate_dropout        │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m128\u001b[0m)       │          \u001b[38;5;34m0\u001b[0m │ hate_pool[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m]   │\n",
              "│ (\u001b[38;5;33mDropout\u001b[0m)           │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ emotion_output      │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m6\u001b[0m)         │        \u001b[38;5;34m774\u001b[0m │ emotion_dropout[\u001b[38;5;34m…\u001b[0m │\n",
              "│ (\u001b[38;5;33mDense\u001b[0m)             │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ violence_output     │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m5\u001b[0m)         │        \u001b[38;5;34m645\u001b[0m │ violence_dropout… │\n",
              "│ (\u001b[38;5;33mDense\u001b[0m)             │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ hate_output (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m3\u001b[0m)         │        \u001b[38;5;34m387\u001b[0m │ hate_dropout[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m…\u001b[0m │\n",
              "└─────────────────────┴───────────────────┴────────────┴───────────────────┘\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n",
              "┃<span style=\"font-weight: bold\"> Layer (type)        </span>┃<span style=\"font-weight: bold\"> Output Shape      </span>┃<span style=\"font-weight: bold\">    Param # </span>┃<span style=\"font-weight: bold\"> Connected to      </span>┃\n",
              "┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩\n",
              "│ emotion_input       │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span>)        │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ -                 │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>)        │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ violence_input      │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span>)        │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ -                 │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>)        │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ hate_input          │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span>)        │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ -                 │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>)        │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ shared_embedding    │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">64</span>)    │  <span style=\"color: #00af00; text-decoration-color: #00af00\">2,460,864</span> │ emotion_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]… │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Embedding</span>)         │                   │            │ violence_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>… │\n",
              "│                     │                   │            │ hate_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]  │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ not_equal           │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span>)        │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ emotion_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]… │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">NotEqual</span>)          │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ not_equal_1         │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span>)        │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ violence_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>… │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">NotEqual</span>)          │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ not_equal_2         │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span>)        │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ hate_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]  │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">NotEqual</span>)          │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ shared_bilstm       │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>)   │     <span style=\"color: #00af00; text-decoration-color: #00af00\">66,048</span> │ shared_embedding… │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Bidirectional</span>)     │                   │            │ not_equal[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>],  │\n",
              "│                     │                   │            │ shared_embedding… │\n",
              "│                     │                   │            │ not_equal_1[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>… │\n",
              "│                     │                   │            │ shared_embedding… │\n",
              "│                     │                   │            │ not_equal_2[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>] │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ emotion_pool        │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>)       │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ shared_bilstm[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]… │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">GlobalMaxPooling1…</span> │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ violence_pool       │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>)       │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ shared_bilstm[<span style=\"color: #00af00; text-decoration-color: #00af00\">1</span>]… │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">GlobalMaxPooling1…</span> │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ hate_pool           │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>)       │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ shared_bilstm[<span style=\"color: #00af00; text-decoration-color: #00af00\">2</span>]… │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">GlobalMaxPooling1…</span> │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ emotion_dropout     │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>)       │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ emotion_pool[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">…</span> │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dropout</span>)           │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ violence_dropout    │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>)       │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ violence_pool[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]… │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dropout</span>)           │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ hate_dropout        │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>)       │          <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ hate_pool[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]   │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dropout</span>)           │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ emotion_output      │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">6</span>)         │        <span style=\"color: #00af00; text-decoration-color: #00af00\">774</span> │ emotion_dropout[<span style=\"color: #00af00; text-decoration-color: #00af00\">…</span> │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>)             │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ violence_output     │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">5</span>)         │        <span style=\"color: #00af00; text-decoration-color: #00af00\">645</span> │ violence_dropout… │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>)             │                   │            │                   │\n",
              "├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
              "│ hate_output (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">3</span>)         │        <span style=\"color: #00af00; text-decoration-color: #00af00\">387</span> │ hate_dropout[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">…</span> │\n",
              "└─────────────────────┴───────────────────┴────────────┴───────────────────┘\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m2,528,718\u001b[0m (9.65 MB)\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">2,528,718</span> (9.65 MB)\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m2,528,718\u001b[0m (9.65 MB)\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">2,528,718</span> (9.65 MB)\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> (0.00 B)\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 8. Aligned Multi-Task Subset Construction\n",
        "\n",
        "Each task (emotion, violence / abuse, hate / offense) originally has a different number of samples, which is incompatible with a single multi-output `model.fit()` call.\n",
        "\n",
        "To enable joint training:\n",
        "1. Count available samples for each task,\n",
        "2. Take the minimum count,\n",
        "3. Randomly sample that many rows from each task,\n",
        "4. Pack the result into parallel input/output dictionaries.\n",
        "\n",
        "This yields a balanced aligned subset where all heads see the same number of training examples. The remaining (larger) data can still be used later for task-specific fine-tuning."
      ],
      "metadata": {
        "id": "Oar_bIQlRRPA"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 8. Aligned Multi-Task Subset Construction (build & pack)\n",
        "\n",
        "rng = np.random.default_rng(RANDOM_STATE)\n",
        "\n",
        "def build_aligned_subset(pad_emo, y_emo,\n",
        "                         pad_vio, y_vio,\n",
        "                         pad_hate, y_hate):\n",
        "    \"\"\"\n",
        "    pad_emo:  [N_emo,  MAX_LEN]\n",
        "    y_emo:    [N_emo]\n",
        "    pad_vio:  [N_vio,  MAX_LEN]\n",
        "    y_vio:    [N_vio]\n",
        "    pad_hate: [N_hate, MAX_LEN]\n",
        "    y_hate:   [N_hate]\n",
        "\n",
        "    Returns a dictionary of aligned (same length) subsets for\n",
        "    emotion / violence / hate.\n",
        "    \"\"\"\n",
        "\n",
        "    n_emo  = pad_emo.shape[0]\n",
        "    n_vio  = pad_vio.shape[0]\n",
        "    n_hate = pad_hate.shape[0]\n",
        "\n",
        "    # ambil ukuran minimum agar semua head punya jumlah sampel sama\n",
        "    n_min = min(n_emo, n_vio, n_hate)\n",
        "\n",
        "    # ambil subset acak berukuran n_min dari tiap task secara independen\n",
        "    emo_idx  = rng.choice(n_emo,  size=n_min, replace=False)\n",
        "    vio_idx  = rng.choice(n_vio,  size=n_min, replace=False)\n",
        "    hate_idx = rng.choice(n_hate, size=n_min, replace=False)\n",
        "\n",
        "    aligned = {\n",
        "        \"emotion_input\":  pad_emo[emo_idx],\n",
        "        \"violence_input\": pad_vio[vio_idx],\n",
        "        \"hate_input\":     pad_hate[hate_idx],\n",
        "        \"emotion_y\":      y_emo[emo_idx],\n",
        "        \"violence_y\":     y_vio[vio_idx],\n",
        "        \"hate_y\":         y_hate[hate_idx],\n",
        "    }\n",
        "    return aligned\n",
        "\n",
        "# Build aligned train subset\n",
        "aligned_train = build_aligned_subset(\n",
        "    emo_train_pad, emo_y_train,\n",
        "    vio_train_pad, vio_y_train,\n",
        "    hate_train_pad, hate_y_train\n",
        ")\n",
        "\n",
        "# Build aligned validation subset\n",
        "aligned_val = build_aligned_subset(\n",
        "    emo_val_pad, emo_y_val,\n",
        "    vio_val_pad, vio_y_val,\n",
        "    hate_val_pad, hate_y_val\n",
        ")\n",
        "\n",
        "# Pack them in the format model.fit expects\n",
        "train_inputs_aligned = {\n",
        "    \"emotion_input\":  aligned_train[\"emotion_input\"],\n",
        "    \"violence_input\": aligned_train[\"violence_input\"],\n",
        "    \"hate_input\":     aligned_train[\"hate_input\"],\n",
        "}\n",
        "train_outputs_aligned = {\n",
        "    \"emotion_output\":  aligned_train[\"emotion_y\"],\n",
        "    \"violence_output\": aligned_train[\"violence_y\"],\n",
        "    \"hate_output\":     aligned_train[\"hate_y\"],\n",
        "}\n",
        "\n",
        "val_inputs_aligned = {\n",
        "    \"emotion_input\":  aligned_val[\"emotion_input\"],\n",
        "    \"violence_input\": aligned_val[\"violence_input\"],\n",
        "    \"hate_input\":     aligned_val[\"hate_input\"],\n",
        "}\n",
        "val_outputs_aligned = {\n",
        "    \"emotion_output\":  aligned_val[\"emotion_y\"],\n",
        "    \"violence_output\": aligned_val[\"violence_y\"],\n",
        "    \"hate_output\":     aligned_val[\"hate_y\"],\n",
        "}\n",
        "\n",
        "print(\"Aligned train size:\", train_inputs_aligned[\"emotion_input\"].shape[0])\n",
        "print(\"Aligned val size:\",   val_inputs_aligned[\"emotion_input\"].shape[0])\n"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "PrWxvqcs_THz",
        "outputId": "64f79a6a-2b3e-437e-8604-11b87394e920"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Aligned train size: 752\n",
            "Aligned val size: 188\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 9. Joint Training\n",
        "\n",
        "All three heads are trained simultaneously.  \n",
        "Each batch contains:\n",
        "- the emotion training examples,\n",
        "- the violence / abuse training examples,\n",
        "- the hate / offensive training examples.\n",
        "\n",
        "The model receives gradients from all heads, encouraging the shared encoder to capture cross-task signals such as emotional escalation, threats, or targeted hostility.\n",
        "\n",
        "Training is monitored on the held-out validation split.  \n",
        "Only a small number of epochs and a small batch size are used to keep runtime practical.\n"
      ],
      "metadata": {
        "id": "sw0jGy526Tqz"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 9. Joint training (aligned multi-task subset)\n",
        "\n",
        "history = model.fit(\n",
        "    x=train_inputs_aligned,\n",
        "    y=train_outputs_aligned,\n",
        "    validation_data=(val_inputs_aligned, val_outputs_aligned),\n",
        "    epochs=10,\n",
        "    batch_size=4,\n",
        "    shuffle=True,\n",
        "    verbose=1,\n",
        ")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "R15cLuul6UlK",
        "outputId": "7078f697-e03d-4bd8-ae93-8ec307ff6e3d"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Epoch 1/10\n",
            "\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m39s\u001b[0m 159ms/step - emotion_output_accuracy: 0.1826 - emotion_output_loss: 1.7888 - hate_output_accuracy: 0.3319 - hate_output_loss: 1.0931 - loss: 4.3188 - violence_output_accuracy: 0.4694 - violence_output_loss: 1.4370 - val_emotion_output_accuracy: 0.2553 - val_emotion_output_loss: 1.7709 - val_hate_output_accuracy: 0.7606 - val_hate_output_loss: 0.9968 - val_loss: 2.8848 - val_violence_output_accuracy: 1.0000 - val_violence_output_loss: 0.1171\n",
            "Epoch 2/10\n",
            "\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m28s\u001b[0m 146ms/step - emotion_output_accuracy: 0.3989 - emotion_output_loss: 1.7049 - hate_output_accuracy: 0.7476 - hate_output_loss: 0.8458 - loss: 2.6381 - violence_output_accuracy: 0.9868 - violence_output_loss: 0.0874 - val_emotion_output_accuracy: 0.3564 - val_emotion_output_loss: 1.6627 - val_hate_output_accuracy: 0.7074 - val_hate_output_loss: 0.6770 - val_loss: 2.4341 - val_violence_output_accuracy: 0.9628 - val_violence_output_loss: 0.0945\n",
            "Epoch 3/10\n",
            "\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 146ms/step - emotion_output_accuracy: 0.6480 - emotion_output_loss: 1.2104 - hate_output_accuracy: 0.8972 - hate_output_loss: 0.3052 - loss: 1.5555 - violence_output_accuracy: 0.9917 - violence_output_loss: 0.0399 - val_emotion_output_accuracy: 0.4947 - val_emotion_output_loss: 1.5573 - val_hate_output_accuracy: 0.7660 - val_hate_output_loss: 0.7097 - val_loss: 2.3538 - val_violence_output_accuracy: 0.9787 - val_violence_output_loss: 0.0868\n",
            "Epoch 4/10\n",
            "\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 146ms/step - emotion_output_accuracy: 0.8808 - emotion_output_loss: 0.5525 - hate_output_accuracy: 0.9713 - hate_output_loss: 0.1158 - loss: 0.7104 - violence_output_accuracy: 0.9847 - violence_output_loss: 0.0420 - val_emotion_output_accuracy: 0.5000 - val_emotion_output_loss: 1.6726 - val_hate_output_accuracy: 0.7287 - val_hate_output_loss: 0.8159 - val_loss: 2.6250 - val_violence_output_accuracy: 0.9734 - val_violence_output_loss: 0.1364\n",
            "Epoch 5/10\n",
            "\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m27s\u001b[0m 143ms/step - emotion_output_accuracy: 0.9564 - emotion_output_loss: 0.2512 - hate_output_accuracy: 0.9960 - hate_output_loss: 0.0430 - loss: 0.3089 - violence_output_accuracy: 0.9978 - violence_output_loss: 0.0147 - val_emotion_output_accuracy: 0.5479 - val_emotion_output_loss: 1.6975 - val_hate_output_accuracy: 0.7234 - val_hate_output_loss: 0.8688 - val_loss: 2.7191 - val_violence_output_accuracy: 0.9787 - val_violence_output_loss: 0.1527\n",
            "Epoch 6/10\n",
            "\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m26s\u001b[0m 140ms/step - emotion_output_accuracy: 0.9864 - emotion_output_loss: 0.1155 - hate_output_accuracy: 0.9955 - hate_output_loss: 0.0250 - loss: 0.1515 - violence_output_accuracy: 1.0000 - violence_output_loss: 0.0110 - val_emotion_output_accuracy: 0.5798 - val_emotion_output_loss: 1.7317 - val_hate_output_accuracy: 0.6596 - val_hate_output_loss: 1.0239 - val_loss: 2.9076 - val_violence_output_accuracy: 0.9628 - val_violence_output_loss: 0.1520\n",
            "Epoch 7/10\n",
            "\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 140ms/step - emotion_output_accuracy: 0.9928 - emotion_output_loss: 0.0564 - hate_output_accuracy: 0.9973 - hate_output_loss: 0.0211 - loss: 0.0846 - violence_output_accuracy: 1.0000 - violence_output_loss: 0.0071 - val_emotion_output_accuracy: 0.6064 - val_emotion_output_loss: 1.7616 - val_hate_output_accuracy: 0.6755 - val_hate_output_loss: 1.0481 - val_loss: 2.9733 - val_violence_output_accuracy: 0.9574 - val_violence_output_loss: 0.1636\n",
            "Epoch 8/10\n",
            "\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m27s\u001b[0m 141ms/step - emotion_output_accuracy: 1.0000 - emotion_output_loss: 0.0266 - hate_output_accuracy: 1.0000 - hate_output_loss: 0.0059 - loss: 0.0359 - violence_output_accuracy: 1.0000 - violence_output_loss: 0.0034 - val_emotion_output_accuracy: 0.5851 - val_emotion_output_loss: 1.7136 - val_hate_output_accuracy: 0.6702 - val_hate_output_loss: 1.1368 - val_loss: 3.0013 - val_violence_output_accuracy: 0.9681 - val_violence_output_loss: 0.1509\n",
            "Epoch 9/10\n",
            "\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m42s\u001b[0m 145ms/step - emotion_output_accuracy: 1.0000 - emotion_output_loss: 0.0219 - hate_output_accuracy: 1.0000 - hate_output_loss: 0.0045 - loss: 0.0285 - violence_output_accuracy: 1.0000 - violence_output_loss: 0.0021 - val_emotion_output_accuracy: 0.6064 - val_emotion_output_loss: 1.8128 - val_hate_output_accuracy: 0.6649 - val_hate_output_loss: 1.1895 - val_loss: 3.1889 - val_violence_output_accuracy: 0.9574 - val_violence_output_loss: 0.1866\n",
            "Epoch 10/10\n",
            "\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m40s\u001b[0m 141ms/step - emotion_output_accuracy: 1.0000 - emotion_output_loss: 0.0124 - hate_output_accuracy: 1.0000 - hate_output_loss: 0.0041 - loss: 0.0181 - violence_output_accuracy: 1.0000 - violence_output_loss: 0.0016 - val_emotion_output_accuracy: 0.6117 - val_emotion_output_loss: 1.7923 - val_hate_output_accuracy: 0.6702 - val_hate_output_loss: 1.2594 - val_loss: 3.2358 - val_violence_output_accuracy: 0.9681 - val_violence_output_loss: 0.1840\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 10. Evaluation on the Validation Split\n",
        "\n",
        "This section measures how well each task-specific head generalizes to data it did not see during training.\n",
        "\n",
        "For each task:\n",
        "- per-class precision, recall, and F1-score are reported using `classification_report`,\n",
        "- a confusion matrix is plotted to show common confusions.\n",
        "\n",
        "These metrics are computed on the held-out validation split.  \n",
        "In a production setting, additional evaluation on a strictly held-out test set (or external dataset) would be required, especially given class imbalance and sensitive safety implications.\n"
      ],
      "metadata": {
        "id": "qxZv6BMd6VYa"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 10. Evaluation on aligned validation subset\n",
        "\n",
        "# 1. Run model inference on the aligned validation inputs\n",
        "val_pred_logits = model.predict(val_inputs_aligned, batch_size=4, verbose=0)\n",
        "\n",
        "# Each head returns a softmax distribution per sample.\n",
        "# Take argmax to get the predicted class index.\n",
        "emo_val_pred  = np.argmax(val_pred_logits[0], axis=1)\n",
        "vio_val_pred  = np.argmax(val_pred_logits[1], axis=1)\n",
        "hate_val_pred = np.argmax(val_pred_logits[2], axis=1)\n",
        "\n",
        "# Ground-truth labels for the aligned validation subset\n",
        "emo_val_true  = val_outputs_aligned[\"emotion_output\"]\n",
        "vio_val_true  = val_outputs_aligned[\"violence_output\"]\n",
        "hate_val_true = val_outputs_aligned[\"hate_output\"]\n",
        "\n",
        "# 2. Build human-readable target_names.\n",
        "# Some datasets (e.g. emotion, hate) store numeric class IDs (0..5).\n",
        "# classification_report expects strings for target_names.\n",
        "emotion_target_names  = [str(x) for x in emotion_classes]\n",
        "violence_target_names = [str(x) for x in violence_classes]\n",
        "hate_target_names     = [str(x) for x in hate_classes]\n",
        "\n",
        "print(\"=== Emotion Task ===\")\n",
        "print(classification_report(\n",
        "    emo_val_true,\n",
        "    emo_val_pred,\n",
        "    target_names=emotion_target_names,\n",
        "    digits=3\n",
        "))\n",
        "\n",
        "print(\"=== Violence / Abuse Task ===\")\n",
        "print(classification_report(\n",
        "    vio_val_true,\n",
        "    vio_val_pred,\n",
        "    target_names=violence_target_names,\n",
        "    digits=3\n",
        "))\n",
        "\n",
        "print(\"=== Hate / Offensive Task ===\")\n",
        "print(classification_report(\n",
        "    hate_val_true,\n",
        "    hate_val_pred,\n",
        "    target_names=hate_target_names,\n",
        "    digits=3\n",
        "))\n",
        "\n",
        "# 3. Confusion matrix visualization helper\n",
        "def plot_confusion(y_true, y_pred, class_names, title):\n",
        "    \"\"\"\n",
        "    Visualize confusion structure on the aligned validation subset.\n",
        "    \"\"\"\n",
        "    cm = confusion_matrix(y_true, y_pred)\n",
        "    plt.figure(figsize=(4,4))\n",
        "    sns.heatmap(\n",
        "        cm,\n",
        "        annot=True,\n",
        "        fmt=\"d\",\n",
        "        xticklabels=class_names,\n",
        "        yticklabels=class_names,\n",
        "        cbar=False\n",
        "    )\n",
        "    plt.xlabel(\"Predicted\")\n",
        "    plt.ylabel(\"True\")\n",
        "    plt.title(title)\n",
        "    plt.tight_layout()\n",
        "    plt.show()\n",
        "\n",
        "plot_confusion(\n",
        "    emo_val_true,\n",
        "    emo_val_pred,\n",
        "    emotion_target_names,\n",
        "    \"Emotion (Aligned Validation)\"\n",
        ")\n",
        "\n",
        "plot_confusion(\n",
        "    vio_val_true,\n",
        "    vio_val_pred,\n",
        "    violence_target_names,\n",
        "    \"Violence / Abuse Risk (Aligned Validation)\"\n",
        ")\n",
        "\n",
        "plot_confusion(\n",
        "    hate_val_true,\n",
        "    hate_val_pred,\n",
        "    hate_target_names,\n",
        "    \"Hate / Offensive (Aligned Validation)\"\n",
        ")\n"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000
        },
        "id": "tnp4GM7M6WNC",
        "outputId": "e04c1bde-49cc-48b9-ff57-96f4c9a98e2b"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "=== Emotion Task ===\n",
            "              precision    recall  f1-score   support\n",
            "\n",
            "           0      0.545     0.600     0.571        30\n",
            "           1      0.538     0.538     0.538        26\n",
            "           2      0.696     0.533     0.604        30\n",
            "           3      0.559     0.594     0.576        32\n",
            "           4      0.581     0.676     0.625        37\n",
            "           5      0.793     0.697     0.742        33\n",
            "\n",
            "    accuracy                          0.612       188\n",
            "   macro avg      0.619     0.606     0.609       188\n",
            "weighted avg      0.621     0.612     0.613       188\n",
            "\n",
            "=== Violence / Abuse Task ===\n",
            "                              precision    recall  f1-score   support\n",
            "\n",
            "Harmful_Traditional_practice      0.971     0.895     0.932        38\n",
            "           Physical_violence      1.000     1.000     1.000        37\n",
            "           economic_violence      0.950     1.000     0.974        38\n",
            "          emotional_violence      1.000     0.947     0.973        38\n",
            "             sexual_violence      0.925     1.000     0.961        37\n",
            "\n",
            "                    accuracy                          0.968       188\n",
            "                   macro avg      0.969     0.968     0.968       188\n",
            "                weighted avg      0.969     0.968     0.968       188\n",
            "\n",
            "=== Hate / Offensive Task ===\n",
            "              precision    recall  f1-score   support\n",
            "\n",
            "           0      0.549     0.736     0.629        53\n",
            "           1      0.662     0.683     0.672        63\n",
            "           2      0.846     0.611     0.710        72\n",
            "\n",
            "    accuracy                          0.670       188\n",
            "   macro avg      0.686     0.676     0.670       188\n",
            "weighted avg      0.701     0.670     0.674       188\n",
            "\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 400x400 with 1 Axes>"
            ],
            "image/png": "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\n"
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 400x400 with 1 Axes>"
            ],
            "image/png": "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\n"
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 400x400 with 1 Axes>"
            ],
            "image/png": "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uhaPO7fuYMiE95GYkIgDuw2fxUSlLyUlFefOxUltaalpuH//gV57eaBYMAQFBcHOzg4LFy7E0qVLkZPzzxaxsbExvL29sXr1avTq1Uup8hST9DgNn6zZicRHqbA0VaNWVXssHfkumnm6AQD+TEjC4m3RSE59giq2FfFhx6YY0NZb2aLLuTpetbF08yLd7dEzggAAv2zchdlj5+G/S3+EmbkZJs8fD0trS5w5fhZjB0xCZkaWQhUT5U8lhFD8yqisrCwkJiYCAOzs7FChwott8afv+aY4yqJS1HbgD0qXQEV0/N4lpUugIsrOLNxp7S/FV2JUqFABzs7OSpdBRETglc9ERPQMBgMREUkYDEREJGEwEBGRhMFAREQSBgMREUkYDEREJGEwEBGRhMFAREQSBgMREUkYDEREJGEwEBGRhMFAREQSBgMREUkYDEREJGEwEBGRhMFAREQSBgMREUkYDEREJGEwEBGRhMFAREQSBgMREUkYDEREJGEwEBGRhMFAREQSBgMREUkYDEREJGEwEBGRhMFAREQSBgMREUkYDEREJGEwEBGRhMFAREQSBgMREUkYDEREJGEwEBGRhMFAREQSBgMREUkYDEREJGEwEBGRhMFAREQSBgMREUkYDEREJGEwEBGRhMFAREQSE6ULKAnTP4hSugQqov1HFildAhWRuUcnpUugEsIZAxERSRgMREQkYTAQEZGEwUBERBIGAxERSRgMREQkYTAQEZGEwUBERBIGAxERSRgMREQkYTAQEZGEwUBERBIGAxERSRgMREQkYTAQEZGEwUBERBIGAxERSRgMREQkYTAQEZGEwUBERBIGAxERSRgMREQkYTAQEZGEwUBERBIGAxERSRgMREQkYTAQEZGEwUBERBIGAxERSRgMREQkYTAQEZGEwUBERBIGAxERSRgMREQkYTAQEZGEwUBERJLnCobo6GgMGDAAzZo1Q3x8PAAgLCwMMTExxVocERGVviIHw08//YQOHTrAzMwMv//+OzIyMgAAycnJmDNnTrEXSEREpavIwTB79mwsX74cK1euRIUKFXTtLVq0wMmTJ4u1OCIiKn1FDoa4uDi0atVKr71ixYp4+PBhcdREREQKKnIwODk54cqVK3rtMTExqFGjRrEURUREyilyMAwZMgSjR4/G0aNHoVKpcPv2baxbtw7BwcEYMWJESdRIRESl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\n"
          },
          "metadata": {}
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 11. Interactive Inference Demo (Qualitative Only)\n",
        "\n",
        "The cell below provides a lightweight interactive widget for qualitative inspection.\n",
        "\n",
        "A short free-form text can be entered.  \n",
        "The text is normalized using the same preprocessing pipeline as training (lowercasing, stopword filtering), encoded with the same tokenizer, and passed through the multi-task model.\n",
        "\n",
        "For each task head (emotion, violence / abuse risk, hate / offensive):\n",
        "- the most likely class label is shown,\n",
        "- along with a confidence score derived from the softmax output.\n",
        "\n",
        "This interface is intended for exploratory analysis in a research setting.  \n",
        "It is not intended for automated enforcement or punitive action.  \n",
        "Low-confidence predictions should be interpreted as model uncertainty, not as a definitive decision.\n"
      ],
      "metadata": {
        "id": "5CamziHh6XU6"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 11. Interactive inference demo (human-readable labels)\n",
        "\n",
        "# Fixed human-readable label maps for each task head.\n",
        "# These reflect the semantic meaning of each class index.\n",
        "EMOTION_ID2LABEL = {\n",
        "    0: \"Sadness\",\n",
        "    1: \"Joy\",\n",
        "    2: \"Love\",\n",
        "    3: \"Anger\",\n",
        "    4: \"Fear\",\n",
        "    5: \"Surprise\",\n",
        "}\n",
        "\n",
        "VIOLENCE_ID2LABEL = {\n",
        "    0: \"Harmful_Traditional_practice\",\n",
        "    1: \"Physical_violence\",\n",
        "    2: \"economic_violence\",\n",
        "    3: \"emotional_violence\",\n",
        "    4: \"sexual_violence\",\n",
        "}\n",
        "\n",
        "HATE_ID2LABEL = {\n",
        "    0: \"Hate Speech\",\n",
        "    1: \"Offensive Speech\",\n",
        "    2: \"Neither\",\n",
        "}\n",
        "\n",
        "\n",
        "def preprocess_single_text(raw_text: str) -> np.ndarray:\n",
        "    \"\"\"\n",
        "    Apply the same normalization and tokenization procedure used in training:\n",
        "    - normalize_text(): lowercasing, punctuation cleanup\n",
        "    - remove_stopwords(): stopword filtering\n",
        "    - tokenizer -> integer IDs\n",
        "    - pad_sequences() -> fixed MAX_LEN\n",
        "    \"\"\"\n",
        "    normed = normalize_text(raw_text)\n",
        "    cleaned = remove_stopwords(normed)\n",
        "    seq = tokenizer.texts_to_sequences([cleaned])\n",
        "    pad = pad_sequences(\n",
        "        seq,\n",
        "        maxlen=MAX_LEN,\n",
        "        padding=\"post\",\n",
        "        truncating=\"post\"\n",
        "    )\n",
        "    return pad\n",
        "\n",
        "\n",
        "def decode_with_confidence(head_logits: np.ndarray, id2label_map: dict) -> dict:\n",
        "    \"\"\"\n",
        "    Convert a single-head softmax output into:\n",
        "    - predicted label string (via provided id2label_map),\n",
        "    - predicted class index,\n",
        "    - confidence score in [0,1] (best softmax value).\n",
        "    Any NaN/Inf values are coerced to 0.0 for display stability.\n",
        "    \"\"\"\n",
        "    probs = np.nan_to_num(head_logits[0], nan=0.0, posinf=0.0, neginf=0.0)\n",
        "    idx = int(np.argmax(probs))\n",
        "    conf = float(probs[idx])\n",
        "    label_readable = id2label_map.get(idx, f\"Class_{idx}\")\n",
        "    return {\n",
        "        \"class_id\": idx,\n",
        "        \"label_readable\": label_readable,\n",
        "        \"confidence\": conf,\n",
        "    }\n",
        "\n",
        "\n",
        "def classify_text_once(raw_text: str) -> dict:\n",
        "    \"\"\"\n",
        "    End-to-end inference for a single input string.\n",
        "    Returns human-readable predictions + confidence per task head.\n",
        "    \"\"\"\n",
        "    pad = preprocess_single_text(raw_text)\n",
        "\n",
        "    emo_logits, vio_logits, hate_logits = model.predict(\n",
        "        {\n",
        "            \"emotion_input\":  pad,\n",
        "            \"violence_input\": pad,\n",
        "            \"hate_input\":     pad,\n",
        "        },\n",
        "        verbose=0\n",
        "    )\n",
        "\n",
        "    emo_res  = decode_with_confidence(emo_logits,  EMOTION_ID2LABEL)\n",
        "    vio_res  = decode_with_confidence(vio_logits,  VIOLENCE_ID2LABEL)\n",
        "    hate_res = decode_with_confidence(hate_logits, HATE_ID2LABEL)\n",
        "\n",
        "    return {\n",
        "        \"emotion\":  emo_res,\n",
        "        \"violence\": vio_res,\n",
        "        \"hate\":     hate_res,\n",
        "    }\n",
        "\n",
        "\n",
        "# --- Interactive widget setup ---\n",
        "\n",
        "input_box = widgets.Text(\n",
        "    value=\"\",\n",
        "    placeholder=\"Enter a short social-media-style message...\",\n",
        "    description=\"Text:\",\n",
        "    layout=widgets.Layout(width=\"80%\")\n",
        ")\n",
        "\n",
        "run_button = widgets.Button(\n",
        "    description=\"Classify\",\n",
        "    button_style=\"\"\n",
        ")\n",
        "\n",
        "output_box = widgets.Output()\n",
        "\n",
        "\n",
        "def on_click_classify(_):\n",
        "    \"\"\"\n",
        "    UI callback.\n",
        "    Produces a triage-style summary:\n",
        "    - For each head, prints the interpreted label (Fear, economic_violence, Hate Speech, etc.)\n",
        "      instead of raw numeric class IDs.\n",
        "    - Prints confidence to indicate the model's internal certainty.\n",
        "    The output is explicitly framed as decision support, not enforcement.\n",
        "    \"\"\"\n",
        "    with output_box:\n",
        "        clear_output(wait=True)\n",
        "\n",
        "        text_inp = input_box.value.strip()\n",
        "        if len(text_inp) == 0:\n",
        "            print(\"No input text provided.\")\n",
        "            return\n",
        "\n",
        "        result = classify_text_once(text_inp)\n",
        "\n",
        "        print(\"Predicted categories (for triage, not automated enforcement):\\n\")\n",
        "\n",
        "        # Emotion\n",
        "        print(\"Emotion:\")\n",
        "        print(f\"  predicted : {result['emotion']['label_readable']} \"\n",
        "              f\"(class {result['emotion']['class_id']})\")\n",
        "        print(f\"  confidence: {result['emotion']['confidence']:.3f}\\n\")\n",
        "\n",
        "        # Violence / Abuse\n",
        "        print(\"Violence / Abuse Risk:\")\n",
        "        print(f\"  predicted : {result['violence']['label_readable']} \"\n",
        "              f\"(class {result['violence']['class_id']})\")\n",
        "        print(f\"  confidence: {result['violence']['confidence']:.3f}\\n\")\n",
        "\n",
        "        # Hate / Offensive\n",
        "        print(\"Hate / Offensive Content:\")\n",
        "        print(f\"  predicted : {result['hate']['label_readable']} \"\n",
        "              f\"(class {result['hate']['class_id']})\")\n",
        "        print(f\"  confidence: {result['hate']['confidence']:.3f}\\n\")\n",
        "\n",
        "        print(\"Note: These predictions are intended to assist human review of potentially high-risk content.\")\n",
        "        print(\"They are not a final moderation decision or a clinical assessment.\\n\")\n",
        "\n",
        "\n",
        "run_button.on_click(on_click_classify)\n",
        "\n",
        "display(input_box, run_button, output_box)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 376,
          "referenced_widgets": [
            "ef003c425c914f079729b3d34cb796bb",
            "bb671a6a50bf47019f1f4dd1d81626ed",
            "5e6430ae7eb6443bac91bfb496040d38",
            "c3701de6e3424ecda35111fcdfbba229",
            "1442a77588894285a72372993edf936c",
            "7eaba2df78a641679b3f997cc58deac6",
            "bef778b2738744bebfb29f706f15c0ab",
            "c3076368624544ec94a4950b89924006"
          ]
        },
        "id": "wgRvZ7Qs6YWa",
        "outputId": "0c6fa23e-828b-4bdd-8003-9bf2055c0576"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "Text(value='', description='Text:', layout=Layout(width='80%'), placeholder='Enter a short social-media-style …"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "ef003c425c914f079729b3d34cb796bb"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "Button(description='Classify', style=ButtonStyle())"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "c3701de6e3424ecda35111fcdfbba229"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "Output()"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "bef778b2738744bebfb29f706f15c0ab"
            }
          },
          "metadata": {}
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 12. Results\n",
        "\n",
        "Performance differs by head on the aligned validation split. The **violence or abuse** head achieves near-ceiling scores, while **emotion** and **hate or offensive** are moderate with clear boundary confusions.\n",
        "\n",
        "- **Emotion:** accuracy 0.612, macro F1 0.609 on 188 samples. Per-class F1 is highest for Surprise at 0.742 and lowest for Joy at 0.538. Love sits at 0.604, Anger at 0.576, Fear at 0.625, and Sadness at 0.571. Weighted F1 is 0.613, close to macro, which indicates that results are not dominated by a single large class.  \n",
        "- **Violence or abuse:** accuracy 0.968, macro F1 0.968 on 188 samples, with class F1 in the 0.961 to 1.000 range. Confusions are minimal, which suggests that the taxonomy and lexical cues for this dataset are highly separable under the shared encoder.  \n",
        "- **Hate or offensive:** accuracy 0.670, macro F1 0.670 on 188 samples. Class F1 is 0.629 for Hate Speech, 0.672 for Offensive Speech, and 0.710 for Neither. Weighted F1 is 0.674. The pattern indicates boundary confusions between hate and offensive and occasional drift from Neither into Offensive.\n",
        "\n",
        "**Key readouts to cite:**\n",
        "- Emotion head: accuracy 0.612, macro F1 0.609, with Surprise at 0.742 F1  \n",
        "- Violence or abuse head: accuracy 0.968, macro F1 0.968, near-diagonal confusion  \n",
        "- Hate or offensive head: accuracy 0.670, macro F1 0.670, with Hate Speech at 0.629 F1\n"
      ],
      "metadata": {
        "id": "36KPAYJ4QGBo"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 13. Insights\n",
        "\n",
        "A single tokenizer fit on the union of training text enables a shared embedding space that reduces vocabulary fragmentation across tasks. Controlled downsampling toward the minority size improves stability without complex sampling schedules. Aligning the multi-task subset is important for joint training since it prevents silent imbalance between heads. Confusion inspection is more informative than a single score because it exposes where euphemism, sarcasm, or polysemy drive errors. Light normalization helps most on violence and hate where punctuation and casing can distract the encoder, while emotion benefits from richer lexical cues or auxiliary prosodic features.\n",
        "\n",
        "**Concise takeaways:**\n",
        "- Shared vocabulary and encoder encourage transfer of general signal across tasks  \n",
        "- Balanced aligned subsets prevent one head from dominating updates during joint training  \n",
        "- Per-class reports and confusion matrices guide targeted data curation and label review\n"
      ],
      "metadata": {
        "id": "Q0ClNNsgQGZa"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 14. Responsible Use and Limitations\n",
        "\n",
        "This notebook is a research and teaching artifact. It is not intended for policy or legal decisions. Predictions support analysis and should be reviewed by a human.\n",
        "\n",
        "**Scope and risks:**\n",
        "- Datasets provide limited coverage of dialects, code-switching, and adversarial obfuscation  \n",
        "- Class imbalance and label noise can affect calibration and can hide rare failure modes  \n",
        "- Single post processing omits dialogue context, author history, and platform policy nuance  \n",
        "- Confidence values are heuristic and not fully calibrated across tasks\n",
        "\n",
        "**Operational guidance:**\n",
        "- Keep a human in the loop for any action that affects people  \n",
        "- Reevaluate performance before deployment to new domains, languages, or communities  \n",
        "- Prefer macro-oriented reporting and per-class inspection when comparing versions  \n",
        "- Maintain a documented process for appeal, correction, and dataset updates\n"
      ],
      "metadata": {
        "id": "UCyUWDZTdDNa"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 15. Conclusion\n",
        "\n",
        "A compact multi-task pipeline with a shared encoder and three task-specific heads offers a coherent way to screen text for emotional escalation, violence or abuse risk, and hate or offensive content. Fixed preprocessing and an aligned training subset make results easier to reproduce and to audit. Macro-focused evaluation and confusion analysis keep attention on minority classes and boundary cases. The approach is suitable for triage and analyst support and reduces deployment complexity by maintaining one encoder rather than three separate models.\n"
      ],
      "metadata": {
        "id": "7f7101nQdEDj"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 16. Next Steps\n",
        "\n",
        "Future work can strengthen reliability while keeping the footprint reasonable. Data-centric improvements include curating hard negatives, enriching long-tail labels, and auditing annotator agreement on ambiguous categories. Modeling options include class-weighted loss or focal loss, temperature scaling for post hoc calibration, and selective abstention for low-confidence cases. Tokenization and encoder upgrades can be explored with compact transformer backbones while preserving the multi-head structure. External validation on a disjoint corpus is important to assess robustness and potential bias.\n",
        "\n",
        "**Priorities to explore:**\n",
        "- Add class-weighted or focal loss and measure macro F1 change per head  \n",
        "- Calibrate confidences with temperature scaling and evaluate expected calibration error  \n",
        "- Introduce selective abstention and report coverage versus accuracy trade-offs  \n",
        "- Test a small transformer encoder with the same heads and the same splits  \n",
        "- Perform slice-based analysis by topic, length, and lexical markers to localize errors\n"
      ],
      "metadata": {
        "id": "YtksXJ99dFQD"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Author / Contact\n",
        "\n",
        "**Rifky Setiawan**  \n",
        "Undergraduate Student, Department of Computer Science  \n",
        "Universitas Gadjah Mada (UGM), Indonesia   \n",
        "Email: rifkysetiawan@mail.ugm.ac.id\n",
        "\n"
      ],
      "metadata": {
        "id": "tDuDyqT_6b8y"
      }
    }
  ]
}