{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "02d3dc80",
      "metadata": {
        "id": "02d3dc80"
      },
      "source": [
        "# SMS Spam Classification with Kaggle Dataset"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cc1945db",
      "metadata": {
        "id": "cc1945db"
      },
      "source": [
        "\n",
        "This project of SMS spam classification uses the **SMS Spam Collection** dataset downloaded from this link\n",
        "https://www.kaggle.com/datasets/uciml/sms-spam-collection-dataset?resource=download\n",
        " (5,574 SMS messages labeled as ham or spam【143902215453541†L32-L36】【143902215453541†L93-L105】) and implements:\n",
        "\n",
        "* Loading the dataset via Kaggle or manual upload.\n",
        "* Text preprocessing (lowercase, remove punctuation, stopwords, lemmatization).\n",
        "* Data splitting into training and testing sets.\n",
        "* Feature representation with **Bag‑of‑Words** (CountVectorizer) and **TF‑IDF** (including n‑grams).\n",
        "* Definition of a reusable evaluation function that computes accuracy, precision, recall, F1 score, confusion matrix and displays a heatmap.\n",
        "* Training and hyperparameter tuning for multiple classifiers via **GridSearchCV**:\n",
        "  - **Random Forest**\n",
        "  - **Logistic Regression**\n",
        "  - **Decision Tree**\n",
        "  - **Support Vector Machine (SVM)**\n",
        "* Comparison of model performance on the validation set using the evaluation function.\n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "81dbccbb",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "81dbccbb",
        "outputId": "ba32e097-962e-4141-998e-8d471e5e95d3"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "[nltk_data] Downloading package stopwords to /root/nltk_data...\n",
            "[nltk_data]   Unzipping corpora/stopwords.zip.\n",
            "[nltk_data] Downloading package wordnet to /root/nltk_data...\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "True"
            ]
          },
          "metadata": {},
          "execution_count": 1
        }
      ],
      "source": [
        "\n",
        "# Install necessary packages (uncomment if needed)\n",
        "# !pip install kaggle nltk scikit-learn seaborn matplotlib\n",
        "\n",
        "import os\n",
        "import pandas as pd\n",
        "import numpy as np\n",
        "import nltk\n",
        "import re\n",
        "import matplotlib.pyplot as plt\n",
        "import seaborn as sns\n",
        "from nltk.corpus import stopwords\n",
        "from nltk.stem import WordNetLemmatizer\n",
        "from sklearn.model_selection import train_test_split, GridSearchCV\n",
        "from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer\n",
        "from sklearn.naive_bayes import MultinomialNB\n",
        "from sklearn.linear_model import LogisticRegression\n",
        "from sklearn.tree import DecisionTreeClassifier\n",
        "from sklearn.ensemble import RandomForestClassifier\n",
        "from sklearn.svm import SVC\n",
        "from sklearn.metrics import (accuracy_score, precision_score, recall_score,\n",
        "                             f1_score, confusion_matrix, classification_report)\n",
        "\n",
        "# Download NLTK resources\n",
        "nltk.download('stopwords')\n",
        "nltk.download('wordnet')\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "9eaf3ae3",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 229
        },
        "id": "9eaf3ae3",
        "outputId": "80671057-ba31-4b49-9f8a-f4c86a21205b"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Dataset file not found locally. Please upload 'spam.csv' or 'SMSSpamCollection'.\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ],
            "text/html": [
              "\n",
              "     <input type=\"file\" id=\"files-80f27a32-2c4d-48f2-bedb-35874f95deac\" name=\"files[]\" multiple disabled\n",
              "        style=\"border:none\" />\n",
              "     <output id=\"result-80f27a32-2c4d-48f2-bedb-35874f95deac\">\n",
              "      Upload widget is only available when the cell has been executed in the\n",
              "      current browser session. Please rerun this cell to enable.\n",
              "      </output>\n",
              "      <script>// Copyright 2017 Google LLC\n",
              "//\n",
              "// Licensed under the Apache License, Version 2.0 (the \"License\");\n",
              "// you may not use this file except in compliance with the License.\n",
              "// You may obtain a copy of the License at\n",
              "//\n",
              "//      http://www.apache.org/licenses/LICENSE-2.0\n",
              "//\n",
              "// Unless required by applicable law or agreed to in writing, software\n",
              "// distributed under the License is distributed on an \"AS IS\" BASIS,\n",
              "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
              "// See the License for the specific language governing permissions and\n",
              "// limitations under the License.\n",
              "\n",
              "/**\n",
              " * @fileoverview Helpers for google.colab Python module.\n",
              " */\n",
              "(function(scope) {\n",
              "function span(text, styleAttributes = {}) {\n",
              "  const element = document.createElement('span');\n",
              "  element.textContent = text;\n",
              "  for (const key of Object.keys(styleAttributes)) {\n",
              "    element.style[key] = styleAttributes[key];\n",
              "  }\n",
              "  return element;\n",
              "}\n",
              "\n",
              "// Max number of bytes which will be uploaded at a time.\n",
              "const MAX_PAYLOAD_SIZE = 100 * 1024;\n",
              "\n",
              "function _uploadFiles(inputId, outputId) {\n",
              "  const steps = uploadFilesStep(inputId, outputId);\n",
              "  const outputElement = document.getElementById(outputId);\n",
              "  // Cache steps on the outputElement to make it available for the next call\n",
              "  // to uploadFilesContinue from Python.\n",
              "  outputElement.steps = steps;\n",
              "\n",
              "  return _uploadFilesContinue(outputId);\n",
              "}\n",
              "\n",
              "// This is roughly an async generator (not supported in the browser yet),\n",
              "// where there are multiple asynchronous steps and the Python side is going\n",
              "// to poll for completion of each step.\n",
              "// This uses a Promise to block the python side on completion of each step,\n",
              "// then passes the result of the previous step as the input to the next step.\n",
              "function _uploadFilesContinue(outputId) {\n",
              "  const outputElement = document.getElementById(outputId);\n",
              "  const steps = outputElement.steps;\n",
              "\n",
              "  const next = steps.next(outputElement.lastPromiseValue);\n",
              "  return Promise.resolve(next.value.promise).then((value) => {\n",
              "    // Cache the last promise value to make it available to the next\n",
              "    // step of the generator.\n",
              "    outputElement.lastPromiseValue = value;\n",
              "    return next.value.response;\n",
              "  });\n",
              "}\n",
              "\n",
              "/**\n",
              " * Generator function which is called between each async step of the upload\n",
              " * process.\n",
              " * @param {string} inputId Element ID of the input file picker element.\n",
              " * @param {string} outputId Element ID of the output display.\n",
              " * @return {!Iterable<!Object>} Iterable of next steps.\n",
              " */\n",
              "function* uploadFilesStep(inputId, outputId) {\n",
              "  const inputElement = document.getElementById(inputId);\n",
              "  inputElement.disabled = false;\n",
              "\n",
              "  const outputElement = document.getElementById(outputId);\n",
              "  outputElement.innerHTML = '';\n",
              "\n",
              "  const pickedPromise = new Promise((resolve) => {\n",
              "    inputElement.addEventListener('change', (e) => {\n",
              "      resolve(e.target.files);\n",
              "    });\n",
              "  });\n",
              "\n",
              "  const cancel = document.createElement('button');\n",
              "  inputElement.parentElement.appendChild(cancel);\n",
              "  cancel.textContent = 'Cancel upload';\n",
              "  const cancelPromise = new Promise((resolve) => {\n",
              "    cancel.onclick = () => {\n",
              "      resolve(null);\n",
              "    };\n",
              "  });\n",
              "\n",
              "  // Wait for the user to pick the files.\n",
              "  const files = yield {\n",
              "    promise: Promise.race([pickedPromise, cancelPromise]),\n",
              "    response: {\n",
              "      action: 'starting',\n",
              "    }\n",
              "  };\n",
              "\n",
              "  cancel.remove();\n",
              "\n",
              "  // Disable the input element since further picks are not allowed.\n",
              "  inputElement.disabled = true;\n",
              "\n",
              "  if (!files) {\n",
              "    return {\n",
              "      response: {\n",
              "        action: 'complete',\n",
              "      }\n",
              "    };\n",
              "  }\n",
              "\n",
              "  for (const file of files) {\n",
              "    const li = document.createElement('li');\n",
              "    li.append(span(file.name, {fontWeight: 'bold'}));\n",
              "    li.append(span(\n",
              "        `(${file.type || 'n/a'}) - ${file.size} bytes, ` +\n",
              "        `last modified: ${\n",
              "            file.lastModifiedDate ? file.lastModifiedDate.toLocaleDateString() :\n",
              "                                    'n/a'} - `));\n",
              "    const percent = span('0% done');\n",
              "    li.appendChild(percent);\n",
              "\n",
              "    outputElement.appendChild(li);\n",
              "\n",
              "    const fileDataPromise = new Promise((resolve) => {\n",
              "      const reader = new FileReader();\n",
              "      reader.onload = (e) => {\n",
              "        resolve(e.target.result);\n",
              "      };\n",
              "      reader.readAsArrayBuffer(file);\n",
              "    });\n",
              "    // Wait for the data to be ready.\n",
              "    let fileData = yield {\n",
              "      promise: fileDataPromise,\n",
              "      response: {\n",
              "        action: 'continue',\n",
              "      }\n",
              "    };\n",
              "\n",
              "    // Use a chunked sending to avoid message size limits. See b/62115660.\n",
              "    let position = 0;\n",
              "    do {\n",
              "      const length = Math.min(fileData.byteLength - position, MAX_PAYLOAD_SIZE);\n",
              "      const chunk = new Uint8Array(fileData, position, length);\n",
              "      position += length;\n",
              "\n",
              "      const base64 = btoa(String.fromCharCode.apply(null, chunk));\n",
              "      yield {\n",
              "        response: {\n",
              "          action: 'append',\n",
              "          file: file.name,\n",
              "          data: base64,\n",
              "        },\n",
              "      };\n",
              "\n",
              "      let percentDone = fileData.byteLength === 0 ?\n",
              "          100 :\n",
              "          Math.round((position / fileData.byteLength) * 100);\n",
              "      percent.textContent = `${percentDone}% done`;\n",
              "\n",
              "    } while (position < fileData.byteLength);\n",
              "  }\n",
              "\n",
              "  // All done.\n",
              "  yield {\n",
              "    response: {\n",
              "      action: 'complete',\n",
              "    }\n",
              "  };\n",
              "}\n",
              "\n",
              "scope.google = scope.google || {};\n",
              "scope.google.colab = scope.google.colab || {};\n",
              "scope.google.colab._files = {\n",
              "  _uploadFiles,\n",
              "  _uploadFilesContinue,\n",
              "};\n",
              "})(self);\n",
              "</script> "
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Saving archive (1).zip to archive (1).zip\n",
            "Loading dataset from: archive (1).zip\n",
            "Dataset shape: (5572, 2)\n",
            "  label                                               text\n",
            "0   ham  Go until jurong point, crazy.. Available only ...\n",
            "1   ham                      Ok lar... Joking wif u oni...\n",
            "2  spam  Free entry in 2 a wkly comp to win FA Cup fina...\n",
            "3   ham  U dun say so early hor... U c already then say...\n",
            "4   ham  Nah I don't think he goes to usf, he lives aro...\n"
          ]
        }
      ],
      "source": [
        "\n",
        "# Dataset loading\n",
        "# -------------------------------------------------------------\n",
        "# Option 1: Download via Kaggle API (requires API credentials and kaggle.json)\n",
        "# !pip install kaggle -q\n",
        "# import json\n",
        "# os.environ['KAGGLE_USERNAME'] = 'your_username'\n",
        "# os.environ['KAGGLE_KEY'] = 'your_key'\n",
        "# !kaggle datasets download -d uciml/sms-spam-collection-dataset -p /content/ --unzip --force\n",
        "\n",
        "from pathlib import Path\n",
        "from google.colab import files\n",
        "\n",
        "# Look for existing dataset files\n",
        "possible_files = ['spam.csv', 'SMSSpamCollection']\n",
        "dataset_file = None\n",
        "for fname in possible_files:\n",
        "    if Path(fname).exists():\n",
        "        dataset_file = Path(fname)\n",
        "        break\n",
        "\n",
        "if dataset_file is None:\n",
        "    print(\"Dataset file not found locally. Please upload 'spam.csv' or 'SMSSpamCollection'.\")\n",
        "    uploaded = files.upload()\n",
        "    fname = next(iter(uploaded))\n",
        "    dataset_file = Path(fname)\n",
        "\n",
        "# Load the CSV/text file\n",
        "print(f\"Loading dataset from: {dataset_file}\")\n",
        "df = pd.read_csv(dataset_file, encoding='latin-1')\n",
        "\n",
        "# Standardize column names to 'label' and 'text'\n",
        "if 'v1' in df.columns and 'v2' in df.columns:\n",
        "    df = df[['v1', 'v2']]\n",
        "    df.columns = ['label', 'text']\n",
        "elif 'label' in df.columns and 'text' in df.columns:\n",
        "    df = df[['label', 'text']]\n",
        "else:\n",
        "    df = df.iloc[:, :2]\n",
        "    df.columns = ['label', 'text']\n",
        "\n",
        "print(f\"Dataset shape: {df.shape}\")\n",
        "print(df.head())\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "4c3471b7",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "4c3471b7",
        "outputId": "be20e11f-6af5-4f8d-888d-243557b833c4"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "  label                                         clean_text\n",
            "0   ham  go jurong point crazy available bugis n great ...\n",
            "1   ham                            ok lar joking wif u oni\n",
            "2  spam  free entry wkly comp win fa cup final tkts st ...\n",
            "3   ham                u dun say early hor u c already say\n",
            "4   ham                nah think go usf life around though\n"
          ]
        }
      ],
      "source": [
        "\n",
        "# Text preprocessing\n",
        "# -------------------------------------------------------------\n",
        "stop_words = set(stopwords.words('english'))\n",
        "lemmatizer = WordNetLemmatizer()\n",
        "\n",
        "def clean_message(msg: str) -> str:\n",
        "    msg = msg.lower()\n",
        "    msg = re.sub(r'[^a-z\\s]', ' ', msg)\n",
        "    tokens = msg.split()\n",
        "    tokens = [lemmatizer.lemmatize(t) for t in tokens if t not in stop_words]\n",
        "    return ' '.join(tokens)\n",
        "\n",
        "# Apply cleaning to all messages\n",
        "df['clean_text'] = df['text'].astype(str).apply(clean_message)\n",
        "\n",
        "print(df[['label', 'clean_text']].head())\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "1b5b4a3f",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "1b5b4a3f",
        "outputId": "60d5d59d-b0e6-44e5-924a-f195b64f5cc7"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Training samples: 4457, Test samples: 1115\n"
          ]
        }
      ],
      "source": [
        "\n",
        "# Encode labels to numeric\n",
        "label_mapping = {label: idx for idx, label in enumerate(sorted(df['label'].unique()))}\n",
        "df['target'] = df['label'].map(label_mapping)\n",
        "\n",
        "# Train-test split (80/20)\n",
        "X_train, X_test, y_train, y_test = train_test_split(\n",
        "    df['clean_text'],\n",
        "    df['target'],\n",
        "    test_size=0.2,\n",
        "    random_state=42,\n",
        "    stratify=df['target']\n",
        ")\n",
        "\n",
        "print(f\"Training samples: {len(X_train)}, Test samples: {len(X_test)}\")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "dca949a2",
      "metadata": {
        "id": "dca949a2"
      },
      "outputs": [],
      "source": [
        "\n",
        "# Evaluation function\n",
        "# -------------------------------------------------------------\n",
        "def evaluate_model(model_name, y_true, y_pred):\n",
        "    accuracy = accuracy_score(y_true, y_pred)\n",
        "    precision = precision_score(y_true, y_pred, average='weighted')\n",
        "    recall = recall_score(y_true, y_pred, average='weighted')\n",
        "    f1 = f1_score(y_true, y_pred, average='weighted')\n",
        "    cm = confusion_matrix(y_true, y_pred)\n",
        "    report = classification_report(y_true, y_pred, target_names=sorted(label_mapping, key=label_mapping.get))\n",
        "\n",
        "    metrics = {\n",
        "        'Model Name': model_name,\n",
        "        'Accuracy': accuracy,\n",
        "        'Precision': precision,\n",
        "        'Recall': recall,\n",
        "        'F1 Score': f1,\n",
        "        'Classification Report': report\n",
        "    }\n",
        "\n",
        "    # Plot confusion matrix\n",
        "    plt.figure(figsize=(4, 4))\n",
        "    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', cbar=False,\n",
        "                xticklabels=np.unique(y_true),\n",
        "                yticklabels=np.unique(y_true))\n",
        "    plt.title(f'Confusion Matrix for {model_name}')\n",
        "    plt.xlabel('Predicted Label')\n",
        "    plt.ylabel('True Label')\n",
        "    plt.show()\n",
        "\n",
        "    return metrics\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "da467754",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000
        },
        "id": "da467754",
        "outputId": "455bd0f2-b08f-4221-da39-76777e5ac007"
      },
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 400x400 with 1 Axes>"
            ],
            "image/png": "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\n"
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Best RandomForest params: {'max_depth': None, 'n_estimators': 200}\n",
            "              precision    recall  f1-score   support\n",
            "\n",
            "         ham       0.97      1.00      0.98       966\n",
            "        spam       1.00      0.79      0.88       149\n",
            "\n",
            "    accuracy                           0.97      1115\n",
            "   macro avg       0.98      0.90      0.93      1115\n",
            "weighted avg       0.97      0.97      0.97      1115\n",
            "\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 400x400 with 1 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAGJCAYAAACNTVhdAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAANSRJREFUeJzt3Xl4TGf/BvB7sk0iy2QlCRohQkjs5CUqlIpaamttr0oQW1EVactbihRpbbEvb5WkqSqlRdGillL7ltiX2KvZSSKyZ57fH36Z10hCwiQjnvtzXbmYc555zvecObnnmXPOnCiEEAJERCQNA30XQERE5YvBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbB/4KuXbuGjh07QqVSQaFQYPPmzTrt/9atW1AoFAgPD9dpvxVZ27Zt0bZtW531l56ejsDAQDg6OkKhUODjjz/WWd+viv3790OhUGD//v066S88PBwKhQK3bt3SSX+y0fU+/KIqdPBfv34dI0aMQM2aNWFqagorKyv4+Phg4cKFyMzMLNNl+/v749y5c5g5cyYiIyPRrFmzMl1eeQoICIBCoYCVlVWR2/HatWtQKBRQKBSYO3duqfv/559/MG3aNERFRemg2hc3a9YshIeHY9SoUYiMjMQHH3xQpsurUaMGunbtWqbL0JVZs2bpdDBTsE8V/CiVSri7u+OLL75AVlaWzpZDJSQqqG3btgkzMzNhbW0tPvroI/Hf//5XLFmyRPTr108YGxuLYcOGldmyMzIyBADx+eefl9ky1Gq1yMzMFHl5eWW2jOL4+/sLIyMjYWhoKNavX19o/tSpU4WpqakAIObMmVPq/k+cOCEAiDVr1pTqednZ2SI7O7vUyyuOt7e38PHx0Vl/z+Pi4iK6dOlSbssTQoj8/HyRmZkp8vPzS/U8c3Nz4e/vX2h6Xl6eyMzMFGq1ulT9+fv7C6VSKSIjI0VkZKRYsmSJePvttwUAMWDAgFL1VZHpeh9+UUb6fdt5MTdv3kS/fv3g4uKCvXv3wsnJSTNv9OjRiImJwfbt28ts+YmJiQAAa2vrMluGQqGAqalpmfX/PEqlEj4+Pli3bh369OmjNe+HH35Aly5dsGnTpnKpJSMjA5UqVYKJiYlO+01ISEC9evV01l9eXh7UarXO63wZBgYGOt2PDA0NYWho+ELPNTIywsCBAzWPP/zwQ7Rq1Qrr1q3D/PnzUaVKFV2V+Vz6eq1emX1D3+88L2LkyJECgDh06FCJ2ufm5oqQkBBRs2ZNYWJiIlxcXMSkSZNEVlaWVruCEdnBgwdF8+bNhVKpFK6uriIiIkLTZurUqQKA1o+Li4sQ4vGopuD/Typ4zpN27dolfHx8hEqlEubm5sLd3V1MmjRJM//mzZtFjor37NkjWrduLSpVqiRUKpV49913xcWLF4tc3rVr14S/v79QqVTCyspKBAQEiEePHj13e/n7+wtzc3MRHh4ulEqlePDggWbe8ePHBQCxadOmQiP+5ORkMWHCBOHp6SnMzc2FpaWl6NSpk4iKitK02bdvX6Ht9+R6+vr6ivr164uTJ0+KN998U5iZmYlx48Zp5vn6+mr6GjRokFAqlYXWv2PHjsLa2lrcu3evyPUrroabN28KIYSIj48XQ4YMEZUrVxZKpVI0aNBAhIeHa/VR8PrMmTNHhIWFiZo1awoDAwNx5syZYrdrSUb8Jd1X8/PzxdSpU4WTk5MwMzMTbdu2FRcuXBAuLi5aI/WCdd23b59m2tWrV0WvXr1ElSpVhFKpFFWrVhV9+/YVKSkpQghR5LYp6HPNmjVa26rAjh07RJs2bYSFhYWwtLQUzZo1E2vXrtXML9innhYcHCwAiMOHDxfqr2A/t7CwEJ07dxbnz58v9PwNGzYIDw8PoVQqRf369cXPP/9c6Pfwea/VpUuXRO/evYWNjY1QKpWiadOmYsuWLVrLycnJEdOmTRNubm5CqVQKW1tb4ePjI3bt2qVpExsbKwICAkTVqlWFiYmJcHR0FO+++67Wtnp6Hxai9PvbypUrNftHs2bNxPHjxwttl+epkCP+X3/9FTVr1kSrVq1K1D4wMBARERF47733MGHCBBw7dgyhoaG4dOkSfvnlF622MTExeO+99zB06FD4+/tj9erVCAgIQNOmTVG/fn306tUL1tbWGD9+PPr374/OnTvDwsKiVPVfuHABXbt2RYMGDRASEgKlUomYmBgcOnTomc/7448/8M4776BmzZqYNm0aMjMzsXjxYvj4+OD06dOoUaOGVvs+ffrA1dUVoaGhOH36NFatWoXKlSvj66+/LlGdvXr1wsiRI/Hzzz9jyJAhAB6P9uvWrYsmTZoUan/jxg1s3rwZ77//PlxdXREfH4+VK1fC19cXFy9ehLOzMzw8PBASEoIvvvgCw4cPx5tvvgkAWq9lcnIy3nnnHfTr1w8DBw4sdiS4cOFC7N27F/7+/jhy5AgMDQ2xcuVK7Nq1C5GRkXB2di7yeR4eHoiMjMT48eNRrVo1TJgwAQDg4OCAzMxMtG3bFjExMRgzZgxcXV3x008/ISAgACkpKRg3bpxWX2vWrEFWVhaGDx8OpVIJW1vbEm3b4pR0X500aRJmz56Nbt26wc/PD9HR0fDz83vu8fKcnBz4+fkhOzsbY8eOhaOjI+7du4dt27YhJSUFKpUKkZGRCAwMRIsWLTB8+HAAQK1atYrtMzw8HEOGDEH9+vUxadIkWFtb48yZM/j9998xYMCAZ9ZTcJLYxsZGMy0yMhL+/v7w8/PD119/jYyMDCxfvhytW7fGmTNnNPv59u3b0bdvX3h5eSE0NBQPHjzA0KFDUbVq1SKXVdRrdeHCBfj4+KBq1aqYOHEizM3NsWHDBvTo0QObNm1Cz549AQDTpk1DaGioZrukpaXh5MmTOH36NN5++20AQO/evXHhwgWMHTsWNWrUQEJCAnbv3o07d+4U+t0sUNr97YcffsDDhw8xYsQIKBQKzJ49G7169cKNGzdgbGz8zG2tpdRvFXqWmpoqAIju3buXqH1UVJQAIAIDA7WmF4w09u7dq5nm4uIiAIgDBw5opiUkJAilUikmTJigmfbku++TSjriDwsLEwBEYmJisXUXNeJv1KiRqFy5skhOTtZMi46OFgYGBmLQoEGFljdkyBCtPnv27Cns7OyKXeaT61EwOnvvvfdE+/bthRCPR5mOjo5i+vTpRW6DrKysQseSb968KZRKpQgJCdFMe9Yxfl9fXwFArFixosh5T4+Wdu7cKQCIGTNmiBs3bggLCwvRo0eP566jEEWPwBcsWCAAiO+//14zLScnR7Rs2VJYWFiItLQ0zXoBEFZWViIhIeGFl/ekku6rcXFxwsjIqNB6Tps2TWt0LkThEf+ZM2cEAPHTTz89s9bijvE/PeJPSUkRlpaWwtvbW2RmZmq1ffI8QME+lZiYKBITE0VMTIyYO3euUCgUwtPTU9P24cOHwtrautA5uri4OKFSqbSme3l5iWrVqomHDx9qpu3fv1/rU7gQz36t2rdvL7y8vLQ+UanVatGqVStRu3ZtzbSGDRs+87V78OBBic55Pb0Pl3Z/s7OzE/fv39e03bJliwAgfv3112cu92kV7qqetLQ0AIClpWWJ2u/YsQMAEBQUpDW9YJT39LmAevXqaUahwONRYJ06dXDjxo0XrvlpBecGtmzZArVaXaLnxMbGIioqCgEBAVqjygYNGuDtt9/WrOeTRo4cqfX4zTffRHJysmYblsSAAQOwf/9+xMXFYe/evYiLiyt2FKdUKmFg8HiXys/PR3JyMiwsLFCnTh2cPn26xMtUKpUYPHhwidp27NgRI0aMQEhICHr16gVTU1OsXLmyxMt62o4dO+Do6Ij+/ftrphkbG+Ojjz5Ceno6/vzzT632vXv3hoODwwsv7+llA8/fV/fs2YO8vDx8+OGHWu3Gjh373GWoVCoAwM6dO5GRkfHSNe/evRsPHz7ExIkTC51LUCgUWo8fPXoEBwcHODg4wM3NDcHBwfDx8cGWLVs0bXfv3o2UlBT0798fSUlJmh9DQ0N4e3tj3759AB5fGXbu3DkMGjRI6xO3r68vvLy8iqz16dfq/v372Lt3L/r06YOHDx9qlpWcnAw/Pz9cu3YN9+7dA/D4d/bChQu4du1akX2bmZnBxMQE+/fvx4MHD0q8/Uq7v/Xt21fr01FBVpU2nypc8FtZWQEAHj58WKL2t2/fhoGBAdzc3LSmOzo6wtraGrdv39aa/sYbbxTqw8bGplQv5vP07dsXPj4+CAwMRJUqVdCvXz9s2LDhmW8CBXXWqVOn0DwPDw8kJSXh0aNHWtOfXpeCHaY069K5c2dYWlpi/fr1WLt2LZo3b15oWxZQq9UICwtD7dq1oVQqYW9vDwcHB5w9exapqaklXmbVqlVLdRJs7ty5sLW1RVRUFBYtWoTKlSuX+LlPu337NmrXrq15Ayvg4eGhmf8kV1fXF15WUcsuyb5a8O/T7WxtbbVCoSiurq4ICgrCqlWrYG9vDz8/PyxdurRUr8+Trl+/DgDw9PR8bltTU1Ps3r0bu3fvxpo1a+Dh4YGEhASYmZlp2hQE61tvvaV5kyj42bVrFxISEgAUvw2KmwYUfq1iYmIghMCUKVMKLWvq1KkAoFleSEgIUlJS4O7uDi8vL3zyySc4e/aspi+lUomvv/4av/32G6pUqYI2bdpg9uzZiIuLe+Y2Ke3+povfaQCocMf4rays4OzsjPPnz5fqeU+PPopT3BULogR/obK4ZeTn52s9NjMzw4EDB7Bv3z5s374dv//+O9avX4+33noLu3bteuGrJp72MutSQKlUolevXoiIiMCNGzcwbdq0YtvOmjULU6ZMwZAhQ/Dll1/C1tYWBgYG+Pjjj0v8yQaAVhCUxJkzZzS/oOfOndMaPZW10tZaEiXdV1/UvHnzEBAQgC1btmDXrl346KOPEBoaiqNHj6JatWpltlxDQ0N06NBB89jPzw9169bFiBEjsHXrVgDQ7CeRkZFwdHQs1IeR0YtH1tOvVcGygoOD4efnV+RzCt5E2rRpg+vXr2u22apVqxAWFoYVK1YgMDAQAPDxxx+jW7du2Lx5M3bu3IkpU6YgNDQUe/fuRePGjV+47ifp4ncaqIAjfgDo2rUrrl+/jiNHjjy3rYuLC9RqdaGPaPHx8UhJSYGLi4vO6rKxsUFKSkqh6U+/awOPL7Nr37495s+fj4sXL2LmzJnYu3ev5qPs0wrqvHLlSqF5ly9fhr29PczNzV9uBYoxYMAAnDlzBg8fPkS/fv2Kbbdx40a0a9cO3377Lfr164eOHTuiQ4cOhbaJLoPt0aNHGDx4MOrVq4fhw4dj9uzZOHHixAv35+LigmvXrhV6o7p8+bJmflkp6b5a8G9MTIxWu+Tk5BKP/Ly8vDB58mQcOHAABw8exL1797BixQrN/JK+RgUnfUs7EAMAJycnjB8/Hr/++iuOHj2q1V/lypXRoUOHQj8F33otbhsUN60oNWvWBPD40EpRy+rQoYPWIWVbW1sMHjwY69atw927d9GgQYNCA6FatWphwoQJ2LVrF86fP4+cnBzMmzev2Br0tb9VyOD/9NNPYW5ujsDAQMTHxxeaf/36dSxcuBDA40MVALBgwQKtNvPnzwcAdOnSRWd11apVC6mpqVofAWNjYwtdOXT//v1Cz23UqBEAIDs7u8i+nZyc0KhRI0RERGgF6fnz57Fr1y7NepaFdu3a4csvv8SSJUuKHIUVMDQ0LDTy+OmnnzTHSQsUvEEV9SZZWp999hnu3LmDiIgIzJ8/HzVq1IC/v3+x2/F5OnfujLi4OKxfv14zLS8vD4sXL4aFhQV8fX1fuuZnLRt4/r7avn17GBkZYfny5VrtlixZ8txlpKWlIS8vT2ual5cXDAwMtLaZubl5iV6fjh07wtLSEqGhoYWuKCrJKHTs2LGoVKkSvvrqKwCPPwVYWVlh1qxZyM3NLdS+4Ds0zs7O8PT0xHfffYf09HTN/D///BPnzp177nKBx28ubdu2xcqVKxEbG1vssoDHb6pPsrCwgJubm2abZWRkFFr/WrVqwdLS8pn7or72twp3qAd4vEF/+OEH9O3bFx4eHhg0aBA8PT2Rk5ODw4cPay6HAoCGDRvC398f//3vf5GSkgJfX18cP34cERER6NGjB9q1a6ezuvr164fPPvsMPXv2xEcffaS5DM3d3V3r5GZISAgOHDiALl26wMXFBQkJCVi2bBmqVauG1q1bF9v/nDlz8M4776Bly5YYOnSo5nJOlUr1zEMwL8vAwACTJ09+bruuXbsiJCQEgwcPRqtWrXDu3DmsXbtWM7IqUKtWLVhbW2PFihWwtLSEubk5vL29S328fO/evVi2bBmmTp2qubx0zZo1aNu2LaZMmYLZs2eXqj8AGD58OFauXImAgACcOnUKNWrUwMaNG3Ho0CEsWLCgxBcVFCcmJgYzZswoNL1x48bo0qVLifbVKlWqYNy4cZg3bx7effdddOrUCdHR0fjtt99gb2//zNH63r17MWbMGLz//vtwd3dHXl4eIiMjYWhoiN69e2vaNW3aFH/88Qfmz58PZ2dnuLq6wtvbu1B/VlZWCAsLQ2BgIJo3b44BAwbAxsYG0dHRyMjIQERExDO3h52dHQYPHoxly5bh0qVL8PDwwPLly/HBBx+gSZMm6NevHxwcHHDnzh1s374dPj4+mje4WbNmoXv37vDx8cHgwYPx4MEDLFmyBJ6enlpvBs+ydOlStG7dGl5eXhg2bBhq1qyJ+Ph4HDlyBH///Teio6MBPL7oo23btmjatClsbW1x8uRJbNy4EWPGjAEAXL16Fe3bt0efPn1Qr149GBkZ4ZdffkF8fPwzPyWX9f5WrFJdA/SKuXr1qhg2bJioUaOGMDExEZaWlsLHx0csXrxY6/Ks3NxcMX36dOHq6iqMjY1F9erVn/kFrqc9fQlWcZdzCvH4i1menp7CxMRE1KlTR3z//feFLufcs2eP6N69u3B2dhYmJibC2dlZ9O/fX1y9erXQMp6+5PGPP/4QPj4+wszMTFhZWYlu3boV+wWupy8XLe7LN08r7ss2Tyrucs4JEyZovlTk4+Mjjhw5UuRlmFu2bBH16tUTRkZGRX6BqyhP9pOWliZcXFxEkyZNRG5urla78ePHCwMDA3HkyJFnrkNxr3d8fLwYPHiwsLe3FyYmJsLLy6vQ6/CsfeBZy0MRX44CIIYOHSqEKPm+mpeXJ6ZMmSIcHR2FmZmZeOutt8SlS5eEnZ2dGDlypKbd05dz3rhxQwwZMkTUqlVLmJqaCltbW9GuXTvxxx9/aPV/+fJl0aZNG2FmZlaiL3Bt3bpVtGrVSrNftmjRQqxbt04z/1n71PXr14WhoWGhy1D9/PyESqUSpqamolatWiIgIECcPHlS67k//vijqFu3rlAqlcLT01Ns3bpV9O7dW9StW1fT5nmv1fXr18WgQYOEo6OjMDY2FlWrVhVdu3YVGzdu1LSZMWOGaNGihbC2thZmZmaibt26YubMmSInJ0cIIURSUpIYPXq0qFu3rjA3NxcqlUp4e3uLDRs2aC2ruC9wvcz+BkBMnTq1yHUrjuL/n0hEFVxKSgpsbGwwY8YMfP755/ouR28aNWoEBwcH7N69W9+lvLIq5DF+ItkVddfUgnMDr8Jtf8tDbm5uofMV+/fvR3R0tDTb4EVxxE9UAYWHhyM8PFxzy5C//voL69atQ8eOHbFz5059l1cubt26hQ4dOmDgwIFwdnbG5cuXsWLFCqhUKpw/fx52dnb6LvGVVSFP7hLJrkGDBjAyMsLs2bORlpamOeFb1Inj15WNjQ2aNm2KVatWITExEebm5ujSpQu++uorhv5zcMRPRCQZHuMnIpIMg5+ISDIMfiIiybyWJ3fNGo/RdwkkiQcnnn+bBCJdMNVhWnPET0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkGPxERJJh8BMRSYbBT0QkGQY/EZFkjPRdAJUdi0pKTP2wK959qyEcbCwQfeVvBM/eiFMX72ja1HGtghnjeuDNJm4wMjLA5Rtx6B+8CnfjHmjaeDdwxbTRXdHcqwby89U4e/Ueun24FFnZufpYLarAfvxhLSLWfIukpES416mLif+ZAq8GDfRdlnQY/K+x5V8MQD03ZwyZHIHYxFT079wC21eMRZPeM/BPYipcq9ljz+ogRGw+jBnLtyPtURbq1XLSCnTvBq7YsuRDzF2zC0Ff/4S8fDUauFeFWi30uGZUEf3+2w7MnR2KyVOnw8urIdZGRmDUiKHYsu132NnZ6bs8qSiEEK/db7BZ4zH6LkHvTJXGSPxrLt4f/1/8/tcFzfRDaz/FrkMXMX3ZNnz31WDk5uZj6JTviu3nz4gJ2HPsMkKWbS+PsiucByeW6LuECuPf/d5HfU8v/GfyFwAAtVqNju190X/ABxg6bLieq3v1mepwmM5j/K8pI0MDGBkZIitH+3BMVnYuWjWuBYVCgU6t6+PanQRsXToat/eE4sB3wejW9n8fux1sLNCigSsS76djX3gQbv0xC7tWjUOrRjXLe3WogsvNycGlixfwr5atNNMMDAzwr3+1wtnoM3qsTE56Df6kpCTMnj0bPXv2RMuWLdGyZUv07NkTc+bMQWJioj5Lq/DSM7JxNPoGJg17B04OKhgYKNCvc3N4N3CFo70VKttawNLcFMGD38buwxfRbdQSbN0XjR/nBaJ1UzcAgGs1ewDA5yM6Y/XPh9F99DJEXbqLHSvHotYbDvpcPapgHqQ8QH5+fqFDOnZ2dkhKStJTVfLSW/CfOHEC7u7uWLRoEVQqFdq0aYM2bdpApVJh0aJFqFu3Lk6ePPncfrKzs5GWlqb1I9T55bAGr74hk7+DQgHc2DUTqccWYHR/X2z4/STUagEDg8cv/bb957B47T6cvXoPc9fsxo6DFzDsvdYAAAMDBQDg201/IXLrUURf+RufzvsZV28lwL97S72tFxG9HL2d3B07dizef/99rFixAgqFQmueEAIjR47E2LFjceTIkWf2ExoaiunTp2tNM6zSHMZOLXRec0Vz8+8kdAxciEqmJrCyMEVcUhoivxqMm/eSkPQgHbm5+bh0I1brOVduxKFV48eHcmIT0wAAl27Eabe5GYfqjjblsxL0WrCxtoGhoSGSk5O1picnJ8Pe3l5PVclLbyP+6OhojB8/vlDoA4BCocD48eMRFRX13H4mTZqE1NRUrR+jKk3LoOKKKyMrB3FJabC2NEOHVh7Ytv8ccvPyceribbi7VNFqW9ulMu7EPr6U8/Y/yfgnIQXuNSprtXFzqYw7sffLrX6q+IxNTOBRrz6OHf3fQE6tVuPYsSNo0LCxHiuTk95G/I6Ojjh+/Djq1q1b5Pzjx4+jSpUqRc57klKphFKp1JqmMDDUSY0VXYeWHlAogKu3ElCrugNmje+Bqzfj8d3Wx798YRF/IPLrIfjrdAz+PHkVHVvVQ+c2nvAbtlDTR1jEH5g8sgvOXb2H6Ct/Y2A3b9SpUQUDPvlWX6tFFdQH/oMx5T+foX59T3h6NcD3kRHIzMxEj5699F2adPQW/MHBwRg+fDhOnTqF9u3ba0I+Pj4ee/bswTfffIO5c+fqq7zXgsrCFCFj30XVKta4n5qBLXuiMHXpr8jLUwMAtu47i7Ezf8QnQzpi3qfv4ertBPT/ZBUOR93Q9LHkh/0wVRpj9oTesFFVwrmr99B11BLc/Jsn5Kh0Or3TGQ/u38eyJYuQlJSIOnU9sGzlKtjxUE+50+t1/OvXr0dYWBhOnTqF/PzHJ2QNDQ3RtGlTBAUFoU+fPi/UL6/jp/LC6/ipvOjyOv5X4gtcubm5mku67O3tYWxs/FL9MfipvDD4qbzoMvhfiVs2GBsbw8nJSd9lEBFJgd/cJSKSDIOfiEgyDH4iIskw+ImIJMPgJyKSDIOfiEgyDH4iIskw+ImIJMPgJyKSDIOfiEgyDH4iIskw+ImIJMPgJyKSDIOfiEgyDH4iIskw+ImIJMPgJyKSDIOfiEgyDH4iIskw+ImIJMPgJyKSDIOfiEgyDH4iIskw+ImIJMPgJyKSDIOfiEgyDH4iIskw+ImIJMPgJyKSDIOfiEgyDH4iIskw+ImIJMPgJyKSDIOfiEgyDH4iIskw+ImIJGNUkkZnz54tcYcNGjR44WKIiKjslSj4GzVqBIVCASFEkfML5ikUCuTn5+u0QCIi0q0SBf/NmzfLug4iIionJQp+FxeXsq6DiIjKyQud3I2MjISPjw+cnZ1x+/ZtAMCCBQuwZcsWnRZHRES6V+rgX758OYKCgtC5c2ekpKRojulbW1tjwYIFuq6PiIh0rNTBv3jxYnzzzTf4/PPPYWhoqJnerFkznDt3TqfFERGR7pU6+G/evInGjRsXmq5UKvHo0SOdFEVERGWn1MHv6uqKqKioQtN///13eHh46KImIiIqQyW6qudJQUFBGD16NLKysiCEwPHjx7Fu3TqEhoZi1apVZVEjERHpUKmDPzAwEGZmZpg8eTIyMjIwYMAAODs7Y+HChejXr19Z1EhERDqkEMV9HbcEMjIykJ6ejsqVK+uyppdm1niMvksgSTw4sUTfJZAkTEs9TC/eC3eVkJCAK1euAHh8ywYHBwedFUVERGWn1Cd3Hz58iA8++ADOzs7w9fWFr68vnJ2dMXDgQKSmppZFjUREpEOlDv7AwEAcO3YM27dvR0pKClJSUrBt2zacPHkSI0aMKIsaiYhIh0p9jN/c3Bw7d+5E69attaYfPHgQnTp1eiWu5ecxfiovPMZP5UWXx/hLPeK3s7ODSqUqNF2lUsHGxkYnRRERUdkpdfBPnjwZQUFBiIuL00yLi4vDJ598gilTpui0OCIi0r0SfXho3LgxFAqF5vG1a9fwxhtv4I033gAA3LlzB0qlEomJiTzOT0T0iitR8Pfo0aOMyyAiovLyUl/gelXx5C6VF57cpfKi15O7RERUsZX6PSQ/Px9hYWHYsGED7ty5g5ycHK359+/f11lxRESke6Ue8U+fPh3z589H3759kZqaiqCgIPTq1QsGBgaYNm1aGZRIRES6VOrgX7t2Lb755htMmDABRkZG6N+/P1atWoUvvvgCR48eLYsaiYhIh0od/HFxcfDy8gIAWFhYaO7P07VrV2zfvl231RERkc6VOvirVauG2NhYAECtWrWwa9cuAMCJEyegVCp1Wx0REelcqYO/Z8+e2LNnDwBg7NixmDJlCmrXro1BgwZhyJAhOi+QiIh066Wv4z969CgOHz6M2rVro1u3brqq66XwOn4qL7yOn8rLK3Ud/7/+9S8EBQXB29sbs2bN0kVNRERUhnT2Ba7Y2FjepI2IqALgN3eJiCTD4CcikgyDn4hIMiU+TxwUFPTM+YmJiS9djK4kHl2s7xJIEvceZOq7BJJELQcznfVV4uA/c+bMc9u0adPmpYohIqKy91rejz89+7VbJXpFxadl6bsEkoQuR/w8xk9EJBkGPxGRZBj8RESSYfATEUmGwU9EJJkXCv6DBw9i4MCBaNmyJe7duwcAiIyMxF9//aXT4oiISPdKHfybNm2Cn58fzMzMcObMGWRnZwMAUlNTeXdOIqIKoNTBP2PGDKxYsQLffPMNjI2NNdN9fHxw+vRpnRZHRES6V+rgv3LlSpHf0FWpVEhJSdFFTUREVIZKHfyOjo6IiYkpNP2vv/5CzZo1dVIUERGVnVIH/7BhwzBu3DgcO3YMCoUC//zzD9auXYvg4GCMGjWqLGokIiIdKvVfcZw4cSLUajXat2+PjIwMtGnTBkqlEsHBwRg7dmxZ1EhERDr0wjdpy8nJQUxMDNLT01GvXj1YWFjourYXxpu0UXnhTdqovOjyJm28OyfRS2DwU3nRy/34C7Rr1w4KhaLY+Xv37n2pgoiIqGyVOvgbNWqk9Tg3NxdRUVE4f/48/P39dVUXERGVkVIHf1hYWJHTp02bhvT09JcuiIiIypbOjvHHxMSgRYsWuH//vi66eyk8xk/lhcf4qby8kn+B68iRIzA1NdVVd0REVEZKfainV69eWo+FEIiNjcXJkycxZcoUnRVGRERlo9TBr1KptB4bGBigTp06CAkJQceOHXVWGBERlY1SBX9+fj4GDx4MLy8v2NjYlFVNRERUhkp1jN/Q0BAdO3bkXTiJiCqwUp/c9fT0xI0bN8qiFiIiKgcv9IdYgoODsW3bNsTGxiItLU3rh4iIXm0lvo4/JCQEEyZMgKWl5f+e/MStG4QQUCgUyM/P132VpcTr+Km88Dp+Ki96uUmboaEhYmNjcenSpWe28/X11UlhL4PBT+WFwU/lRS83aSt4f3gVgp2IiF5cqY7xP+uunEREVDGU6jp+d3f354b/q3CvHiIiKl6pgn/69OmFvrlLREQVS4lP7hoYGCAuLg6VK1cu65peGk/uUnnhyV0qL3q5OyeP7xMRvR5KHPyv4Z/mJSKSUomP8avV6rKsg4iIyonO/hALERFVDAx+IiLJMPiJiCTD4CcikgyDn4hIMgx+IiLJMPiJiCTD4CcikgyDn4hIMgx+IiLJMPiJiCTD4CcikgyDn4hIMgx+IiLJMPiJiCTD4CcikgyDn4hIMgx+IiLJMPiJiCTD4CcikgyDn4hIMgx+IiLJMPiJiCTD4CcikgyDn4hIMgx+IiLJMPiJiCTD4CcikgyDn4hIMgx+IiLJMPiJiCTD4CcikgyDn4hIMkb6LoDKz+mTJ/Bd+Le4dOkCkhITMXfBErR7q4NmfnJyEhaFzcXRI4fw8OFDNGnSDJ9Omow3XGror2iqEM5FncKmHyIQc+US7icnYvKs+WjV5i3N/O+/XY4De3YiMSEOxkbGcKtTD4OGj0Hd+l6aNg/TUrE87CscO3QABgYK+Ph2wIhxn8KsUiV9rNJrjSN+iWRmZsK9Tl189p8vCs0TQmDCuNG49/ffmL9wGX5Y/zOcnJ0xavgQZGZk6KFaqkiyMjPh6uaOD4MmFTm/anUXjBo/EcsiNmLOsjWo7OSMyUGjkPrgvqbN7On/wZ2b1zEzbAWmfb0Y56NPYdHskPJaBalwxC8RnzfbwOfNNkXOu3P7Fs6djcaGn39FLbfaAIBJk6ehY7vW+P237ejZ+/3yLJUqmOYtW6N5y9bFzm/XsbPW4+FjJ2DXtl9w8/o1NGrmjTu3buDUsUNYsGot3OvWBwCM/Hgipn4yBoFjgmBnX7lM65cNR/wEAMjJyQEAmCiVmmkGBgYwMTFB1JlT+iqLXkO5ubn4bcsmmFtYwNXNHQBw+fxZWFhYakIfABo384bCwABXLpzXV6mvLQY/AQBquNaEo5Mzliycj7S0VOTm5iB89TeIj49DUlKivsuj18CxQwfQ6+2W6PFWC2ze8D1mhq2AytoGAPDgfhJUNrZa7Q2NjGBpaYUH95P0Ue5r7ZUO/rt372LIkCHPbJOdnY20tDStn+zs7HKq8PVhbGyMuWGLcOf2LbRr7Q2fFo1x8vgx+LRuAwPFK72bUAXRsElzLFmzHvOWR6Cptw9Cv/gUKU8c46fy80r/Rt+/fx8RERHPbBMaGgqVSqX1M292aDlV+HrxqOeJdT9txv5DJ7Bzz0EsWbEKKSkpqFqtur5Lo9eAqZkZnKu9gbqeDfDxpGkwNDTEzm2/AABsbO21TvQCQH5eHh4+TIONrb0+yn2t6fXk7tatW585/8aNG8/tY9KkSQgKCtKalguTl6pLdpaWlgAen/C9dPE8Ro35SM8V0etIrRbI/f9zS3U9GyA9/SGuXb6I2nXrAQCiTx+HUKtRp76nPst8Lek1+Hv06AGFQgEhRLFtFArFM/tQKpVQPnFCEgDSs4vvT2YZGY9w984dzeN/7v2NK5cvwUqlgpOTM3bv+h02NjZwdHJGzLWrmPv1TLRt1x4tWxV/tQYRAGRmZOCfe//bt+Jj7+H6tcuwtFTBSmWNH7/7Bv/yaQsbe3ukpaRg28/rkZyUgDfbvQ0AeKNGTTT19sGi2SEYE/w58vLysGz+V2jT3o9X9JQBhXhW6paxqlWrYtmyZejevXuR86OiotC0aVPk5+eXql8Gf9FOnjiGEUP9C03v+m4PTJ/xFdat/Q6R4auRnJwMewcHdOnWHcNGjIKxMT9BFSc+LUvfJbwSzp4+gYkfDSs0vcM73TAmeDJmT5+EKxfPITU1BVZW1nD3qI9+/oFw9/jfaP5hWiqWzQ/F8UMHoDAwgI9ve4z8+DN+gev/1XIw01lfeg3+d999F40aNUJISNFf0oiOjkbjxo2hVqtL1S+Dn8oLg5/Kiy6DX6+Hej755BM8evSo2Plubm7Yt29fOVZERPT60+uIv6xwxE/lhSN+Ki+6HPG/0pdzEhGR7jH4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkw+AnIpIMg5+ISDIMfiIiyTD4iYgkoxBCCH0XQfqXnZ2N0NBQTJo0CUqlUt/l0GuM+5r+MfgJAJCWlgaVSoXU1FRYWVnpuxx6jXFf0z8e6iEikgyDn4hIMgx+IiLJMPgJAKBUKjF16lSebKMyx31N/3hyl4hIMhzxExFJhsFPRCQZBj8RkWQY/EREkmHwE5YuXYoaNWrA1NQU3t7eOH78uL5LotfQgQMH0K1bNzg7O0OhUGDz5s36LklaDH7JrV+/HkFBQZg6dSpOnz6Nhg0bws/PDwkJCfoujV4zjx49QsOGDbF06VJ9lyI9Xs4pOW9vbzRv3hxLliwBAKjValSvXh1jx47FxIkT9Vwdva4UCgV++eUX9OjRQ9+lSIkjfonl5OTg1KlT6NChg2aagYEBOnTogCNHjuixMiIqSwx+iSUlJSE/Px9VqlTRml6lShXExcXpqSoiKmsMfiIiyTD4JWZvbw9DQ0PEx8drTY+Pj4ejo6OeqiKissbgl5iJiQmaNm2KPXv2aKap1Wrs2bMHLVu21GNlRFSWjPRdAOlXUFAQ/P390axZM7Ro0QILFizAo0ePMHjwYH2XRq+Z9PR0xMTEaB7fvHkTUVFRsLW1xRtvvKHHyuTDyzkJS5YswZw5cxAXF4dGjRph0aJF8Pb21ndZ9JrZv38/2rVrV2i6v78/wsPDy78giTH4iYgkw2P8RESSYfATEUmGwU9EJBkGPxGRZBj8RESSYfATEUmGwU9EJBkGPxGRZBj89NoKCAjQ+kMfbdu2xccff1zudezfvx8KhQIpKSlltoyn1/VFlEed9Gpg8FO5CggIgEKhgEKhgImJCdzc3BASEoK8vLwyX/bPP/+ML7/8skRtyzsEa9SogQULFpTLsoh4kzYqd506dcKaNWuQnZ2NHTt2YPTo0TA2NsakSZMKtc3JyYGJiYlOlmtra6uTfogqOo74qdwplUo4OjrCxcUFo0aNQocOHbB161YA/ztkMXPmTDg7O6NOnToAgLt376JPnz6wtraGra0tunfvjlu3bmn6zM/PR1BQEKytrWFnZ4dPP/0UT9+G6ulDPdnZ2fjss89QvXp1KJVKuLm54dtvv8WtW7c0NxOzsbGBQqFAQEAAgMe3rQ4NDYWrqyvMzMzQsGFDbNy4UWs5O3bsgLu7O8zMzNCuXTutOl9Efn4+hg4dqllmnTp1sHDhwiLbTp8+HQ4ODrCyssLIkSORk5OjmVeS2kkOHPGT3pmZmSE5OVnzeM+ePbCyssLu3bsBALm5ufDz80PLli1x8OBBGBkZYcaMGejUqRPOnj0LExMTzJs3D+Hh4Vi9ejU8PDwwb948/PLLL3jrrbeKXe6gQYNw5MgRLFq0CA0bNsTNmzeRlJSE6tWrY9OmTejduzeuXLkCKysrmJmZAQBCQ0Px/fffY8WKFahduzYOHDiAgQMHwsHBAb6+vrh79y569eqF0aNHY/jw4Th58iQmTJjwUttHrVajWrVq+Omnn2BnZ4fDhw9j+PDhcHJyQp8+fbS2m6mpKfbv349bt25h8ODBsLOzw8yZM0tUO0lEEJUjf39/0b17dyGEEGq1WuzevVsolUoRHBysmV+lShWRnZ2teU5kZKSoU6eOUKvVmmnZ2dnCzMxM7Ny5UwghhJOTk5g9e7Zmfm5urqhWrZpmWUII4evrK8aNGyeEEOLKlSsCgNi9e3eRde7bt08AEA8ePNBMy8rKEpUqVRKHDx/Wajt06FDRv39/IYQQkyZNEvXq1dOa/9lnnxXq62kuLi4iLCys2PlPGz16tOjdu7fmsb+/v7C1tRWPHj3STFu+fLmwsLAQ+fn5Jaq9qHWm1xNH/FTutm3bBgsLC+Tm5kKtVmPAgAGYNm2aZr6Xl5fWcf3o6GjExMTA0tJSq5+srCxcv34dqampiI2N1fobAkZGRmjWrFmhwz0FoqKiYGhoWKqRbkxMDDIyMvD2229rTc/JyUHjxo0BAJcuXSr0twx08dfMli5ditWrV+POnTvIzMxETk4OGjVqpNWmYcOGqFSpktZy09PTcffuXaSnpz+3dpIHg5/KXbt27bB8+XKYmJjA2dkZRkbau6G5ubnW4/T0dDRt2hRr164t1JeDg8ML1VBw6KY00tPTAQDbt29H1apVteYplcoXqqMkfvzxRwQHB2PevHlo2bIlLC0tMWfOHBw7dqzEfeirdno1Mfip3Jmbm8PNza3E7Zs0aYL169ejcuXKsLKyKrKNk5MTjh07hjZt2gAA8vLycOrUKTRp0qTI9l5eXlCr1fjzzz/RoUOHQvMLPnHk5+drptWrVw9KpRJ37twp9pOCh4eH5kR1gaNHjz5/JZ/h0KFDaNWqFT788EPNtOvXrxdqFx0djczMTM2b2tGjR2FhYYHq1avD1tb2ubWTPHhVD73y/v3vf8Pe3h7du3fHwYMHcfPmTezfvx8fffQR/v77bwDAuHHj8NVXX2Hz5s24fPkyPvzww2deg1+jRg34+/tjyJAh2Lx5s6bPDRs2AABcXFygUCiwbds2JCYmIj09HZaWlggODsb48eMRERGB69ev4/Tp01i8eDEiIiIAACNHjsS1a9fwySef4MqVK/jhhx9K/GcF7927h6ioKK2fBw8eoHbt2jh58iR27tyJq1evYsqUKThx4kSh5+fk5GDo0KG4ePEiduzYgalTp2LMmDEwMDAoUe0kEX2fZCC5PHlytzTzY2NjxaBBg4S9vb1QKpWiZs2aYtiwYSI1NVUI8fhk7rhx44SVlZWwtrYWQUFBYtCgQcWe3BVCiMzMTDF+/Hjh5OQkTExMhJubm1i9erVmfkhIiHB0dBQKhUL4+/sLIR6fkF6wYIGoU6eOMDY2Fg4ODsLPz0/8+eefmuf9+uuvws3NTSiVSvHmm2+K1atXl+jkLoBCP5GRkSIrK0sEBAQIlUolrK2txahRo8TEiRNFw4YNC223L774QtjZ2QkLCwsxbNgwkZWVpWnzvNp5clce/Ju7RESS4aEeIiLJMPiJiCTD4CcikgyDn4hIMgx+IiLJMPiJiCTD4CcikgyDn4hIMgx+IiLJMPiJiCTD4Cciksz/AYOqo4hmVaVoAAAAAElFTkSuQmCC\n"
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Best LogisticRegression params: {'solver': 'liblinear'}\n",
            "              precision    recall  f1-score   support\n",
            "\n",
            "         ham       0.98      1.00      0.99       966\n",
            "        spam       1.00      0.87      0.93       149\n",
            "\n",
            "    accuracy                           0.98      1115\n",
            "   macro avg       0.99      0.94      0.96      1115\n",
            "weighted avg       0.98      0.98      0.98      1115\n",
            "\n"
          ]
        }
      ],
      "source": [
        "\n",
        "# Bag-of-Words feature representation\n",
        "# -------------------------------------------------------------\n",
        "vectorizer_bow = CountVectorizer()\n",
        "X_train_bow = vectorizer_bow.fit_transform(X_train)\n",
        "X_test_bow = vectorizer_bow.transform(X_test)\n",
        "\n",
        "# Random Forest with hyperparameter tuning\n",
        "rf_classifier = RandomForestClassifier(random_state=42)\n",
        "rf_param_grid = {\n",
        "    'n_estimators': [100, 200],\n",
        "    'max_depth': [None, 10, 20]\n",
        "}\n",
        "rf_grid = GridSearchCV(estimator=rf_classifier, param_grid=rf_param_grid, cv=5, scoring='accuracy', n_jobs=-1)\n",
        "rf_grid.fit(X_train_bow, y_train)\n",
        "best_rf = rf_grid.best_estimator_\n",
        "y_pred_rf = best_rf.predict(X_test_bow)\n",
        "metrics_rf = evaluate_model('RandomForestClassifier', y_test, y_pred_rf)\n",
        "print(\"Best RandomForest params:\", rf_grid.best_params_)\n",
        "print(metrics_rf['Classification Report'])\n",
        "\n",
        "# Logistic Regression with hyperparameter tuning (solver)\n",
        "log_reg = LogisticRegression(max_iter=1000, random_state=42)\n",
        "log_param_grid = {\n",
        "    'solver': ['liblinear', 'lbfgs']\n",
        "}\n",
        "log_grid = GridSearchCV(estimator=log_reg, param_grid=log_param_grid, cv=5, scoring='accuracy', n_jobs=-1)\n",
        "log_grid.fit(X_train_bow, y_train)\n",
        "best_log = log_grid.best_estimator_\n",
        "y_pred_log = best_log.predict(X_test_bow)\n",
        "metrics_log = evaluate_model('LogisticRegression', y_test, y_pred_log)\n",
        "print(\"Best LogisticRegression params:\", log_grid.best_params_)\n",
        "print(metrics_log['Classification Report'])\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "ba72fc29",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000
        },
        "id": "ba72fc29",
        "outputId": "10835404-f988-4026-8abb-33382b67c6ed"
      },
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 400x400 with 1 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYsAAAGJCAYAAAB7KB+AAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAANvNJREFUeJzt3XlYVGX/P/D3gDAg+yriguKOCyqaKSpuSW65ZmomoLimGYuVP1MRFyotNJfU3HjUfNxSSy13y4zc0UpSVNI0QBYBkZ25f3/4ZR6HGbhBgUF9v66L63LOueecz7k9w/ucc58zKIQQAkRERCUw0HcBRERU9TEsiIhIimFBRERSDAsiIpJiWBARkRTDgoiIpBgWREQkxbAgIiIphgUREUkxLADExMSgd+/esLKygkKhwN69e8t1+X///TcUCgU2bdpUrst9nnXr1g3dunUrt+VlZGTA398fTk5OUCgUeP/998tt2VWRr68v6tWrV6b3nDx5EgqFAidPnqyQmp535b1PllVISAgUCoXGtPz8fHzwwQeoU6cODAwMMGjQIACAQqFASEhIpdZXZcLi5s2bmDhxIlxdXWFiYgJLS0t4enpi2bJlyMrKqtB1+/j44Pfff8fChQuxefNmtGvXrkLXV5l8fX2hUChgaWmpsx9jYmKgUCigUCiwZMmSMi//33//RUhICKKiosqh2qe3aNEibNq0CZMnT8bmzZvxzjvvVOj66tWrp+43AwMDWFtbo2XLlpgwYQLOnDlToeuuqgr3NdmPr69vpdaVkJCA4OBgNG3aFNWrV4eZmRk8PDywYMECpKamVmotZbVhwwYsXrwYw4YNQ0REBAICAvRWi6IqfDfUgQMH8Oabb0KpVGLMmDFo0aIFcnNz8csvv2D37t3w9fXF2rVrK2TdWVlZqF69OmbNmoUFCxZUyDqEEMjJyYGRkREMDQ0rZB3F8fX1xdatWyGEwDfffIPhw4drzA8JCcGnn36K7OxsLF68GMHBwWVa/vnz59G+fXts3LixTL8EcnNzAQDGxsZlWl9xXn31VVSrVg2//PJLuSxPpl69erCxsUFQUBAA4OHDh4iOjsbOnTsRHx+PgIAAfPHFFxW2/ry8PKhUKiiVylK/R6VSITc3F8bGxjAwKP/jxMjISNy8eVP9OjY2FnPmzMGECRPQpUsX9fQGDRqgY8eO5b5+Xc6dO4e+ffsiIyMDo0ePhoeHB4DH++1///tfdOrUCYcPHwYA9VmFvs688vPzkZ+fDxMTE/W0ESNG4JdffsHdu3c12mZnZ6NatWqoVq1a5RUo9OzWrVvC3NxcNG3aVPz7779a82NiYsTSpUsrbP23b98WAMTixYsrbB365OPjI8zMzETv3r3FoEGDtOY3atRIDB069Kn74Ny5cwKA2LhxY6naP3r0qMzrKI369euLfv36ldvy8vLyRE5OTrHzXVxcdK4vMzNTDBo0SAAQq1atKrd6nkel3TcyMjIqZP0PHjwQtWrVEjVq1BDR0dFa8+Pj48X8+fPVr728vISXl1eF1PK0unfvLpo3b16h68jKyhIFBQXSdnoPi0mTJgkA4vTp06Vqn5eXJ0JDQ4Wrq6swNjYWLi4uYubMmSI7O1ujXeGH+dSpU6J9+/ZCqVSK+vXri4iICHWbuXPnCgAaPy4uLkKIx79kC//9pML3POnw4cPC09NTWFlZCTMzM9G4cWMxc+ZM9fzY2FidH5pjx46Jzp07i+rVqwsrKyvxxhtviKtXr+pcX0xMjPDx8RFWVlbC0tJS+Pr6luoXb2FYbNq0SSiVSvHgwQP1vLNnzwoAYvfu3VphkZycLIKCgkSLFi2EmZmZsLCwEK+//rqIiopStzlx4oRW/z25nV5eXqJ58+bi/PnzokuXLsLU1FRMnz5dPe/JD+aYMWOEUqnU2v7evXsLa2trce/ePZ3bV1wNsbGxQgghEhISxNixY4Wjo6NQKpWiVatWYtOmTRrLKPz/Wbx4sQgPDxeurq7CwMBAXLp0qdh+LS4shBDi4cOHwtbWVtSqVUuoVCr19IKCAhEeHi7c3NyEUqkUjo6OYsKECSIlJUVrGQcPHhRdu3YV5ubmwsLCQrRr105s3bpVPV/X/rlt2zbRtm1b9XtatGihcaBV2FcnTpzQeN+OHTtE27ZthYmJibCzsxNvv/22uHv3rkabwv3o7t27YuDAgcLMzEzY29uLoKAgkZ+fr7MfdIXFxo0bBQBx8uRJMXnyZOHg4CCsra01trvwM2Fubi769u0r/vjjD61lR0dHi6FDhwobGxuhVCqFh4eH2Ldvn0abTz75RADQ6LeSFN0nc3JyxOzZs0Xbtm2FpaWlqF69uujcubM4fvy41ntlfZ+bmytCQkJEw4YNhVKpFLa2tsLT01McPnxY3ebJ3y2F+2TRn8L/OwBi7ty5GjXcvXtX+Pn5CUdHR2FsbCzc3NzE+vXrNdoU7gPbtm0Ts2bNEs7OzkKhUGj8XihOJZ7D6Pb999/D1dUVnTp1KlV7f39/REREYNiwYQgKCsKZM2cQFhaG6Oho7NmzR6PtjRs3MGzYMIwbNw4+Pj7YsGEDfH194eHhgebNm2PIkCGwtrZGQEAARo4cib59+8Lc3LxM9f/555/o378/WrVqhdDQUCiVSty4cQOnT58u8X1Hjx5Fnz594OrqipCQEGRlZWH58uXw9PTExYsXtQYvhw8fjvr16yMsLAwXL17EunXr4OjoiE8//bRUdQ4ZMgSTJk3Ct99+i7FjxwIAvvnmGzRt2hRt27bVan/r1i3s3bsXb775JurXr4+EhASsWbMGXl5euHr1KpydndGsWTOEhoZqXWp48v8yOTkZffr0wYgRIzB69GjUqFFDZ33Lli3D8ePH4ePjg8jISBgaGmLNmjU4fPgwNm/eDGdnZ53va9asGTZv3oyAgADUrl1bfVnIwcEBWVlZ6NatG27cuIGpU6eifv362LlzJ3x9fZGamorp06drLGvjxo3Izs7GhAkToFQqYWtrW6q+Lcrc3ByDBw/G+vXrcfXqVTRv3hwAMHHiRGzatAl+fn547733EBsbixUrVuDSpUs4ffo0jIyMAACbNm3C2LFj0bx5c8ycORPW1ta4dOkSfvzxR4waNUrnOo8cOYKRI0eiZ8+e6n0iOjoap0+f1trOJxXW0759e4SFhSEhIQHLli3D6dOncenSJVhbW6vbFhQUwNvbGx06dMCSJUtw9OhRfP7552jQoAEmT55cpj6aMmUKHBwcMGfOHDx69AgAsHnzZvj4+MDb2xuffvopMjMz8dVXX6Fz5864dOmS+jPx559/wtPTE7Vq1cJHH30EMzMz7NixA4MGDcLu3bsxePBgAMB3330HU1NTDBs2rEy1FUpPT8e6deswcuRIjB8/Hg8fPsT69evh7e2Ns2fPonXr1gBK1/chISEICwuDv78/XnnlFaSnp+P8+fO4ePEiXnvtNa11Ozg4YPPmzVi4cCEyMjIQFhYG4PH+rktCQgJeffVVKBQKTJ06FQ4ODvjhhx8wbtw4pKena93wMX/+fBgbGyM4OBg5OTmluxwsjZMKlJaWJgCIgQMHlqp9VFSUACD8/f01pgcHBwsAGonv4uIiAIiff/5ZPe3+/ftCqVSKoKAg9bQnjyqfVNozi/DwcAFAJCYmFlu3rjOL1q1bC0dHR5GcnKyedvnyZWFgYCDGjBmjtb6xY8dqLHPw4MHCzs6u2HU+uR1mZmZCCCGGDRsmevbsKYR4fJTr5OQk5s2bp7MPsrOztU5NY2NjhVKpFKGhoeppJV1q8PLyEgDE6tWrdc4resp/6NAhAUAsWLBAfXlS16UzXXQd6S9dulQAEFu2bFFPy83NFR07dhTm5uYiPT1dvV0AhKWlpbh///5Tr+9JhftF4dHuqVOndB7l/vjjjxrTU1NThYWFhejQoYPIysrSaPvkWUrR/XP69OnC0tKy2KN8IbTPLHJzc4Wjo6No0aKFxrr2798vAIg5c+ZorA+Axv+9EEK0adNGeHh46FxfSWcWnTt31qj14cOHwtraWowfP15jGfHx8cLKykpjes+ePUXLli01riaoVCrRqVMn0ahRI/U0Gxsb4e7uXmx/FFV0n8zPz9e6FPngwQNRo0YNjc9jafre3d1deplU11WLwrPzolDkzGLcuHGiZs2aIikpSaPdiBEjhJWVlcjMzBRC/G8fcHV1VU8rLb3eDZWeng4AsLCwKFX7gwcPAgACAwM1phceTR44cEBjupubm8bAmoODA5o0aYJbt249dc1FFR557du3DyqVqlTviYuLQ1RUFHx9fTWOXlu1aoXXXntNvZ1PmjRpksbrLl26IDk5Wd2HpTFq1CicPHkS8fHxOH78OOLj44s9UlUqlepB0IKCAiQnJ8Pc3BxNmjTBxYsXS71OpVIJPz+/UrXt3bs3Jk6ciNDQUAwZMgQmJiZYs2ZNqddV1MGDB+Hk5ISRI0eqpxkZGeG9995DRkYGfvrpJ432Q4cOhYODw1Ov70mFZ6gPHz4EAOzcuRNWVlZ47bXXkJSUpP7x8PCAubk5Tpw4AeDxUerDhw/x0UcfaQx0AtC6rfJJ1tbWePToEY4cOVLqGs+fP4/79+9jypQpGuvq168fmjZtqvV5AnTvh0/zeRo/frzGzR5HjhxBamoqRo4cqdE/hoaG6NChg7p/UlJScPz4cQwfPhwPHz5Ut0tOToa3tzdiYmJw7949AI9/v5T2d4suhoaG6iNulUqFlJQU5Ofno127dhqfgdL0vbW1Nf7880/ExMQ8dT3FEUJg9+7dGDBgAIQQGv3n7e2NtLQ0rc+sj48PTE1Ny7QevYaFpaUlgP99oGRu374NAwMDNGzYUGO6k5MTrK2tcfv2bY3pdevW1VqGjY0NHjx48JQVa3vrrbfg6ekJf39/1KhRAyNGjMCOHTtKDI7COps0aaI1r1mzZkhKSlKfmhcqui02NjYAUKZt6du3LywsLLB9+3Zs3boV7du31+rLQiqVCuHh4WjUqBGUSiXs7e3h4OCAK1euIC0trdTrrFWrVpnueFqyZAlsbW0RFRWFL7/8Eo6OjqV+b1G3b99Go0aNtO78KTyVL7q/1K9f/6nXVVRGRgaA/x0IxcTEIC0tDY6OjnBwcND4ycjIwP379wFAfTdRixYtyrS+KVOmoHHjxujTpw9q166NsWPH4scffyzxPSXth02bNtXqHxMTE60wfdrPU9G+Lvwl2qNHD63+OXz4sLp/bty4ASEEZs+erdVu7ty5AKBua2lpWerfLcWJiIhAq1atYGJiAjs7Ozg4OODAgQMan4HS9H1oaChSU1PRuHFjtGzZEjNmzMCVK1eeqbZCiYmJSE1Nxdq1a7X6pPBArbBPCj3Nvq7XMQtLS0s4Ozvjjz/+KNP7SjrCelJxt6mKUtwtXNw6CgoKNF6bmpri559/xokTJ3DgwAH8+OOP2L59O3r06IHDhw+X262yz7IthZRKJYYMGYKIiAjcunWrxId6Fi1ahNmzZ2Ps2LGYP38+bG1tYWBggPfff7/UZ1AAynz0cunSJfWO/fvvv2ucFVS0stZaksJ9ujCMVSoVHB0dsXXrVp3tn/WMxtHREVFRUTh06BB++OEH/PDDD9i4cSPGjBmDiIiIZ1p2ofK87btoXxfuU5s3b4aTk5NW+8JbRAvbBQcHw9vbW+eyC/u8adOmiIqKUt8uXFZbtmyBr68vBg0ahBkzZsDR0RGGhoYICwvTuEW4NH3ftWtX3Lx5E/v27cPhw4exbt06hIeHY/Xq1fD39y9zbU8q7JPRo0fDx8dHZ5tWrVppvH6afV3vA9z9+/fH2rVrERkZKb332sXFBSqVCjExMRoDPQkJCUhNTYWLi0u51WVjY6PzgZ2iR1sAYGBggJ49e6Jnz5744osvsGjRIsyaNQsnTpxAr169dG4HAFy7dk1r3l9//QV7e3uYmZk9+0boMGrUKGzYsAEGBgYYMWJEse127dqF7t27Y/369RrTU1NTYW9vr35d2uAujUePHsHPzw9ubm7o1KkTPvvsMwwePBjt27d/quW5uLjgypUrUKlUGmcXf/31l3p+RcjIyMCePXtQp04d9X7aoEEDHD16FJ6eniV+UBs0aADgcdgUd9ZXHGNjYwwYMAADBgyASqXClClTsGbNGsyePVvnsp7cD3v06KEx79q1axXWP7oUbrejo6POz0whV1dXAI8vJ5bUDgAGDBiAyMhI7N69+6kOOnbt2gVXV1d8++23Gvt54RnMk0rT97a2tvDz84Ofnx8yMjLQtWtXhISEPHNYODg4wMLCAgUFBdI+eRZ6f4L7gw8+gJmZGfz9/ZGQkKA1/+bNm1i2bBmAx5dRAGDp0qUabQoffurXr1+51dWgQQOkpaVpnCrGxcVp3XGVkpKi9d7CuyRycnJ0LrtmzZpo3bo1IiIiNALpjz/+wOHDh9XbWRG6d++O+fPnY8WKFTqP4AoZGhpqnbXs3LlTfT24UGGolceTsB9++CHu3LmDiIgIfPHFF6hXrx58fHyK7UeZvn37Ij4+Htu3b1dPy8/Px/Lly2Fubg4vL69nrrmorKwsvPPOO0hJScGsWbPUv2SGDx+OgoICzJ8/X+s9+fn56v7r3bs3LCwsEBYWhuzsbI12JZ1FJicna7w2MDBQH00W13/t2rWDo6MjVq9erdHmhx9+QHR0dLl+nmS8vb1haWmJRYsWIS8vT2t+YmIigMdh0q1bN6xZswZxcXHFtgMej6/UrFkTQUFBuH79ulbb+/fvl/ggbuGZ1JP9fubMGURGRmq0K03fF21jbm6Ohg0bPvW+XbTOoUOHYvfu3Tqv0jzZJ89C72cWDRo0wDfffIO33noLzZo103iC+9dff1Xf6ggA7u7u8PHxwdq1a5GamgovLy+cPXsWERERGDRoELp3715udY0YMQIffvghBg8ejPfee099G1/jxo01BotCQ0Px888/o1+/fnBxccH9+/exatUq1K5dG507dy52+YsXL0afPn3QsWNHjBs3Tn3rrJWVVYV+54uBgQE+/vhjabv+/fsjNDQUfn5+6NSpE37//Xds3bpVfWRXqEGDBrC2tsbq1athYWEBMzMzdOjQoczXRI8fP45Vq1Zh7ty56lt5N27ciG7dumH27Nn47LPPyrQ8AJgwYQLWrFkDX19fXLhwAfXq1cOuXbtw+vRpLF269JkGPwHg3r172LJlC4DHZxNXr15VP8EdFBSEiRMnqtt6eXlh4sSJCAsLQ1RUFHr37g0jIyPExMRg586dWLZsGYYNGwZLS0uEh4fD398f7du3x6hRo2BjY4PLly8jMzOz2EtK/v7+SElJQY8ePVC7dm3cvn0by5cvR+vWrYu93dLIyAiffvop/Pz84OXlhZEjR6pvna1Xr16lfrWEpaUlvvrqK7zzzjto27YtRowYAQcHB9y5cwcHDhyAp6cnVqxYAQBYuXIlOnfujJYtW2L8+PFwdXVFQkICIiMjcffuXVy+fBnA46sDe/bsQd++fdG6dWuNJ7gvXryIbdu2lXg1o3///vj2228xePBg9OvXD7GxsVi9ejXc3NzUY1JA6frezc0N3bp1g4eHB2xtbXH+/Hns2rULU6dOLZf+++STT3DixAl06NAB48ePh5ubG1JSUnDx4kUcPXpU50FtmZXp3qkKdP36dTF+/HhRr149YWxsLCwsLISnp6dYvny5xi1yeXl5Yt68eaJ+/frCyMhI1KlTp8SH8ooqentccbfOCvH4YbsWLVoIY2Nj0aRJE7Flyxat29uOHTsmBg4cKJydnYWxsbFwdnYWI0eOFNevX9daR9HbS48ePSo8PT2FqampsLS0FAMGDCj2obyit+YW3oJY+PBZcZ68dbY4xd06GxQUJGrWrClMTU2Fp6eniIyM1HnL6759+4Sbm5uoVq2azofydHlyOenp6cLFxUW0bdtW5OXlabQLCAgQBgYGIjIyssRtKO7/OyEhQfj5+Ql7e3thbGwsWrZsqfX/UNI+UNL68H8PSikUCmFpaSmaN28uxo8fL86cOVPs+9auXSs8PDyEqampsLCwEC1bthQffPCB1rcXfPfdd6JTp07qfeOVV14R27ZtU88veuvsrl27RO/evdUPZNWtW1dMnDhRxMXFqdsU91De9u3bRZs2bdQPi5X0UF5Rum73LFTSrbPnzp3T+Z4TJ04Ib29vYWVlJUxMTESDBg2Er6+vOH/+vEa7mzdvijFjxggnJydhZGQkatWqJfr37y927dqltcx///1XBAQEiMaNGwsTExNRvXp14eHhIRYuXCjS0tLU7Yru2yqVSixatEi4uLgIpVIp2rRpI/bv3/9Ufb9gwQLxyiuvCGtra2FqaiqaNm0qFi5cKHJzc0vsy9LeOivE43393XffFXXq1BFGRkbCyclJ9OzZU6xdu1ajfwGInTt36uz/klSJ74YiIqKqTe9jFkREVPUxLIiISIphQUREUgwLIiKSYlgQEZEUw4KIiKQYFkREJKX3J7grgmmb8nkqkkjmwbkV+i6BXhImev5tzTMLIiKSYlgQEZEUw4KIiKQYFkREJMWwICIiKYYFERFJMSyIiEiKYUFERFIMCyIikmJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpJiWBARkRTDgoiIpBgWREQkxbAgIiIphgUREUkxLIiISIphQUREUgwLIiKSYlgQEZEUw4KIiKQYFkREJMWwICIiKYYFERFJMSyIiEiKYUFERFIMCyIikmJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpJiWBARkRTDgoiIpBgWREQkxbAgIiIphgUREUkxLIiISIphQUREUgwLIiKSYlgQEZEUw4KIiKQYFkREJMWwICIiKYYFERFJMSyIiEiKYUFERFIMCyIikmJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpJiWBARkRTDgoiIpBgWREQkxbAgIiIphgUREUlV03cBVHHMqysxd0p/vNHDHQ425rh87S6CP9uFC1fvAADWzhuNd954VeM9h09fxcCpq9Svdy6dCPfGteBga4EH6Zk4ceYaPv5yH+IS0yp1W+j5c+H8OWzasB7RV/9AYmIiwr9ciR49e6nnf7VyOX784QDi4+NhZGQEN7fmmDo9AK1aueuxaioOw+IF9tWcUXBr6IyxH0cgLjENI/u+ggOrp6Ht0AX49/9+2R86/Scmzt2ifk9Obr7GMn4+dx2L1x9CfFIanB2tERYwGN8sHofuvl9U6rbQ8ycrKxNNmjTBoCFDETh9qtZ8F5d6mDlrDmrXroPsnGxs+c8mTB4/Ft//cAS2trZ6qJhKwrB4QZkojTCoZ2u8GbAWpy/eBAAsXHMQfbu2wPg3u2Deqv0AgNzcfCQkPyx2Ocu3nlD/+07cAyzZeAQ7vhiPatUMkJ+vqtiNoOda5y5e6NzFq9j5ffsP0Hgd/MFM7Nm9CzHXr6HDqx0rujwqI4bFC6qaoQGqVTNEdm6exvTsnDx0atNA/bpLu0a4fSwMqemZOHnuOuat3I+UtEc6l2ljWR0j+rTDb5djGRRUrvJyc7F753ZYWFigcZMm+i6HdNBrWCQlJWHDhg2IjIxEfHw8AMDJyQmdOnWCr68vHBwc9Fnecy0jMwe/Xb6FmeP74FpsAhKS0zH89Xbo0Ko+bv6TCAA48ms09h2/jL/vJcO1tj3mTRuAfSsmw8vnc6hUQr2sBe8NxKQRXWFmqsSZK7EY8t5qfW0WvWB+OnkCHwYHIjs7C/YODlj99QbY2PASVFWkEEIIebPyd+7cOXh7e6N69ero1asXatSoAQBISEjAsWPHkJmZiUOHDqFdu3YlLicnJwc5OTka0xy7fAiFgWGF1f68qF/bHmtC3kYXj0bIzy9A1F//IOb2fbRpVhdthi7Qal+vlh2i989Dn4lf4uTZ6+rpdtZmsLE0Q92atpg1sQ/SMrIYGP/nwbkV+i7hueDevInWADcAZGZmIikxEampD7B71w6cPfMbtmzbCTs7Oz1VWnWZ6Pk6kN5WP23aNLz55ptYvXo1FAqFxjwhBCZNmoRp06YhMjKyxOWEhYVh3rx5GtMMa7SHUc1Xyr3m503s3ST09l+G6ibGsDQ3QXxSOjZ/4ofYe0k62/99LxmJDx6iQR0HjbBITn2E5NRHuHHnPq7FxuPGoQXo0Ko+zlyJraxNoRdU9erVUdfFBXVdXNDKvTUG9OmNvd/uwrjxE/VdGhWht+csLl++jICAAK2gAACFQoGAgABERUVJlzNz5kykpaVp/FSr4VEBFT+/MrNzEZ+UDmsLU/Tq1Az7T/6us10tR2vYWZkhPim92GUZGDz+/zI24nAXlT+VUCE3N1ffZZAOevvEOzk54ezZs2jatKnO+WfPnlVfmiqJUqmEUqnUmMZLUI/16tgMCgVw/e/7aFDHAYsCBuF6bAL+810kzEyNMWtiX+w9FoX4pHS41rHHwumDcPOfJBz5NRoA0L6FCzyau+DXSzeR+jAT9Ws7YO6Ufrh5J5FnFSSV+egR7ty5o3597+5d/BUdDSsrK1hZW2Pd2tXo1r0H7B0ckPrgAf67bSvuJyTgNe/X9Vg1FUdvYREcHIwJEybgwoUL6Nmzp9aYxddff40lS5boq7wXgpW5CUKnvYFaNayRkpaJfceiMHfl98jPV6GaoUCLRrXw9oAOsLYwRVxiGo5G/oXQVfuRm/f4WYvM7DwM7OGOjyf1g5mpMeKT0nD412h8+vUGdRui4vz55x/w9xujfr3kszAAwBsDB+PjufMQG3sL3+3bg9QHD2BtbY3mLVpi43+2omHDRvoqmUqgtwFuANi+fTvCw8Nx4cIFFBQUAAAMDQ3h4eGBwMBADB8+/KmWa9pG+wEgoorAAW6qLPoe4NZrWBTKy8tDUtLjQVd7e3sYGRk90/IYFlRZGBZUWfQdFlVilNLIyAg1a9bUdxlERFQMfussERFJMSyIiEiKYUFERFIMCyIikmJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpJiWBARkRTDgoiIpBgWREQkxbAgIiIphgUREUkxLIiISIphQUREUgwLIiKSYlgQEZEUw4KIiKQYFkREJMWwICIiKYYFERFJMSyIiEiKYUFERFIMCyIikmJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpKqVppGV65cKfUCW7Vq9dTFEBFR1VSqsGjdujUUCgWEEDrnF85TKBQoKCgo1wKJiEj/ShUWsbGxFV0HERFVYaUKCxcXl4qug4iIqrCnGuDevHkzPD094ezsjNu3bwMAli5din379pVrcUREVDWUOSy++uorBAYGom/fvkhNTVWPUVhbW2Pp0qXlXR8REVUBZQ6L5cuX4+uvv8asWbNgaGiont6uXTv8/vvv5VocERFVDWUOi9jYWLRp00ZrulKpxKNHj8qlKCIiqlrKHBb169dHVFSU1vQff/wRzZo1K4+aiIioiinV3VBPCgwMxLvvvovs7GwIIXD27Fls27YNYWFhWLduXUXUSEREelbmsPD394epqSk+/vhjZGZmYtSoUXB2dsayZcswYsSIiqiRiIj0TCGKeyy7FDIzM5GRkQFHR8fyrOmZmbaZqu8S6CXx4NwKfZdALwmTMh/al6+nXv39+/dx7do1AI+/7sPBwaHciiIioqqlzAPcDx8+xDvvvANnZ2d4eXnBy8sLzs7OGD16NNLS0iqiRiIi0rMyh4W/vz/OnDmDAwcOIDU1Fampqdi/fz/Onz+PiRMnVkSNRESkZ2UeszAzM8OhQ4fQuXNnjemnTp3C66+/XiWeteCYBVUWjllQZdH3mEWZzyzs7OxgZWWlNd3Kygo2NjblUhQREVUtZQ6Ljz/+GIGBgYiPj1dPi4+Px4wZMzB79uxyLY6IiKqGUp3YtGnTBgqFQv06JiYGdevWRd26dQEAd+7cgVKpRGJiIsctiIheQKUKi0GDBlVwGUREVJU900N5VRUHuKmycICbKstzN8BNREQvnzJnVUFBAcLDw7Fjxw7cuXMHubm5GvNTUlLKrTgiIqoaynxmMW/ePHzxxRd46623kJaWhsDAQAwZMgQGBgYICQmpgBKJiEjfyhwWW7duxddff42goCBUq1YNI0eOxLp16zBnzhz89ttvFVEjERHpWZnDIj4+Hi1btgQAmJubq78Pqn///jhw4ED5VkdERFVCmcOidu3aiIuLAwA0aNAAhw8fBgCcO3cOSqWyfKsjIqIqocxhMXjwYBw7dgwAMG3aNMyePRuNGjXCmDFjMHbs2HIvkIiI9O+Zn7P47bff8Ouvv6JRo0YYMGBAedX1TPicBVUWPmdBleW5f87i1VdfRWBgIDp06IBFixaVR01ERFTFlNtDeXFxcfwiQSKiFxSf4CYiIimGBRERSTEsiIhIqtTj64GBgSXOT0xMfOZiykvymeX6LoFeEglpOfougV4SLnb6fY6t1GFx6dIlaZuuXbs+UzFERFQ1vZB/zyIz94XbJKqiEh/myhsRlQN9n1lwzIKIiKQYFkREJMWwICIiKYYFERFJMSyIiEjqqcLi1KlTGD16NDp27Ih79+4BADZv3oxffvmlXIsjIqKqocxhsXv3bnh7e8PU1BSXLl1CTs7jh5LS0tL4rbNERC+oMofFggULsHr1anz99dcwMjJST/f09MTFixfLtTgiIqoayhwW165d0/mktpWVFVJTU8ujJiIiqmLKHBZOTk64ceOG1vRffvkFrq6u5VIUERFVLWUOi/Hjx2P69Ok4c+YMFAoF/v33X2zduhXBwcGYPHlyRdRIRER6Vua/6vrRRx9BpVKhZ8+eyMzMRNeuXaFUKhEcHIxp06ZVRI1ERKRnT/1Fgrm5ubhx4wYyMjLg5uYGc3Pz8q7tqfGLBKmy8IsEqbLo+4sE+a2zRM+AYUGVRd9hUebLUN27d4dCoSh2/vHjx5+pICIiqnrKHBatW7fWeJ2Xl4eoqCj88ccf8PHxKa+6iIioCilzWISHh+ucHhISgoyMjGcuiIiIqp5yG7O4ceMGXnnlFaSkpJTH4p4JxyyosnDMgiqLvscsyu1bZyMjI2FiYlJeiyMioiqkzJehhgwZovFaCIG4uDicP38es2fPLrfCiIio6ihzWFhZWWm8NjAwQJMmTRAaGorevXuXW2FERFR1lCksCgoK4Ofnh5YtW8LGxqaiaiIioiqmTGMWhoaG6N27N79dlojoJVPmAe4WLVrg1q1bFVELERFVUU/1x4+Cg4Oxf/9+xMXFIT09XeOHiIhePKV+ziI0NBRBQUGwsLD435uf+NoPIQQUCgUKCgrKv8oy4nMWVFn4nAVVFn0/Z1HqsDA0NERcXByio6NLbOfl5VUuhT0LhgVVFoYFVRZ9h0Wp74YqzJSqEAZERFS5yjRmUdK3zRIR0YurTM9ZNG7cWBoYVeG7oYiIqHyVKSzmzZun9QQ3ERG9+Eo9wG1gYID4+Hg4OjpWdE3PjAPcVFk4wE2VRd8D3KUes+B4BRHRy6vUYfEC/qluIiIqpVKPWahUqoqsg4iIqrBy++NHRET04mJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpJiWBARkRTDgoiIpBgWREQkxbAgIiIphgUREUkxLIiISIphQUREUgwLIiKSYlgQEZEUw4KIiKQYFkREJMWwICIiKYYFERFJMSyIiEiKYUFERFIMCyIikmJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpKqpu8CqPKsX7cGx48ewd+xt6A0MYG7extMDwhCvfquAIB/791Fv9d76XzvZ0uW4jXv1yuzXHqOXLl0Hju/2YSYa9FISUrE3LCl8PTqAQDIz8/DpjUrcDbyFOL+vQszcwu0bdcB4ya/DzsHRwBAfNw9bN24FlEXzuBBcjLs7B3Q8/V+GOkzAUZGRvrcNPo/DIuXyMXz5/DWiFFo3qIl8gsKsGJZOCZP9Me3e/fDtHp11HCqiSMnTmm8Z/fOHfjPpvXw7NJFT1XT8yA7OwuuDZvAu/9ghM4M0JiXk52NmOvReNtvIlwbNkbGw3SsWvop5nz4HlZu+C8A4J/bsRAqFaZ/MAe1atfF37diEP7JPGRnZWHCtGB9bBIVoRBCCH0XUd4yc1+4TaoQKSkp6OnVCes2boZHu/Y624x4czCaNnNDSOjCSq7u+ZD4MFffJVQ5vTu10jiz0OXa1T8wzX8Utnx7CI5ONXW22bF1I/bv2YH/7Pqhokp9rrjYKfW6fo5ZvMQyMh4CAKysrHTOv/rnH7j2VzQGDRlamWXRS+DRowwoFAqYWVgU3yYjAxaWuvdNqnwMi5eUSqXCkk8XoXWbtmjYqLHONnv37EZ91wZo3bptJVdHL7LcnBysWxWObq/1gZmZuc429+7ewb5d29Bv4LBKro6KU6XD4p9//sHYsWNLbJOTk4P09HSNn5ycnEqq8PkVtjAUN27E4JPPvtA5Pzs7Gz8c3M+zCipX+fl5WDA7GBAC7834WGebpMQEzAqYjK49XkNfhkWVUaXDIiUlBRERESW2CQsLg5WVlcbPks/CKqnC59MnC0Nx6qeT+Hr9f1DDyUlnm6NHDiE7Kxv9Bwyq3OLohZWfn4cFH8/A/fg4fLJsrc6ziuTE+5gx1R9uLd3x/odz9VAlFUevd0N99913Jc6/deuWdBkzZ85EYGCgxrQChfEz1fWiEkLg00Xzcfz4UXy94T+oVbt2sW33frsLXt27w9bWthIrpBdVYVDc++c2Fq9YD0sra602SYkJmDHVH42aNEPQrPkwMKjSx7IvHb2GxaBBg6BQKFDSDVkKhaLEZSiVSiiVmncJ8G4o3cIWhuKHg/sRvmwlzMzMkJSUCAAwN7eAiYmJut2dO7dx8cJ5LF+1Vl+l0nMmKzMT/969o34dH3cPN6//BQtLK9ja22P+/wtCzPVozF+8AiqVCinJSQAAC0srGBkZISkxAcHvjkMNp5qYMC0IaakP1MuytbOv9O0hbXq9dbZWrVpYtWoVBg4cqHN+VFQUPDw8UFBQUKblMix0a9Oyqc7p8+YvwhuDhqhfL1/2BQ7u/x4HDh3j0Z0Eb5197PLFc5gxdZzW9Nf6voF3xk3GmKF9dL5v8Yr1cG/bHocP7MOShbN1tjn865VyrfV5pe9bZ/UaFm+88QZat26N0NBQnfMvX76MNm3aQKVSlWm5DAuqLAwLqiz6Dgu9XoaaMWMGHj16VOz8hg0b4sSJE5VYERER6cInuImeAc8sqLLo+8yCF6SJiEiKYUFERFIMCyIikmJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpJiWBARkRTDgoiIpBgWREQkxbAgIiIphgUREUkxLIiISIphQUREUgwLIiKSYlgQEZEUw4KIiKQYFkREJMWwICIiKYYFERFJMSyIiEiKYUFERFIMCyIikmJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpJiWBARkRTDgoiIpBgWREQkxbAgIiIphgUREUkxLIiISIphQUREUgwLIiKSYlgQEZEUw4KIiKQYFkREJMWwICIiKYYFERFJMSyIiEiKYUFERFIMCyIikmJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpJiWBARkRTDgoiIpBgWREQkxbAgIiIphgUREUkxLIiISIphQUREUgwLIiKSYlgQEZEUw4KIiKQYFkREJKUQQgh9F0H6l5OTg7CwMMycORNKpVLf5dALjPva84lhQQCA9PR0WFlZIS0tDZaWlvouh15g3NeeT7wMRUREUgwLIiKSYlgQEZEUw4IAAEqlEnPnzuWAI1U47mvPJw5wExGRFM8siIhIimFBRERSDAsiIpJiWBARkRTDgrBy5UrUq1cPJiYm6NChA86ePavvkugF9PPPP2PAgAFwdnaGQqHA3r179V0SlQHD4iW3fft2BAYGYu7cubh48SLc3d3h7e2N+/fv67s0esE8evQI7u7uWLlypb5LoafAW2dfch06dED79u2xYsUKAIBKpUKdOnUwbdo0fPTRR3qujl5UCoUCe/bswaBBg/RdCpUSzyxeYrm5ubhw4QJ69eqlnmZgYIBevXohMjJSj5URUVXDsHiJJSUloaCgADVq1NCYXqNGDcTHx+upKiKqihgWREQkxbB4idnb28PQ0BAJCQka0xMSEuDk5KSnqoioKmJYvMSMjY3h4eGBY8eOqaepVCocO3YMHTt21GNlRFTVVNN3AaRfgYGB8PHxQbt27fDKK69g6dKlePToEfz8/PRdGr1gMjIycOPGDfXr2NhYREVFwdbWFnXr1tVjZVQavHWWsGLFCixevBjx8fFo3bo1vvzyS3To0EHfZdEL5uTJk+jevbvWdB8fH2zatKnyC6IyYVgQEZEUxyyIiEiKYUFERFIMCyIikmJYEBGRFMOCiIikGBZERCTFsCAiIimGBRERSTEs6IXl6+ur8cd1unXrhvfff7/S6zh58iQUCgVSU1MrbB1Ft/VpVEad9PxiWFCl8vX1hUKhgEKhgLGxMRo2bIjQ0FDk5+dX+Lq//fZbzJ8/v1RtK/sXZ7169bB06dJKWRfR0+AXCVKle/3117Fx40bk5OTg4MGDePfdd2FkZISZM2dqtc3NzYWxsXG5rNfW1rZclkP0MuKZBVU6pVIJJycnuLi4YPLkyejVqxe+++47AP+7nLJw4UI4OzujSZMmAIB//vkHw4cPh7W1NWxtbTFw4ED8/fff6mUWFBQgMDAQ1tbWsLOzwwcffICiX3tW9DJUTk4OPvzwQ9SpUwdKpRINGzbE+vXr8ffff6u/8M7GxgYKhQK+vr4AHn+Fe1hYGOrXrw9TU1O4u7tj165dGus5ePAgGjduDFNTU3Tv3l2jzqdRUFCAcePGqdfZpEkTLFu2TGfbefPmwcHBAZaWlpg0aRJyc3PV80pTO1FxeGZBemdqaork5GT162PHjsHS0hJHjhwBAOTl5cHb2xsdO3bEqVOnUK1aNSxYsACvv/46rly5AmNjY3z++efYtGkTNmzYgGbNmuHzzz/Hnj170KNHj2LXO2bMGERGRuLLL7+Eu7s7YmNjkZSUhDp16mD37t0YOnQorl27BktLS5iamgIAwsLCsGXLFqxevRqNGjXCzz//jNGjR8PBwQFeXl74559/MGTIELz77ruYMGECzp8/j6CgoGfqH5VKhdq1a2Pnzp2ws7PDr7/+igkTJqBmzZoYPny4Rr+ZmJjg5MmT+Pvvv+Hn5wc7OzssXLiwVLUTlUgQVSIfHx8xcOBAIYQQKpVKHDlyRCiVShEcHKyeX6NGDZGTk6N+z+bNm0WTJk2ESqVST8vJyRGmpqbi0KFDQgghatasKT777DP1/Ly8PFG7dm31uoQQwsvLS0yfPl0IIcS1a9cEAHHkyBGddZ44cUIAEA8ePFBPy87OFtWrVxe//vqrRttx48aJkSNHCiGEmDlzpnBzc9OY/+GHH2otqygXFxcRHh5e7Pyi3n33XTF06FD1ax8fH2FraysePXqknvbVV18Jc3NzUVBQUKradW0zUSGeWVCl279/P8zNzZGXlweVSoVRo0YhJCREPb9ly5Ya4xSXL1/GjRs3YGFhobGc7Oxs3Lx5E2lpaYiLi9P4GxzVqlVDu3bttC5FFYqKioKhoWGZjqhv3LiBzMxMvPbaaxrTc3Nz0aZNGwBAdHS01t8CKY+/Orhy5Ups2LABd+7cQVZWFnJzc9G6dWuNNu7u7qhevbrGejMyMvDPP/8gIyNDWjtRSRgWVOm6d++Or776CsbGxnB2dka1apq7oZmZmcbrjIwMeHh4YOvWrVrLcnBweKoaCi8rlUVGRgYA4MCBA6hVq5bGPKVS+VR1lMZ///tfBAcH4/PPP0fHjh1hYWGBxYsX48yZM6Vehr5qpxcHw4IqnZmZGRo2bFjq9m3btsX27dvh6OgIS0tLnW1q1qyJM2fOoGvXrgCA/Px8XLhwAW3bttXZvmXLllCpVPjpp5/Qq1cvrfmFZzYFBQXqaW5ublAqlbhz506xZyTNmjVTD9YX+u233+QbWYLTp0+jU6dOmDJlinrazZs3tdpdvnwZWVlZ6iD87bffYG5ujjp16sDW1lZaO1FJeDcUVXlvv/027O3tMXDgQJw6dQqxsbE4efIk3nvvPdy9excAMH36dHzyySfYu3cv/vrrL0yZMqXEZyTq1asHHx8fjB07Fnv37lUvc8eOHQAAFxcXKBQK7N+/H4mJicjIyICFhQWCg4MREBCAiIgI3Lx5ExcvXsTy5csREREBAJg0aRJiYmIwY8YMXLt2Dd98802p/2TovXv3EBUVpfHz4MEDNGrUCOfPn8ehQ4dw/fp1zJ49G+fOndN6f25uLsaNG4erV6/i4MGDmDt3LqZOnQoDA4NS1U5UIn0PmtDL5ckB7rLMj4uLE2PGjBH29vZCqVQKV1dXMX78eJGWliaEeDygPX36dGFpaSmsra1FYGCgGDNmTLED3EIIkZWVJQICAkTNmjWFsbGxaNiwodiwYYN6fmhoqHBychIKhUL4+PgIIR4Pyi9dulQ0adJEGBkZCQcHB+Ht7S1++ukn9fu+//570bBhQ6FUKkWXLl3Ehg0bSjXADUDrZ/PmzSI7O1v4+voKKysrYW1tLSZPniw++ugj4e7urtVvc+bMEXZ2dsLc3FyMHz9eZGdnq9vIaucAN5WEf4ObiIikeBmKiIikGBZERCTFsCAiIimGBRERSTEsiIhIimFBRERSDAsiIpJiWBARkRTDgoiIpBgWREQkxbAgIiKp/w/4cypQxF72SgAAAABJRU5ErkJggg==\n"
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Best DecisionTree params: {'criterion': 'gini', 'max_depth': None}\n",
            "              precision    recall  f1-score   support\n",
            "\n",
            "         ham       0.97      0.99      0.98       966\n",
            "        spam       0.90      0.82      0.86       149\n",
            "\n",
            "    accuracy                           0.96      1115\n",
            "   macro avg       0.94      0.90      0.92      1115\n",
            "weighted avg       0.96      0.96      0.96      1115\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": "stream",
          "name": "stdout",
          "text": [
            "Best SVM params: {'kernel': 'linear'}\n",
            "              precision    recall  f1-score   support\n",
            "\n",
            "         ham       0.99      1.00      0.99       966\n",
            "        spam       0.97      0.91      0.94       149\n",
            "\n",
            "    accuracy                           0.98      1115\n",
            "   macro avg       0.98      0.95      0.96      1115\n",
            "weighted avg       0.98      0.98      0.98      1115\n",
            "\n"
          ]
        }
      ],
      "source": [
        "\n",
        "# TF-IDF with unigrams and bigrams\n",
        "# -------------------------------------------------------------\n",
        "vectorizer_tfidf = TfidfVectorizer(ngram_range=(1, 2), max_features=20000)\n",
        "X_train_tfidf = vectorizer_tfidf.fit_transform(X_train)\n",
        "X_test_tfidf = vectorizer_tfidf.transform(X_test)\n",
        "\n",
        "# Decision Tree with hyperparameter tuning\n",
        "dt_classifier = DecisionTreeClassifier(random_state=42)\n",
        "dt_param_grid = {\n",
        "    'criterion': ['gini', 'entropy'],\n",
        "    'max_depth': [None, 10, 20]\n",
        "}\n",
        "dt_grid = GridSearchCV(estimator=dt_classifier, param_grid=dt_param_grid, cv=5, scoring='accuracy', n_jobs=-1)\n",
        "dt_grid.fit(X_train_tfidf, y_train)\n",
        "best_dt = dt_grid.best_estimator_\n",
        "y_pred_dt = best_dt.predict(X_test_tfidf)\n",
        "metrics_dt = evaluate_model('DecisionTreeClassifier', y_test, y_pred_dt)\n",
        "print(\"Best DecisionTree params:\", dt_grid.best_params_)\n",
        "print(metrics_dt['Classification Report'])\n",
        "\n",
        "# Support Vector Machine with hyperparameter tuning\n",
        "svm_classifier = SVC(random_state=42)\n",
        "svm_param_grid = {\n",
        "    'kernel': ['linear', 'rbf', 'poly']\n",
        "}\n",
        "svm_grid = GridSearchCV(estimator=svm_classifier, param_grid=svm_param_grid, cv=5, scoring='accuracy', n_jobs=-1)\n",
        "svm_grid.fit(X_train_tfidf, y_train)\n",
        "best_svm = svm_grid.best_estimator_\n",
        "y_pred_svm = best_svm.predict(X_test_tfidf)\n",
        "metrics_svm = evaluate_model('SupportVectorMachine', y_test, y_pred_svm)\n",
        "print(\"Best SVM params:\", svm_grid.best_params_)\n",
        "print(metrics_svm['Classification Report'])\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fa7e565a",
      "metadata": {
        "id": "fa7e565a"
      },
      "source": [
        "\n",
        "**Summaryof the steps **\n",
        "\n",
        "1. **I Downloaded the NLP dataset** – The code  includes instructions for downloading the SMS Spam Collection dataset via the Kaggle API and an option to upload the spam.csv file manually.Using the below link\n",
        "https://www.kaggle.com/datasets/uciml/sms-spam-collection-dataset?resource=download\n",
        "\n",
        "2. **Apply data preprocessing** – It cleans the text by lower‑casing, removing punctuation, filtering stop‑words and lemmatizing.\n",
        "\n",
        "3. **Split the dataset** – It performs an 80/20 train–test split of the cleaned messages and labels.\n",
        "\n",
        "4. **Apply feature representation methods** – It uses both Bag‑of‑Words (CountVectorizer) and TF‑IDF (TfidfVectorizer with n‑grams) to convert text into numerical feature vectors.\n",
        "\n",
        "5. **Train and evaluate models** – It trains several classifiers (Random Forest, Logistic Regression, Decision Tree, SVM) with hyperparameter tuning via GridSearchCV, then evaluates them using accuracy, precision, recall, F1 scores and confusion‑matrix plots."
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "language_info": {
      "name": "python"
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}