{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Vv6noLRoaqh0"
      },
      "source": [
        "# Scikit-learn Compatible Estimators"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Y9pEv59la5CV"
      },
      "source": [
        "[![Slides](https://img.shields.io/badge/🦌-ReHLine-blueviolet)](https://rehline-python.readthedocs.io/en/latest/)\n",
        "\n",
        "The core class `plqERM_Ridge` serves as a base implementation for both classification and regression tasks. Its subclasses, `plqERMClassifier` and `plqERMRegressor`, provide task-specific functionality while integrating seamlessly with scikit-learn utilities such as `Pipeline`, `cross_val_score`, and `GridSearchCV`. In addition, these models support common evaluation methods, allowing users to compute metrics such as accuracy scores for classification or R² values for regression."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "chXqSvec7yqI"
      },
      "source": [
        "#### Classification Example with GridSearchCV and Pipeline\n",
        "\n",
        "Here we shows a classification example which contains `pipeline`, `cross_val_score` and `GridSearchCV`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "id": "umXH0TZG9Zsl"
      },
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from sklearn.datasets import make_classification\n",
        "from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score\n",
        "from sklearn.pipeline import Pipeline\n",
        "from sklearn.preprocessing import StandardScaler\n",
        "from sklearn.metrics import accuracy_score, classification_report, confusion_matrix"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "id": "Qh3tOux-9gZ9"
      },
      "outputs": [],
      "source": [
        "# generate the dataset\n",
        "X, y = make_classification(\n",
        "    n_samples=2000,\n",
        "    n_features=20,\n",
        "    n_informative=8,\n",
        "    n_redundant=4,\n",
        "    n_repeated=0,\n",
        "    n_classes=2,\n",
        "    weights=[0.7, 0.3],   # imbalance\n",
        "    class_sep=1.2,\n",
        "    flip_y=0.01,\n",
        "    random_state=42,\n",
        ")\n",
        "\n",
        "X_train, X_test, y_train, y_test = train_test_split(\n",
        "    X, y, test_size=0.25, stratify=y, random_state=42\n",
        ")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "id": "_MR1vTRc93xM"
      },
      "outputs": [],
      "source": [
        "from rehline import plq_Ridge_Classifier\n",
        "\n",
        "# set the pipeline\n",
        "pipe = Pipeline([\n",
        "    (\"scaler\", StandardScaler()),\n",
        "    (\"clf\", plq_Ridge_Classifier(loss={\"name\": \"svm\"})),\n",
        "])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {
        "id": "tfGUG7auABMG"
      },
      "outputs": [],
      "source": [
        "# set the parameter grid\n",
        "param_grid = {\n",
        "    \"clf__loss\": [{\"name\": \"svm\"}, {\"name\": \"sSVM\"}],\n",
        "    \"clf__C\": [0.1, 1.0, 3.0],\n",
        "    \"clf__fit_intercept\": [True, False],\n",
        "    \"clf__intercept_scaling\": [0.5, 1.0, 2.0],\n",
        "    \"clf__max_iter\": [5000, 10000],\n",
        "    \"clf__class_weight\": [None, \"balanced\", {0: 1.0, 1: 2.0}],\n",
        "    \"clf__constraint\": [\n",
        "        [],                              # no constraint\n",
        "        [{\"name\": \"nonnegative\"}],\n",
        "        [{\"name\": \"fair\", \"sen_idx\": [0], \"tol_sen\": 0.1}],\n",
        "    ],\n",
        "}"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "LBsUuv6bBW00",
        "outputId": "fbd50af6-a23a-4eb9-c0dc-0c1e538c9574"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "CV scores: [0.79333333 0.82       0.82333333 0.81       0.80666667]\n"
          ]
        }
      ],
      "source": [
        "# cross_val_score function\n",
        "cv_scores = cross_val_score(\n",
        "    pipe,\n",
        "    X_train, y_train,\n",
        "    cv=5,\n",
        "    scoring=\"accuracy\",\n",
        "    n_jobs=-1,\n",
        ")\n",
        "print(\"CV scores:\", cv_scores)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 207
        },
        "id": "s0Ur4GgIAGET",
        "outputId": "f2fee1ba-d348-472f-9cb2-8c5d62a776ba"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Fitting 5 folds for each of 648 candidates, totalling 3240 fits\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<style>#sk-container-id-1 {\n",
              "  /* Definition of color scheme common for light and dark mode */\n",
              "  --sklearn-color-text: #000;\n",
              "  --sklearn-color-text-muted: #666;\n",
              "  --sklearn-color-line: gray;\n",
              "  /* Definition of color scheme for unfitted estimators */\n",
              "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
              "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
              "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
              "  --sklearn-color-unfitted-level-3: chocolate;\n",
              "  /* Definition of color scheme for fitted estimators */\n",
              "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
              "  --sklearn-color-fitted-level-1: #d4ebff;\n",
              "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
              "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
              "\n",
              "  /* Specific color for light theme */\n",
              "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
              "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
              "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
              "  --sklearn-color-icon: #696969;\n",
              "\n",
              "  @media (prefers-color-scheme: dark) {\n",
              "    /* Redefinition of color scheme for dark theme */\n",
              "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
              "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
              "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
              "    --sklearn-color-icon: #878787;\n",
              "  }\n",
              "}\n",
              "\n",
              "#sk-container-id-1 {\n",
              "  color: var(--sklearn-color-text);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 pre {\n",
              "  padding: 0;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 input.sk-hidden--visually {\n",
              "  border: 0;\n",
              "  clip: rect(1px 1px 1px 1px);\n",
              "  clip: rect(1px, 1px, 1px, 1px);\n",
              "  height: 1px;\n",
              "  margin: -1px;\n",
              "  overflow: hidden;\n",
              "  padding: 0;\n",
              "  position: absolute;\n",
              "  width: 1px;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-dashed-wrapped {\n",
              "  border: 1px dashed var(--sklearn-color-line);\n",
              "  margin: 0 0.4em 0.5em 0.4em;\n",
              "  box-sizing: border-box;\n",
              "  padding-bottom: 0.4em;\n",
              "  background-color: var(--sklearn-color-background);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-container {\n",
              "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
              "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
              "     so we also need the `!important` here to be able to override the\n",
              "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
              "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
              "  display: inline-block !important;\n",
              "  position: relative;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-text-repr-fallback {\n",
              "  display: none;\n",
              "}\n",
              "\n",
              "div.sk-parallel-item,\n",
              "div.sk-serial,\n",
              "div.sk-item {\n",
              "  /* draw centered vertical line to link estimators */\n",
              "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
              "  background-size: 2px 100%;\n",
              "  background-repeat: no-repeat;\n",
              "  background-position: center center;\n",
              "}\n",
              "\n",
              "/* Parallel-specific style estimator block */\n",
              "\n",
              "#sk-container-id-1 div.sk-parallel-item::after {\n",
              "  content: \"\";\n",
              "  width: 100%;\n",
              "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
              "  flex-grow: 1;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-parallel {\n",
              "  display: flex;\n",
              "  align-items: stretch;\n",
              "  justify-content: center;\n",
              "  background-color: var(--sklearn-color-background);\n",
              "  position: relative;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-parallel-item {\n",
              "  display: flex;\n",
              "  flex-direction: column;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
              "  align-self: flex-end;\n",
              "  width: 50%;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
              "  align-self: flex-start;\n",
              "  width: 50%;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
              "  width: 0;\n",
              "}\n",
              "\n",
              "/* Serial-specific style estimator block */\n",
              "\n",
              "#sk-container-id-1 div.sk-serial {\n",
              "  display: flex;\n",
              "  flex-direction: column;\n",
              "  align-items: center;\n",
              "  background-color: var(--sklearn-color-background);\n",
              "  padding-right: 1em;\n",
              "  padding-left: 1em;\n",
              "}\n",
              "\n",
              "\n",
              "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
              "clickable and can be expanded/collapsed.\n",
              "- Pipeline and ColumnTransformer use this feature and define the default style\n",
              "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
              "*/\n",
              "\n",
              "/* Pipeline and ColumnTransformer style (default) */\n",
              "\n",
              "#sk-container-id-1 div.sk-toggleable {\n",
              "  /* Default theme specific background. It is overwritten whether we have a\n",
              "  specific estimator or a Pipeline/ColumnTransformer */\n",
              "  background-color: var(--sklearn-color-background);\n",
              "}\n",
              "\n",
              "/* Toggleable label */\n",
              "#sk-container-id-1 label.sk-toggleable__label {\n",
              "  cursor: pointer;\n",
              "  display: flex;\n",
              "  width: 100%;\n",
              "  margin-bottom: 0;\n",
              "  padding: 0.5em;\n",
              "  box-sizing: border-box;\n",
              "  text-align: center;\n",
              "  align-items: start;\n",
              "  justify-content: space-between;\n",
              "  gap: 0.5em;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 label.sk-toggleable__label .caption {\n",
              "  font-size: 0.6rem;\n",
              "  font-weight: lighter;\n",
              "  color: var(--sklearn-color-text-muted);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
              "  /* Arrow on the left of the label */\n",
              "  content: \"▸\";\n",
              "  float: left;\n",
              "  margin-right: 0.25em;\n",
              "  color: var(--sklearn-color-icon);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
              "  color: var(--sklearn-color-text);\n",
              "}\n",
              "\n",
              "/* Toggleable content - dropdown */\n",
              "\n",
              "#sk-container-id-1 div.sk-toggleable__content {\n",
              "  max-height: 0;\n",
              "  max-width: 0;\n",
              "  overflow: hidden;\n",
              "  text-align: left;\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-0);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-0);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-toggleable__content pre {\n",
              "  margin: 0.2em;\n",
              "  border-radius: 0.25em;\n",
              "  color: var(--sklearn-color-text);\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-0);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-0);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
              "  /* Expand drop-down */\n",
              "  max-height: 200px;\n",
              "  max-width: 100%;\n",
              "  overflow: auto;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
              "  content: \"▾\";\n",
              "}\n",
              "\n",
              "/* Pipeline/ColumnTransformer-specific style */\n",
              "\n",
              "#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
              "  color: var(--sklearn-color-text);\n",
              "  background-color: var(--sklearn-color-unfitted-level-2);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
              "  background-color: var(--sklearn-color-fitted-level-2);\n",
              "}\n",
              "\n",
              "/* Estimator-specific style */\n",
              "\n",
              "/* Colorize estimator box */\n",
              "#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-2);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-2);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
              "#sk-container-id-1 div.sk-label label {\n",
              "  /* The background is the default theme color */\n",
              "  color: var(--sklearn-color-text-on-default-background);\n",
              "}\n",
              "\n",
              "/* On hover, darken the color of the background */\n",
              "#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
              "  color: var(--sklearn-color-text);\n",
              "  background-color: var(--sklearn-color-unfitted-level-2);\n",
              "}\n",
              "\n",
              "/* Label box, darken color on hover, fitted */\n",
              "#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
              "  color: var(--sklearn-color-text);\n",
              "  background-color: var(--sklearn-color-fitted-level-2);\n",
              "}\n",
              "\n",
              "/* Estimator label */\n",
              "\n",
              "#sk-container-id-1 div.sk-label label {\n",
              "  font-family: monospace;\n",
              "  font-weight: bold;\n",
              "  display: inline-block;\n",
              "  line-height: 1.2em;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-label-container {\n",
              "  text-align: center;\n",
              "}\n",
              "\n",
              "/* Estimator-specific */\n",
              "#sk-container-id-1 div.sk-estimator {\n",
              "  font-family: monospace;\n",
              "  border: 1px dotted var(--sklearn-color-border-box);\n",
              "  border-radius: 0.25em;\n",
              "  box-sizing: border-box;\n",
              "  margin-bottom: 0.5em;\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-0);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-estimator.fitted {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-0);\n",
              "}\n",
              "\n",
              "/* on hover */\n",
              "#sk-container-id-1 div.sk-estimator:hover {\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-2);\n",
              "}\n",
              "\n",
              "#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-2);\n",
              "}\n",
              "\n",
              "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
              "\n",
              "/* Common style for \"i\" and \"?\" */\n",
              "\n",
              ".sk-estimator-doc-link,\n",
              "a:link.sk-estimator-doc-link,\n",
              "a:visited.sk-estimator-doc-link {\n",
              "  float: right;\n",
              "  font-size: smaller;\n",
              "  line-height: 1em;\n",
              "  font-family: monospace;\n",
              "  background-color: var(--sklearn-color-background);\n",
              "  border-radius: 1em;\n",
              "  height: 1em;\n",
              "  width: 1em;\n",
              "  text-decoration: none !important;\n",
              "  margin-left: 0.5em;\n",
              "  text-align: center;\n",
              "  /* unfitted */\n",
              "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
              "  color: var(--sklearn-color-unfitted-level-1);\n",
              "}\n",
              "\n",
              ".sk-estimator-doc-link.fitted,\n",
              "a:link.sk-estimator-doc-link.fitted,\n",
              "a:visited.sk-estimator-doc-link.fitted {\n",
              "  /* fitted */\n",
              "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
              "  color: var(--sklearn-color-fitted-level-1);\n",
              "}\n",
              "\n",
              "/* On hover */\n",
              "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
              ".sk-estimator-doc-link:hover,\n",
              "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
              ".sk-estimator-doc-link:hover {\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-3);\n",
              "  color: var(--sklearn-color-background);\n",
              "  text-decoration: none;\n",
              "}\n",
              "\n",
              "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
              ".sk-estimator-doc-link.fitted:hover,\n",
              "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
              ".sk-estimator-doc-link.fitted:hover {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-3);\n",
              "  color: var(--sklearn-color-background);\n",
              "  text-decoration: none;\n",
              "}\n",
              "\n",
              "/* Span, style for the box shown on hovering the info icon */\n",
              ".sk-estimator-doc-link span {\n",
              "  display: none;\n",
              "  z-index: 9999;\n",
              "  position: relative;\n",
              "  font-weight: normal;\n",
              "  right: .2ex;\n",
              "  padding: .5ex;\n",
              "  margin: .5ex;\n",
              "  width: min-content;\n",
              "  min-width: 20ex;\n",
              "  max-width: 50ex;\n",
              "  color: var(--sklearn-color-text);\n",
              "  box-shadow: 2pt 2pt 4pt #999;\n",
              "  /* unfitted */\n",
              "  background: var(--sklearn-color-unfitted-level-0);\n",
              "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
              "}\n",
              "\n",
              ".sk-estimator-doc-link.fitted span {\n",
              "  /* fitted */\n",
              "  background: var(--sklearn-color-fitted-level-0);\n",
              "  border: var(--sklearn-color-fitted-level-3);\n",
              "}\n",
              "\n",
              ".sk-estimator-doc-link:hover span {\n",
              "  display: block;\n",
              "}\n",
              "\n",
              "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
              "\n",
              "#sk-container-id-1 a.estimator_doc_link {\n",
              "  float: right;\n",
              "  font-size: 1rem;\n",
              "  line-height: 1em;\n",
              "  font-family: monospace;\n",
              "  background-color: var(--sklearn-color-background);\n",
              "  border-radius: 1rem;\n",
              "  height: 1rem;\n",
              "  width: 1rem;\n",
              "  text-decoration: none;\n",
              "  /* unfitted */\n",
              "  color: var(--sklearn-color-unfitted-level-1);\n",
              "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 a.estimator_doc_link.fitted {\n",
              "  /* fitted */\n",
              "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
              "  color: var(--sklearn-color-fitted-level-1);\n",
              "}\n",
              "\n",
              "/* On hover */\n",
              "#sk-container-id-1 a.estimator_doc_link:hover {\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-3);\n",
              "  color: var(--sklearn-color-background);\n",
              "  text-decoration: none;\n",
              "}\n",
              "\n",
              "#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-3);\n",
              "}\n",
              "</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>GridSearchCV(cv=5,\n",
              "             estimator=Pipeline(steps=[(&#x27;scaler&#x27;, StandardScaler()),\n",
              "                                       (&#x27;clf&#x27;,\n",
              "                                        plq_Ridge_Classifier(loss={&#x27;name&#x27;: &#x27;svm&#x27;}))]),\n",
              "             n_jobs=-1,\n",
              "             param_grid={&#x27;clf__C&#x27;: [0.1, 1.0, 3.0],\n",
              "                         &#x27;clf__class_weight&#x27;: [None, &#x27;balanced&#x27;,\n",
              "                                               {0: 1.0, 1: 2.0}],\n",
              "                         &#x27;clf__constraint&#x27;: [[], [{&#x27;name&#x27;: &#x27;nonnegative&#x27;}],\n",
              "                                             [{&#x27;name&#x27;: &#x27;fair&#x27;, &#x27;sen_idx&#x27;: [0],\n",
              "                                               &#x27;tol_sen&#x27;: 0.1}]],\n",
              "                         &#x27;clf__fit_intercept&#x27;: [True, False],\n",
              "                         &#x27;clf__intercept_scaling&#x27;: [0.5, 1.0, 2.0],\n",
              "                         &#x27;clf__loss&#x27;: [{&#x27;name&#x27;: &#x27;svm&#x27;}, {&#x27;name&#x27;: &#x27;sSVM&#x27;}],\n",
              "                         &#x27;clf__max_iter&#x27;: [5000, 10000]},\n",
              "             scoring=&#x27;accuracy&#x27;, verbose=1)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" ><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>GridSearchCV</div></div><div><a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.6/modules/generated/sklearn.model_selection.GridSearchCV.html\">?<span>Documentation for GridSearchCV</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></div></label><div class=\"sk-toggleable__content fitted\"><pre>GridSearchCV(cv=5,\n",
              "             estimator=Pipeline(steps=[(&#x27;scaler&#x27;, StandardScaler()),\n",
              "                                       (&#x27;clf&#x27;,\n",
              "                                        plq_Ridge_Classifier(loss={&#x27;name&#x27;: &#x27;svm&#x27;}))]),\n",
              "             n_jobs=-1,\n",
              "             param_grid={&#x27;clf__C&#x27;: [0.1, 1.0, 3.0],\n",
              "                         &#x27;clf__class_weight&#x27;: [None, &#x27;balanced&#x27;,\n",
              "                                               {0: 1.0, 1: 2.0}],\n",
              "                         &#x27;clf__constraint&#x27;: [[], [{&#x27;name&#x27;: &#x27;nonnegative&#x27;}],\n",
              "                                             [{&#x27;name&#x27;: &#x27;fair&#x27;, &#x27;sen_idx&#x27;: [0],\n",
              "                                               &#x27;tol_sen&#x27;: 0.1}]],\n",
              "                         &#x27;clf__fit_intercept&#x27;: [True, False],\n",
              "                         &#x27;clf__intercept_scaling&#x27;: [0.5, 1.0, 2.0],\n",
              "                         &#x27;clf__loss&#x27;: [{&#x27;name&#x27;: &#x27;svm&#x27;}, {&#x27;name&#x27;: &#x27;sSVM&#x27;}],\n",
              "                         &#x27;clf__max_iter&#x27;: [5000, 10000]},\n",
              "             scoring=&#x27;accuracy&#x27;, verbose=1)</pre></div> </div></div><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" ><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>best_estimator_: Pipeline</div></div></label><div class=\"sk-toggleable__content fitted\"><pre>Pipeline(steps=[(&#x27;scaler&#x27;, StandardScaler()),\n",
              "                (&#x27;clf&#x27;,\n",
              "                 plq_Ridge_Classifier(C=0.1,\n",
              "                                      constraint=[{&#x27;name&#x27;: &#x27;fair&#x27;,\n",
              "                                                   &#x27;sen_idx&#x27;: [0],\n",
              "                                                   &#x27;tol_sen&#x27;: 0.1}],\n",
              "                                      loss={&#x27;name&#x27;: &#x27;svm&#x27;}, max_iter=5000))])</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-3\" type=\"checkbox\" ><label for=\"sk-estimator-id-3\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>StandardScaler</div></div><div><a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.6/modules/generated/sklearn.preprocessing.StandardScaler.html\">?<span>Documentation for StandardScaler</span></a></div></label><div class=\"sk-toggleable__content fitted\"><pre>StandardScaler()</pre></div> </div></div><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-4\" type=\"checkbox\" ><label for=\"sk-estimator-id-4\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>plq_Ridge_Classifier</div></div></label><div class=\"sk-toggleable__content fitted\"><pre>plq_Ridge_Classifier(C=0.1,\n",
              "                     constraint=[{&#x27;name&#x27;: &#x27;fair&#x27;, &#x27;sen_idx&#x27;: [0],\n",
              "                                  &#x27;tol_sen&#x27;: 0.1}],\n",
              "                     loss={&#x27;name&#x27;: &#x27;svm&#x27;}, max_iter=5000)</pre></div> </div></div></div></div></div></div></div></div></div></div></div>"
            ],
            "text/plain": [
              "GridSearchCV(cv=5,\n",
              "             estimator=Pipeline(steps=[('scaler', StandardScaler()),\n",
              "                                       ('clf',\n",
              "                                        plq_Ridge_Classifier(loss={'name': 'svm'}))]),\n",
              "             n_jobs=-1,\n",
              "             param_grid={'clf__C': [0.1, 1.0, 3.0],\n",
              "                         'clf__class_weight': [None, 'balanced',\n",
              "                                               {0: 1.0, 1: 2.0}],\n",
              "                         'clf__constraint': [[], [{'name': 'nonnegative'}],\n",
              "                                             [{'name': 'fair', 'sen_idx': [0],\n",
              "                                               'tol_sen': 0.1}]],\n",
              "                         'clf__fit_intercept': [True, False],\n",
              "                         'clf__intercept_scaling': [0.5, 1.0, 2.0],\n",
              "                         'clf__loss': [{'name': 'svm'}, {'name': 'sSVM'}],\n",
              "                         'clf__max_iter': [5000, 10000]},\n",
              "             scoring='accuracy', verbose=1)"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# perform GridSearchCV to tune the hyperparameter\n",
        "grid = GridSearchCV(\n",
        "    estimator=pipe,\n",
        "    param_grid=param_grid,\n",
        "    scoring=\"accuracy\",\n",
        "    cv=5,\n",
        "    n_jobs=-1,\n",
        "    refit=True,\n",
        "    verbose=1,\n",
        ")\n",
        "\n",
        "grid.fit(X_train, y_train)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "pD_uySLxBcKx",
        "outputId": "3cbff9f2-8db1-487e-db5e-1ec4c66508c5"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Best params: {'clf__C': 0.1, 'clf__class_weight': None, 'clf__constraint': [{'name': 'fair', 'sen_idx': [0], 'tol_sen': 0.1}], 'clf__fit_intercept': True, 'clf__intercept_scaling': 1.0, 'clf__loss': {'name': 'svm'}, 'clf__max_iter': 5000}\n",
            "Best CV accuracy: 0.8146666666666667\n"
          ]
        }
      ],
      "source": [
        "print(\"Best params:\", grid.best_params_)\n",
        "print(\"Best CV accuracy:\", grid.best_score_)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "nbddbX5cBkCa",
        "outputId": "3859879e-d801-43b7-84c5-3327e589aa4c"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Test accuracy: 0.802\n",
            "\n",
            "Classification report:\n",
            "               precision    recall  f1-score   support\n",
            "\n",
            "           0     0.8094    0.9370    0.8685       349\n",
            "           1     0.7708    0.4901    0.5992       151\n",
            "\n",
            "    accuracy                         0.8020       500\n",
            "   macro avg     0.7901    0.7135    0.7339       500\n",
            "weighted avg     0.7978    0.8020    0.7872       500\n",
            "\n",
            "Confusion matrix:\n",
            " [[327  22]\n",
            " [ 77  74]]\n"
          ]
        }
      ],
      "source": [
        "# use the best estimator fit and predict\n",
        "best_model = grid.best_estimator_\n",
        "y_pred = best_model.predict(X_test)\n",
        "test_acc = accuracy_score(y_test, y_pred)\n",
        "\n",
        "print(\"Test accuracy:\", test_acc)\n",
        "print(\"\\nClassification report:\\n\", classification_report(y_test, y_pred, digits=4))\n",
        "print(\"Confusion matrix:\\n\", confusion_matrix(y_test, y_pred))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8tYkW_az8-ra"
      },
      "source": [
        "#### Regression Example\n",
        "\n",
        "Here we shows a regression example which contains `pipeline`, `cross_val_score` and `GridSearchCV`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "id": "6oNtcqzXHdof"
      },
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from sklearn.datasets import make_regression\n",
        "from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score\n",
        "from sklearn.pipeline import Pipeline\n",
        "from sklearn.preprocessing import StandardScaler\n",
        "from sklearn.metrics import mean_squared_error, r2_score"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {
        "id": "jtqyQTx8HeJb"
      },
      "outputs": [],
      "source": [
        "# generate the data\n",
        "X, y = make_regression(\n",
        "    n_samples=1500,\n",
        "    n_features=15,\n",
        "    n_informative=10,\n",
        "    noise=10.0,\n",
        "    random_state=42\n",
        ")\n",
        "\n",
        "X_train, X_test, y_train, y_test = train_test_split(\n",
        "    X, y, test_size=0.25, random_state=42\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "id": "W0YrpRYUHgpd"
      },
      "outputs": [],
      "source": [
        "from rehline import plq_Ridge_Regressor\n",
        "\n",
        "# set the pipeline\n",
        "pipe = Pipeline([\n",
        "    (\"scaler\", StandardScaler()),\n",
        "    (\"reg\", plq_Ridge_Regressor(loss={\"name\": \"QR\", \"qt\": 0.5})),\n",
        "])\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {
        "id": "UK3mHaLnHjBf"
      },
      "outputs": [],
      "source": [
        "# set the param_grid\n",
        "param_grid = {\n",
        "    \"reg__loss\": [\n",
        "        {\"name\": \"QR\", \"qt\": 0.5},\n",
        "        {\"name\": \"huber\", \"tau\": 1.0},    # Huber needs tau\n",
        "        {\"name\": \"SVR\", \"epsilon\": 0.1},  # SVR needs epsilon\n",
        "    ],\n",
        "    \"reg__C\": [0.1, 1.0, 10.0],\n",
        "    \"reg__fit_intercept\": [True, False],\n",
        "    \"reg__intercept_scaling\": [0.5, 1.0],\n",
        "    \"reg__max_iter\": [5000, 8000],\n",
        "    \"reg__constraint\": [\n",
        "        [],                              # no constraint\n",
        "        [{\"name\": \"nonnegative\"}],\n",
        "        [{\"name\": \"fair\", \"sen_idx\": [0], \"tol_sen\": 0.1}],\n",
        "    ],\n",
        "}"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Ulsm5DtPHluB",
        "outputId": "fa5e76b3-f7bb-4a85-82cd-ce7d9b624915"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "CV R^2 scores: [0.99578266 0.99573973 0.99608371 0.99525645 0.9949942 ]\n",
            "Mean CV R^2: 0.9955713512215377\n"
          ]
        }
      ],
      "source": [
        "# cross_val_score function\n",
        "\n",
        "cv_scores = cross_val_score(\n",
        "    pipe,\n",
        "    X_train, y_train,\n",
        "    cv=5,\n",
        "    scoring=\"r2\",\n",
        "    n_jobs=-1,\n",
        ")\n",
        "print(\"CV R^2 scores:\", cv_scores)\n",
        "print(\"Mean CV R^2:\", np.mean(cv_scores))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 243
        },
        "id": "19c8A6KqHn4u",
        "outputId": "c26d6e76-9316-458f-ff80-ef9dd70ef473"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Fitting 5 folds for each of 216 candidates, totalling 1080 fits\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.12/dist-packages/rehline/_class.py:419: ConvergenceWarning: ReHLine failed to converge, increase the number of iterations: `max_iter`.\n",
            "  warnings.warn(\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<style>#sk-container-id-2 {\n",
              "  /* Definition of color scheme common for light and dark mode */\n",
              "  --sklearn-color-text: #000;\n",
              "  --sklearn-color-text-muted: #666;\n",
              "  --sklearn-color-line: gray;\n",
              "  /* Definition of color scheme for unfitted estimators */\n",
              "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
              "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
              "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
              "  --sklearn-color-unfitted-level-3: chocolate;\n",
              "  /* Definition of color scheme for fitted estimators */\n",
              "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
              "  --sklearn-color-fitted-level-1: #d4ebff;\n",
              "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
              "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
              "\n",
              "  /* Specific color for light theme */\n",
              "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
              "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
              "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
              "  --sklearn-color-icon: #696969;\n",
              "\n",
              "  @media (prefers-color-scheme: dark) {\n",
              "    /* Redefinition of color scheme for dark theme */\n",
              "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
              "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
              "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
              "    --sklearn-color-icon: #878787;\n",
              "  }\n",
              "}\n",
              "\n",
              "#sk-container-id-2 {\n",
              "  color: var(--sklearn-color-text);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 pre {\n",
              "  padding: 0;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 input.sk-hidden--visually {\n",
              "  border: 0;\n",
              "  clip: rect(1px 1px 1px 1px);\n",
              "  clip: rect(1px, 1px, 1px, 1px);\n",
              "  height: 1px;\n",
              "  margin: -1px;\n",
              "  overflow: hidden;\n",
              "  padding: 0;\n",
              "  position: absolute;\n",
              "  width: 1px;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-dashed-wrapped {\n",
              "  border: 1px dashed var(--sklearn-color-line);\n",
              "  margin: 0 0.4em 0.5em 0.4em;\n",
              "  box-sizing: border-box;\n",
              "  padding-bottom: 0.4em;\n",
              "  background-color: var(--sklearn-color-background);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-container {\n",
              "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
              "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
              "     so we also need the `!important` here to be able to override the\n",
              "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
              "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
              "  display: inline-block !important;\n",
              "  position: relative;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-text-repr-fallback {\n",
              "  display: none;\n",
              "}\n",
              "\n",
              "div.sk-parallel-item,\n",
              "div.sk-serial,\n",
              "div.sk-item {\n",
              "  /* draw centered vertical line to link estimators */\n",
              "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
              "  background-size: 2px 100%;\n",
              "  background-repeat: no-repeat;\n",
              "  background-position: center center;\n",
              "}\n",
              "\n",
              "/* Parallel-specific style estimator block */\n",
              "\n",
              "#sk-container-id-2 div.sk-parallel-item::after {\n",
              "  content: \"\";\n",
              "  width: 100%;\n",
              "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
              "  flex-grow: 1;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-parallel {\n",
              "  display: flex;\n",
              "  align-items: stretch;\n",
              "  justify-content: center;\n",
              "  background-color: var(--sklearn-color-background);\n",
              "  position: relative;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-parallel-item {\n",
              "  display: flex;\n",
              "  flex-direction: column;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-parallel-item:first-child::after {\n",
              "  align-self: flex-end;\n",
              "  width: 50%;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-parallel-item:last-child::after {\n",
              "  align-self: flex-start;\n",
              "  width: 50%;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-parallel-item:only-child::after {\n",
              "  width: 0;\n",
              "}\n",
              "\n",
              "/* Serial-specific style estimator block */\n",
              "\n",
              "#sk-container-id-2 div.sk-serial {\n",
              "  display: flex;\n",
              "  flex-direction: column;\n",
              "  align-items: center;\n",
              "  background-color: var(--sklearn-color-background);\n",
              "  padding-right: 1em;\n",
              "  padding-left: 1em;\n",
              "}\n",
              "\n",
              "\n",
              "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
              "clickable and can be expanded/collapsed.\n",
              "- Pipeline and ColumnTransformer use this feature and define the default style\n",
              "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
              "*/\n",
              "\n",
              "/* Pipeline and ColumnTransformer style (default) */\n",
              "\n",
              "#sk-container-id-2 div.sk-toggleable {\n",
              "  /* Default theme specific background. It is overwritten whether we have a\n",
              "  specific estimator or a Pipeline/ColumnTransformer */\n",
              "  background-color: var(--sklearn-color-background);\n",
              "}\n",
              "\n",
              "/* Toggleable label */\n",
              "#sk-container-id-2 label.sk-toggleable__label {\n",
              "  cursor: pointer;\n",
              "  display: flex;\n",
              "  width: 100%;\n",
              "  margin-bottom: 0;\n",
              "  padding: 0.5em;\n",
              "  box-sizing: border-box;\n",
              "  text-align: center;\n",
              "  align-items: start;\n",
              "  justify-content: space-between;\n",
              "  gap: 0.5em;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 label.sk-toggleable__label .caption {\n",
              "  font-size: 0.6rem;\n",
              "  font-weight: lighter;\n",
              "  color: var(--sklearn-color-text-muted);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 label.sk-toggleable__label-arrow:before {\n",
              "  /* Arrow on the left of the label */\n",
              "  content: \"▸\";\n",
              "  float: left;\n",
              "  margin-right: 0.25em;\n",
              "  color: var(--sklearn-color-icon);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {\n",
              "  color: var(--sklearn-color-text);\n",
              "}\n",
              "\n",
              "/* Toggleable content - dropdown */\n",
              "\n",
              "#sk-container-id-2 div.sk-toggleable__content {\n",
              "  max-height: 0;\n",
              "  max-width: 0;\n",
              "  overflow: hidden;\n",
              "  text-align: left;\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-0);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-toggleable__content.fitted {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-0);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-toggleable__content pre {\n",
              "  margin: 0.2em;\n",
              "  border-radius: 0.25em;\n",
              "  color: var(--sklearn-color-text);\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-0);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-toggleable__content.fitted pre {\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-0);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
              "  /* Expand drop-down */\n",
              "  max-height: 200px;\n",
              "  max-width: 100%;\n",
              "  overflow: auto;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
              "  content: \"▾\";\n",
              "}\n",
              "\n",
              "/* Pipeline/ColumnTransformer-specific style */\n",
              "\n",
              "#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
              "  color: var(--sklearn-color-text);\n",
              "  background-color: var(--sklearn-color-unfitted-level-2);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
              "  background-color: var(--sklearn-color-fitted-level-2);\n",
              "}\n",
              "\n",
              "/* Estimator-specific style */\n",
              "\n",
              "/* Colorize estimator box */\n",
              "#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-2);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-2);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-label label.sk-toggleable__label,\n",
              "#sk-container-id-2 div.sk-label label {\n",
              "  /* The background is the default theme color */\n",
              "  color: var(--sklearn-color-text-on-default-background);\n",
              "}\n",
              "\n",
              "/* On hover, darken the color of the background */\n",
              "#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {\n",
              "  color: var(--sklearn-color-text);\n",
              "  background-color: var(--sklearn-color-unfitted-level-2);\n",
              "}\n",
              "\n",
              "/* Label box, darken color on hover, fitted */\n",
              "#sk-container-id-2 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
              "  color: var(--sklearn-color-text);\n",
              "  background-color: var(--sklearn-color-fitted-level-2);\n",
              "}\n",
              "\n",
              "/* Estimator label */\n",
              "\n",
              "#sk-container-id-2 div.sk-label label {\n",
              "  font-family: monospace;\n",
              "  font-weight: bold;\n",
              "  display: inline-block;\n",
              "  line-height: 1.2em;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-label-container {\n",
              "  text-align: center;\n",
              "}\n",
              "\n",
              "/* Estimator-specific */\n",
              "#sk-container-id-2 div.sk-estimator {\n",
              "  font-family: monospace;\n",
              "  border: 1px dotted var(--sklearn-color-border-box);\n",
              "  border-radius: 0.25em;\n",
              "  box-sizing: border-box;\n",
              "  margin-bottom: 0.5em;\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-0);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-estimator.fitted {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-0);\n",
              "}\n",
              "\n",
              "/* on hover */\n",
              "#sk-container-id-2 div.sk-estimator:hover {\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-2);\n",
              "}\n",
              "\n",
              "#sk-container-id-2 div.sk-estimator.fitted:hover {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-2);\n",
              "}\n",
              "\n",
              "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
              "\n",
              "/* Common style for \"i\" and \"?\" */\n",
              "\n",
              ".sk-estimator-doc-link,\n",
              "a:link.sk-estimator-doc-link,\n",
              "a:visited.sk-estimator-doc-link {\n",
              "  float: right;\n",
              "  font-size: smaller;\n",
              "  line-height: 1em;\n",
              "  font-family: monospace;\n",
              "  background-color: var(--sklearn-color-background);\n",
              "  border-radius: 1em;\n",
              "  height: 1em;\n",
              "  width: 1em;\n",
              "  text-decoration: none !important;\n",
              "  margin-left: 0.5em;\n",
              "  text-align: center;\n",
              "  /* unfitted */\n",
              "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
              "  color: var(--sklearn-color-unfitted-level-1);\n",
              "}\n",
              "\n",
              ".sk-estimator-doc-link.fitted,\n",
              "a:link.sk-estimator-doc-link.fitted,\n",
              "a:visited.sk-estimator-doc-link.fitted {\n",
              "  /* fitted */\n",
              "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
              "  color: var(--sklearn-color-fitted-level-1);\n",
              "}\n",
              "\n",
              "/* On hover */\n",
              "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
              ".sk-estimator-doc-link:hover,\n",
              "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
              ".sk-estimator-doc-link:hover {\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-3);\n",
              "  color: var(--sklearn-color-background);\n",
              "  text-decoration: none;\n",
              "}\n",
              "\n",
              "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
              ".sk-estimator-doc-link.fitted:hover,\n",
              "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
              ".sk-estimator-doc-link.fitted:hover {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-3);\n",
              "  color: var(--sklearn-color-background);\n",
              "  text-decoration: none;\n",
              "}\n",
              "\n",
              "/* Span, style for the box shown on hovering the info icon */\n",
              ".sk-estimator-doc-link span {\n",
              "  display: none;\n",
              "  z-index: 9999;\n",
              "  position: relative;\n",
              "  font-weight: normal;\n",
              "  right: .2ex;\n",
              "  padding: .5ex;\n",
              "  margin: .5ex;\n",
              "  width: min-content;\n",
              "  min-width: 20ex;\n",
              "  max-width: 50ex;\n",
              "  color: var(--sklearn-color-text);\n",
              "  box-shadow: 2pt 2pt 4pt #999;\n",
              "  /* unfitted */\n",
              "  background: var(--sklearn-color-unfitted-level-0);\n",
              "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
              "}\n",
              "\n",
              ".sk-estimator-doc-link.fitted span {\n",
              "  /* fitted */\n",
              "  background: var(--sklearn-color-fitted-level-0);\n",
              "  border: var(--sklearn-color-fitted-level-3);\n",
              "}\n",
              "\n",
              ".sk-estimator-doc-link:hover span {\n",
              "  display: block;\n",
              "}\n",
              "\n",
              "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
              "\n",
              "#sk-container-id-2 a.estimator_doc_link {\n",
              "  float: right;\n",
              "  font-size: 1rem;\n",
              "  line-height: 1em;\n",
              "  font-family: monospace;\n",
              "  background-color: var(--sklearn-color-background);\n",
              "  border-radius: 1rem;\n",
              "  height: 1rem;\n",
              "  width: 1rem;\n",
              "  text-decoration: none;\n",
              "  /* unfitted */\n",
              "  color: var(--sklearn-color-unfitted-level-1);\n",
              "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 a.estimator_doc_link.fitted {\n",
              "  /* fitted */\n",
              "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
              "  color: var(--sklearn-color-fitted-level-1);\n",
              "}\n",
              "\n",
              "/* On hover */\n",
              "#sk-container-id-2 a.estimator_doc_link:hover {\n",
              "  /* unfitted */\n",
              "  background-color: var(--sklearn-color-unfitted-level-3);\n",
              "  color: var(--sklearn-color-background);\n",
              "  text-decoration: none;\n",
              "}\n",
              "\n",
              "#sk-container-id-2 a.estimator_doc_link.fitted:hover {\n",
              "  /* fitted */\n",
              "  background-color: var(--sklearn-color-fitted-level-3);\n",
              "}\n",
              "</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>GridSearchCV(cv=5,\n",
              "             estimator=Pipeline(steps=[(&#x27;scaler&#x27;, StandardScaler()),\n",
              "                                       (&#x27;reg&#x27;, plq_Ridge_Regressor())]),\n",
              "             n_jobs=-1,\n",
              "             param_grid={&#x27;reg__C&#x27;: [0.1, 1.0, 10.0],\n",
              "                         &#x27;reg__constraint&#x27;: [[], [{&#x27;name&#x27;: &#x27;nonnegative&#x27;}],\n",
              "                                             [{&#x27;name&#x27;: &#x27;fair&#x27;, &#x27;sen_idx&#x27;: [0],\n",
              "                                               &#x27;tol_sen&#x27;: 0.1}]],\n",
              "                         &#x27;reg__fit_intercept&#x27;: [True, False],\n",
              "                         &#x27;reg__intercept_scaling&#x27;: [0.5, 1.0],\n",
              "                         &#x27;reg__loss&#x27;: [{&#x27;name&#x27;: &#x27;QR&#x27;, &#x27;qt&#x27;: 0.5},\n",
              "                                       {&#x27;name&#x27;: &#x27;huber&#x27;, &#x27;tau&#x27;: 1.0},\n",
              "                                       {&#x27;epsilon&#x27;: 0.1, &#x27;name&#x27;: &#x27;SVR&#x27;}],\n",
              "                         &#x27;reg__max_iter&#x27;: [5000, 8000]},\n",
              "             scoring=&#x27;r2&#x27;, verbose=1)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-5\" type=\"checkbox\" ><label for=\"sk-estimator-id-5\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>GridSearchCV</div></div><div><a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.6/modules/generated/sklearn.model_selection.GridSearchCV.html\">?<span>Documentation for GridSearchCV</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></div></label><div class=\"sk-toggleable__content fitted\"><pre>GridSearchCV(cv=5,\n",
              "             estimator=Pipeline(steps=[(&#x27;scaler&#x27;, StandardScaler()),\n",
              "                                       (&#x27;reg&#x27;, plq_Ridge_Regressor())]),\n",
              "             n_jobs=-1,\n",
              "             param_grid={&#x27;reg__C&#x27;: [0.1, 1.0, 10.0],\n",
              "                         &#x27;reg__constraint&#x27;: [[], [{&#x27;name&#x27;: &#x27;nonnegative&#x27;}],\n",
              "                                             [{&#x27;name&#x27;: &#x27;fair&#x27;, &#x27;sen_idx&#x27;: [0],\n",
              "                                               &#x27;tol_sen&#x27;: 0.1}]],\n",
              "                         &#x27;reg__fit_intercept&#x27;: [True, False],\n",
              "                         &#x27;reg__intercept_scaling&#x27;: [0.5, 1.0],\n",
              "                         &#x27;reg__loss&#x27;: [{&#x27;name&#x27;: &#x27;QR&#x27;, &#x27;qt&#x27;: 0.5},\n",
              "                                       {&#x27;name&#x27;: &#x27;huber&#x27;, &#x27;tau&#x27;: 1.0},\n",
              "                                       {&#x27;epsilon&#x27;: 0.1, &#x27;name&#x27;: &#x27;SVR&#x27;}],\n",
              "                         &#x27;reg__max_iter&#x27;: [5000, 8000]},\n",
              "             scoring=&#x27;r2&#x27;, verbose=1)</pre></div> </div></div><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-6\" type=\"checkbox\" ><label for=\"sk-estimator-id-6\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>best_estimator_: Pipeline</div></div></label><div class=\"sk-toggleable__content fitted\"><pre>Pipeline(steps=[(&#x27;scaler&#x27;, StandardScaler()),\n",
              "                (&#x27;reg&#x27;,\n",
              "                 plq_Ridge_Regressor(C=10.0,\n",
              "                                     constraint=[{&#x27;name&#x27;: &#x27;nonnegative&#x27;}],\n",
              "                                     loss={&#x27;epsilon&#x27;: 0.1, &#x27;name&#x27;: &#x27;SVR&#x27;},\n",
              "                                     max_iter=8000))])</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-7\" type=\"checkbox\" ><label for=\"sk-estimator-id-7\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>StandardScaler</div></div><div><a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.6/modules/generated/sklearn.preprocessing.StandardScaler.html\">?<span>Documentation for StandardScaler</span></a></div></label><div class=\"sk-toggleable__content fitted\"><pre>StandardScaler()</pre></div> </div></div><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-8\" type=\"checkbox\" ><label for=\"sk-estimator-id-8\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>plq_Ridge_Regressor</div></div></label><div class=\"sk-toggleable__content fitted\"><pre>plq_Ridge_Regressor(C=10.0, constraint=[{&#x27;name&#x27;: &#x27;nonnegative&#x27;}],\n",
              "                    loss={&#x27;epsilon&#x27;: 0.1, &#x27;name&#x27;: &#x27;SVR&#x27;}, max_iter=8000)</pre></div> </div></div></div></div></div></div></div></div></div></div></div>"
            ],
            "text/plain": [
              "GridSearchCV(cv=5,\n",
              "             estimator=Pipeline(steps=[('scaler', StandardScaler()),\n",
              "                                       ('reg', plq_Ridge_Regressor())]),\n",
              "             n_jobs=-1,\n",
              "             param_grid={'reg__C': [0.1, 1.0, 10.0],\n",
              "                         'reg__constraint': [[], [{'name': 'nonnegative'}],\n",
              "                                             [{'name': 'fair', 'sen_idx': [0],\n",
              "                                               'tol_sen': 0.1}]],\n",
              "                         'reg__fit_intercept': [True, False],\n",
              "                         'reg__intercept_scaling': [0.5, 1.0],\n",
              "                         'reg__loss': [{'name': 'QR', 'qt': 0.5},\n",
              "                                       {'name': 'huber', 'tau': 1.0},\n",
              "                                       {'epsilon': 0.1, 'name': 'SVR'}],\n",
              "                         'reg__max_iter': [5000, 8000]},\n",
              "             scoring='r2', verbose=1)"
            ]
          },
          "execution_count": 20,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# use GridSearchCV to tune the hyperparameters\n",
        "\n",
        "grid = GridSearchCV(\n",
        "    estimator=pipe,\n",
        "    param_grid=param_grid,\n",
        "    scoring=\"r2\",\n",
        "    cv=5,\n",
        "    n_jobs=-1,\n",
        "    refit=True,\n",
        "    verbose=1,\n",
        ")\n",
        "\n",
        "grid.fit(X_train, y_train)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "_JhyOqu4Hp6G",
        "outputId": "e70ab254-015b-4327-82a6-fe235a333f6d"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Best params: {'reg__C': 10.0, 'reg__constraint': [{'name': 'nonnegative'}], 'reg__fit_intercept': True, 'reg__intercept_scaling': 1.0, 'reg__loss': {'name': 'SVR', 'epsilon': 0.1}, 'reg__max_iter': 8000}\n",
            "Best CV R^2: 0.9967851378070526\n"
          ]
        }
      ],
      "source": [
        "# print the best parameters and the best CV R^2 score\n",
        "print(\"Best params:\", grid.best_params_)\n",
        "print(\"Best CV R^2:\", grid.best_score_)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "s_Hp2L0IHtMD",
        "outputId": "be85ae0b-079f-49e9-823f-8184ca93c838"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Test R^2: 0.9968147697852413\n",
            "Test MSE: 103.43336817904354\n"
          ]
        }
      ],
      "source": [
        "# use the best estimator to fit and predict the model\n",
        "best_model = grid.best_estimator_\n",
        "y_pred = best_model.predict(X_test)\n",
        "\n",
        "print(\"Test R^2:\", r2_score(y_test, y_pred))\n",
        "print(\"Test MSE:\", mean_squared_error(y_test, y_pred))"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
