Repository: vanderschaarlab/temporai (language: python)

Issue:
[Enhancement] Introduce plugin types
Introduce plugin types which can be listed separately, so that we can have clear separation between models/metrics/data sources etc. plugins.


Discussion / hints:

Fix patch:
diff --git a/.coveragerc b/.coveragerc
index 7b566376..64625f96 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -29,3 +29,5 @@ exclude_lines =
     # Don't complain if non-runnable code isn't run:
     if 0:
     if __name__ == .__main__.:
+
+    @overload
diff --git a/docs/pre_build_notebooks.py b/docs/pre_build_notebooks.py
index 73370ff2..67897536 100644
--- a/docs/pre_build_notebooks.py
+++ b/docs/pre_build_notebooks.py
@@ -56,6 +56,7 @@ def modify_and_copy_nb(notebook_path: str, output_path: str, notebook_link: str)
     # Add links to Colab notebook.
     # Add notebook_link as the first cell
     link_cell = nbformat.v4.new_markdown_cell(notebook_link)
+    link_cell.id = ""
     new_cells.insert(0, link_cell)  # Insert at the beginning
     nb.cells = new_cells
 
diff --git a/docs/user_guide/data/tutorial01_data_format.ipynb b/docs/user_guide/data/tutorial01_data_format.ipynb
index cfd756db..2716c7e1 100644
--- a/docs/user_guide/data/tutorial01_data_format.ipynb
+++ b/docs/user_guide/data/tutorial01_data_format.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "32cd32f2",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/data/tutorial01_data_format.ipynb)"
@@ -42,7 +42,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 18,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -765,7 +765,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 25,
+   "execution_count": 10,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -774,7 +774,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 26,
+   "execution_count": 11,
    "metadata": {},
    "outputs": [
     {
@@ -873,7 +873,7 @@
        "sample_2   9               31       3.1        c"
       ]
      },
-     "execution_count": 26,
+     "execution_count": 11,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -886,7 +886,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 27,
+   "execution_count": 12,
    "metadata": {},
    "outputs": [
     {
@@ -908,7 +908,7 @@
        "        [-999.0, -999.0, -999.0]]], dtype=object)"
       ]
      },
-     "execution_count": 27,
+     "execution_count": 12,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -921,7 +921,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 28,
+   "execution_count": 13,
    "metadata": {},
    "outputs": [
     {
@@ -942,7 +942,7 @@
        " sample_2   9               31       3.1        c]"
       ]
      },
-     "execution_count": 28,
+     "execution_count": 13,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -955,7 +955,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 29,
+   "execution_count": 14,
    "metadata": {},
    "outputs": [
     {
@@ -976,7 +976,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 15,
    "metadata": {},
    "outputs": [
     {
@@ -1003,7 +1003,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 33,
+   "execution_count": 16,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -1016,7 +1016,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 34,
+   "execution_count": 17,
    "metadata": {},
    "outputs": [
     {
@@ -1101,7 +1101,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 35,
+   "execution_count": 18,
    "metadata": {},
    "outputs": [
     {
@@ -1201,7 +1201,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/data/tutorial02_datasets.ipynb b/docs/user_guide/data/tutorial02_datasets.ipynb
index d276eb92..590b5866 100644
--- a/docs/user_guide/data/tutorial02_datasets.ipynb
+++ b/docs/user_guide/data/tutorial02_datasets.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "9aa22a2b",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/data/tutorial02_datasets.ipynb)"
@@ -2301,7 +2301,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/data/tutorial03_dataloaders.ipynb b/docs/user_guide/data/tutorial03_dataloaders.ipynb
index 451929c1..3850afe9 100644
--- a/docs/user_guide/data/tutorial03_dataloaders.ipynb
+++ b/docs/user_guide/data/tutorial03_dataloaders.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "731ff030",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/data/tutorial03_dataloaders.ipynb)"
@@ -73,7 +73,7 @@
     {
      "data": {
       "text/plain": [
-       "<tempor.utils.dataloaders.sine.SineDataLoader at 0x7f8155017fa0>"
+       "<tempor.utils.dataloaders.sine.SineDataLoader at 0x7fcd2dc85910>"
       ]
      },
      "execution_count": 3,
@@ -570,7 +570,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 21,
+   "execution_count": 8,
    "metadata": {},
    "outputs": [
     {
@@ -581,7 +581,13 @@
       "--------------------------------------------------------------------------------\n",
       "\n",
       "DummyTemporalPredictionDataLoader loads the following dataset:\n",
-      "\n",
+      "\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
       "TemporalPredictionDataset(\n",
       "    time_series=TimeSeriesSamples([100, *, 5]),\n",
       "    static=StaticSamples([100, 3]),\n",
@@ -2319,9 +2325,9 @@
       ],
       "text/plain": [
        "TimeSeriesSamples with data:\n",
-       "                     drug  ascites  hepatomegaly  spiders  edema  histologic   \n",
+       "                     drug  ascites  hepatomegaly  spiders  edema  histologic  \\\n",
        "sample_idx time_idx                                                            \n",
-       "1          0.569489   0.0      1.0           1.0      1.0    1.0         3.0  \\\n",
+       "1          0.569489   0.0      1.0           1.0      1.0    1.0         3.0   \n",
        "           1.095170   0.0      1.0           1.0      1.0    1.0         3.0   \n",
        "2          5.319790   0.0      1.0           1.0      1.0    1.0         2.0   \n",
        "           6.261636   0.0      1.0           1.0      1.0    1.0         2.0   \n",
@@ -2333,9 +2339,9 @@
        "           3.425145   1.0      0.0           0.0      0.0    0.0         1.0   \n",
        "           3.989158   1.0      0.0           0.0      1.0    0.0         1.0   \n",
        "\n",
-       "                     serBilir   serChol   albumin  alkaline      SGOT   \n",
+       "                     serBilir   serChol   albumin  alkaline      SGOT  \\\n",
        "sample_idx time_idx                                                     \n",
-       "1          0.569489  3.281890  0.000000 -0.894575  0.195532 -1.485263  \\\n",
+       "1          0.569489  3.281890  0.000000 -0.894575  0.195532 -1.485263   \n",
        "           1.095170  2.015877 -0.469461 -1.570646  0.285613  0.195488   \n",
        "2          5.319790  0.172710 -0.658914 -1.431455 -0.605844 -0.442126   \n",
        "           6.261636 -0.013468 -0.603657 -1.172958 -0.512364 -0.046806   \n",
@@ -2645,12 +2651,12 @@
        "    <tr>\n",
        "      <th>1</th>\n",
        "      <td>-1.001889</td>\n",
-       "      <td>-0.541524</td>\n",
+       "      <td>-0.541523</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>2</th>\n",
        "      <td>-1.070862</td>\n",
-       "      <td>-0.589326</td>\n",
+       "      <td>-0.589325</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>3</th>\n",
@@ -2672,7 +2678,7 @@
        "      <th rowspan=\"5\" valign=\"top\">39</th>\n",
        "      <th>5</th>\n",
        "      <td>0.959902</td>\n",
-       "      <td>-0.690057</td>\n",
+       "      <td>-0.690056</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>6</th>\n",
@@ -2682,12 +2688,12 @@
        "    <tr>\n",
        "      <th>7</th>\n",
        "      <td>2.233045</td>\n",
-       "      <td>0.637906</td>\n",
+       "      <td>0.637905</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>8</th>\n",
        "      <td>1.645018</td>\n",
-       "      <td>1.056963</td>\n",
+       "      <td>1.056957</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>9</th>\n",
@@ -2704,15 +2710,15 @@
        "                         k_in         p\n",
        "sample_idx time_idx                    \n",
        "0          0        -0.781441 -0.245827\n",
-       "           1        -1.001889 -0.541524\n",
-       "           2        -1.070862 -0.589326\n",
+       "           1        -1.001889 -0.541523\n",
+       "           2        -1.070862 -0.589325\n",
        "           3        -1.425115 -1.065485\n",
        "           4        -1.841006 -1.542429\n",
        "...                       ...       ...\n",
-       "39         5         0.959902 -0.690057\n",
+       "39         5         0.959902 -0.690056\n",
        "           6         1.683426 -0.128967\n",
-       "           7         2.233045  0.637906\n",
-       "           8         1.645018  1.056963\n",
+       "           7         2.233045  0.637905\n",
+       "           8         1.645018  1.056957\n",
        "           9         0.333051  1.048721\n",
        "\n",
        "[400 rows x 2 columns]"
@@ -2804,7 +2810,7 @@
        "    </tr>\n",
        "    <tr>\n",
        "      <th>9</th>\n",
-       "      <td>-0.431988</td>\n",
+       "      <td>-0.431990</td>\n",
        "    </tr>\n",
        "  </tbody>\n",
        "</table>\n",
@@ -2825,7 +2831,7 @@
        "           6        -1.495843\n",
        "           7        -1.193632\n",
        "           8        -0.850845\n",
-       "           9        -0.431988\n",
+       "           9        -0.431990\n",
        "\n",
        "[400 rows x 1 columns]"
       ]
@@ -3510,6 +3516,663 @@
      },
      "metadata": {},
      "output_type": "display_data"
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "\n",
+      "--------------------------------------------------------------------------------\n",
+      "\n",
+      "UCIDiabetesDataLoader loads the following dataset:\n",
+      "\n",
+      "Downloading file from URL: https://archive.ics.uci.edu/ml/machine-learning-databases/diabetes/Index\n",
+      "Downloading file from URL: https://archive.ics.uci.edu/ml/machine-learning-databases/diabetes/README\n",
+      "Downloading file from URL: https://archive.ics.uci.edu/ml/machine-learning-databases/diabetes/diabetes-data.tar.Z\n",
+      "TemporalPredictionDataset(\n",
+      "    time_series=TimeSeriesSamples([70, *, 18]),\n",
+      "    predictive=TemporalPredictionTaskData(\n",
+      "        targets=TimeSeriesSamples([70, *, 1])\n",
+      "    )\n",
+      ")\n",
+      "This contains:\n",
+      "\n",
+      "time_series:\n"
+     ]
+    },
+    {
+     "data": {
+      "text/html": [
+       "<p><span style=\"font-family: monospace;\">TimeSeriesSamples</span> with data:</p><div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th>typical_exercise_activity</th>\n",
+       "      <th>unspecified_special_event</th>\n",
+       "      <th>ultralente_insulin_dose</th>\n",
+       "      <th>more-than-usual_exercise_activity</th>\n",
+       "      <th>post-lunch_blood_glucose_measurement</th>\n",
+       "      <th>less-than-usual_meal_ingestion</th>\n",
+       "      <th>regular_insulin_dose</th>\n",
+       "      <th>post-breakfast_blood_glucose_measurement</th>\n",
+       "      <th>pre-breakfast_blood_glucose_measurement</th>\n",
+       "      <th>less-than-usual_exercise_activity</th>\n",
+       "      <th>pre-supper_blood_glucose_measurement</th>\n",
+       "      <th>pre-lunch_blood_glucose_measurement</th>\n",
+       "      <th>more-than-usual_meal_ingestion</th>\n",
+       "      <th>post-supper_blood_glucose_measurement</th>\n",
+       "      <th>unspecified_blood_glucose_measurement</th>\n",
+       "      <th>nph_insulin_dose</th>\n",
+       "      <th>pre-snack_blood_glucose_measurement</th>\n",
+       "      <th>typical_meal_ingestion</th>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>sample_idx</th>\n",
+       "      <th>time_idx</th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th rowspan=\"5\" valign=\"top\">0</th>\n",
+       "      <th>0</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>9.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>100.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>13.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>7.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>119.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>123.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>10.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>216.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>13.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>2.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>...</th>\n",
+       "      <th>...</th>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th rowspan=\"5\" valign=\"top\">69</th>\n",
+       "      <th>146</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>145.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>147</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>1.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>259.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>7.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>148</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>7.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>149</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>7.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>150</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>7.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "<p>18199 rows × 18 columns</p>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "TimeSeriesSamples with data:\n",
+       "                     typical_exercise_activity  unspecified_special_event  \\\n",
+       "sample_idx time_idx                                                         \n",
+       "0          0                               NaN                        NaN   \n",
+       "           1                               NaN                        NaN   \n",
+       "           2                               NaN                        NaN   \n",
+       "           3                               NaN                        NaN   \n",
+       "           4                               NaN                        NaN   \n",
+       "...                                        ...                        ...   \n",
+       "69         146                             NaN                        NaN   \n",
+       "           147                             NaN                        NaN   \n",
+       "           148                             NaN                        NaN   \n",
+       "           149                             NaN                        NaN   \n",
+       "           150                             NaN                        NaN   \n",
+       "\n",
+       "                     ultralente_insulin_dose  \\\n",
+       "sample_idx time_idx                            \n",
+       "0          0                             NaN   \n",
+       "           1                             NaN   \n",
+       "           2                             NaN   \n",
+       "           3                             NaN   \n",
+       "           4                             NaN   \n",
+       "...                                      ...   \n",
+       "69         146                           NaN   \n",
+       "           147                           NaN   \n",
+       "           148                           NaN   \n",
+       "           149                           NaN   \n",
+       "           150                           NaN   \n",
+       "\n",
+       "                     more-than-usual_exercise_activity  \\\n",
+       "sample_idx time_idx                                      \n",
+       "0          0                                       NaN   \n",
+       "           1                                       NaN   \n",
+       "           2                                       NaN   \n",
+       "           3                                       NaN   \n",
+       "           4                                       NaN   \n",
+       "...                                                ...   \n",
+       "69         146                                     NaN   \n",
+       "           147                                     NaN   \n",
+       "           148                                     NaN   \n",
+       "           149                                     NaN   \n",
+       "           150                                     NaN   \n",
+       "\n",
+       "                     post-lunch_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                         \n",
+       "0          0                                          NaN   \n",
+       "           1                                          NaN   \n",
+       "           2                                          NaN   \n",
+       "           3                                          NaN   \n",
+       "           4                                          NaN   \n",
+       "...                                                   ...   \n",
+       "69         146                                        NaN   \n",
+       "           147                                        NaN   \n",
+       "           148                                        NaN   \n",
+       "           149                                        NaN   \n",
+       "           150                                        NaN   \n",
+       "\n",
+       "                     less-than-usual_meal_ingestion  regular_insulin_dose  \\\n",
+       "sample_idx time_idx                                                         \n",
+       "0          0                                    NaN                   9.0   \n",
+       "           1                                    NaN                   7.0   \n",
+       "           2                                    NaN                   NaN   \n",
+       "           3                                    NaN                  10.0   \n",
+       "           4                                    NaN                   2.0   \n",
+       "...                                             ...                   ...   \n",
+       "69         146                                  NaN                   NaN   \n",
+       "           147                                  NaN                   1.0   \n",
+       "           148                                  NaN                   NaN   \n",
+       "           149                                  NaN                   NaN   \n",
+       "           150                                  NaN                   NaN   \n",
+       "\n",
+       "                     post-breakfast_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                             \n",
+       "0          0                                              NaN   \n",
+       "           1                                              NaN   \n",
+       "           2                                              NaN   \n",
+       "           3                                              NaN   \n",
+       "           4                                              NaN   \n",
+       "...                                                       ...   \n",
+       "69         146                                            NaN   \n",
+       "           147                                            NaN   \n",
+       "           148                                            NaN   \n",
+       "           149                                            NaN   \n",
+       "           150                                            NaN   \n",
+       "\n",
+       "                     pre-breakfast_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                            \n",
+       "0          0                                           100.0   \n",
+       "           1                                             NaN   \n",
+       "           2                                             NaN   \n",
+       "           3                                           216.0   \n",
+       "           4                                             NaN   \n",
+       "...                                                      ...   \n",
+       "69         146                                           NaN   \n",
+       "           147                                         259.0   \n",
+       "           148                                           NaN   \n",
+       "           149                                           NaN   \n",
+       "           150                                           NaN   \n",
+       "\n",
+       "                     less-than-usual_exercise_activity  \\\n",
+       "sample_idx time_idx                                      \n",
+       "0          0                                       NaN   \n",
+       "           1                                       NaN   \n",
+       "           2                                       NaN   \n",
+       "           3                                       NaN   \n",
+       "           4                                       NaN   \n",
+       "...                                                ...   \n",
+       "69         146                                     NaN   \n",
+       "           147                                     NaN   \n",
+       "           148                                     NaN   \n",
+       "           149                                     NaN   \n",
+       "           150                                     NaN   \n",
+       "\n",
+       "                     pre-supper_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                         \n",
+       "0          0                                          NaN   \n",
+       "           1                                        119.0   \n",
+       "           2                                          NaN   \n",
+       "           3                                          NaN   \n",
+       "           4                                          NaN   \n",
+       "...                                                   ...   \n",
+       "69         146                                        NaN   \n",
+       "           147                                        NaN   \n",
+       "           148                                        NaN   \n",
+       "           149                                        NaN   \n",
+       "           150                                        NaN   \n",
+       "\n",
+       "                     pre-lunch_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                        \n",
+       "0          0                                         NaN   \n",
+       "           1                                         NaN   \n",
+       "           2                                         NaN   \n",
+       "           3                                         NaN   \n",
+       "           4                                         NaN   \n",
+       "...                                                  ...   \n",
+       "69         146                                       NaN   \n",
+       "           147                                       NaN   \n",
+       "           148                                       NaN   \n",
+       "           149                                       NaN   \n",
+       "           150                                       NaN   \n",
+       "\n",
+       "                     more-than-usual_meal_ingestion  \\\n",
+       "sample_idx time_idx                                   \n",
+       "0          0                                    NaN   \n",
+       "           1                                    NaN   \n",
+       "           2                                    NaN   \n",
+       "           3                                    NaN   \n",
+       "           4                                    NaN   \n",
+       "...                                             ...   \n",
+       "69         146                                  NaN   \n",
+       "           147                                  NaN   \n",
+       "           148                                  NaN   \n",
+       "           149                                  NaN   \n",
+       "           150                                  NaN   \n",
+       "\n",
+       "                     post-supper_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                          \n",
+       "0          0                                           NaN   \n",
+       "           1                                           NaN   \n",
+       "           2                                           NaN   \n",
+       "           3                                           NaN   \n",
+       "           4                                           NaN   \n",
+       "...                                                    ...   \n",
+       "69         146                                         NaN   \n",
+       "           147                                         NaN   \n",
+       "           148                                         NaN   \n",
+       "           149                                         NaN   \n",
+       "           150                                         NaN   \n",
+       "\n",
+       "                     unspecified_blood_glucose_measurement  nph_insulin_dose  \\\n",
+       "sample_idx time_idx                                                            \n",
+       "0          0                                           NaN              13.0   \n",
+       "           1                                           NaN               NaN   \n",
+       "           2                                         123.0               NaN   \n",
+       "           3                                           NaN              13.0   \n",
+       "           4                                           NaN               NaN   \n",
+       "...                                                    ...               ...   \n",
+       "69         146                                       145.0               NaN   \n",
+       "           147                                         NaN               7.0   \n",
+       "           148                                         NaN               7.0   \n",
+       "           149                                         NaN               7.0   \n",
+       "           150                                         NaN               7.0   \n",
+       "\n",
+       "                     pre-snack_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                        \n",
+       "0          0                                         NaN   \n",
+       "           1                                         NaN   \n",
+       "           2                                         NaN   \n",
+       "           3                                         NaN   \n",
+       "           4                                         NaN   \n",
+       "...                                                  ...   \n",
+       "69         146                                       NaN   \n",
+       "           147                                       NaN   \n",
+       "           148                                       NaN   \n",
+       "           149                                       NaN   \n",
+       "           150                                       NaN   \n",
+       "\n",
+       "                     typical_meal_ingestion  \n",
+       "sample_idx time_idx                          \n",
+       "0          0                            NaN  \n",
+       "           1                            NaN  \n",
+       "           2                            NaN  \n",
+       "           3                            NaN  \n",
+       "           4                            NaN  \n",
+       "...                                     ...  \n",
+       "69         146                          NaN  \n",
+       "           147                          NaN  \n",
+       "           148                          NaN  \n",
+       "           149                          NaN  \n",
+       "           150                          NaN  \n",
+       "\n",
+       "[18199 rows x 18 columns]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "predictive.targets:\n"
+     ]
+    },
+    {
+     "data": {
+      "text/html": [
+       "<p><span style=\"font-family: monospace;\">TimeSeriesSamples</span> with data:</p><div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th>hypoglycemic_symptoms</th>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>sample_idx</th>\n",
+       "      <th>time_idx</th>\n",
+       "      <th></th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th rowspan=\"5\" valign=\"top\">0</th>\n",
+       "      <th>0</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>...</th>\n",
+       "      <th>...</th>\n",
+       "      <td>...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th rowspan=\"5\" valign=\"top\">69</th>\n",
+       "      <th>146</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>147</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>148</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>149</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>150</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "<p>18199 rows × 1 columns</p>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "TimeSeriesSamples with data:\n",
+       "                     hypoglycemic_symptoms\n",
+       "sample_idx time_idx                       \n",
+       "0          0                           NaN\n",
+       "           1                           NaN\n",
+       "           2                           NaN\n",
+       "           3                           NaN\n",
+       "           4                           NaN\n",
+       "...                                    ...\n",
+       "69         146                         NaN\n",
+       "           147                         NaN\n",
+       "           148                         NaN\n",
+       "           149                         NaN\n",
+       "           150                         NaN\n",
+       "\n",
+       "[18199 rows x 1 columns]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     }
    ],
    "source": [
@@ -3558,7 +4221,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/data/tutorial04_data_splitting.ipynb b/docs/user_guide/data/tutorial04_data_splitting.ipynb
index a06cd400..b91ba8ef 100644
--- a/docs/user_guide/data/tutorial04_data_splitting.ipynb
+++ b/docs/user_guide/data/tutorial04_data_splitting.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "991f6200",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/data/tutorial04_data_splitting.ipynb)"
@@ -182,7 +182,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/extending/tutorial01_custom_plugin.ipynb b/docs/user_guide/extending/tutorial01_custom_plugin.ipynb
index 806426a6..af193adc 100644
--- a/docs/user_guide/extending/tutorial01_custom_plugin.ipynb
+++ b/docs/user_guide/extending/tutorial01_custom_plugin.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "17135c54",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/extending/tutorial01_custom_plugin.ipynb)"
@@ -60,6 +60,8 @@
        " 'prediction.one_off.regression',\n",
        " 'prediction.temporal.classification',\n",
        " 'prediction.temporal.regression',\n",
+       " 'preprocessing.encoding.static',\n",
+       " 'preprocessing.encoding.temporal',\n",
        " 'preprocessing.imputation.static',\n",
        " 'preprocessing.imputation.temporal',\n",
        " 'preprocessing.nop',\n",
@@ -109,6 +111,7 @@
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"font-weight: bold\">}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'encoding'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_onehot_encoder'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_onehot_encoder'</span><span style=\"font-weight: bold\">]}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'imputation'</span>: <span style=\"font-weight: bold\">{</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_tabular_imputer'</span><span style=\"font-weight: bold\">]</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ffill'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_tabular_imputer'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'bfill'</span><span style=\"font-weight: bold\">]</span>\n",
@@ -137,6 +140,7 @@
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
        "\u001b[2;32m│   \u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   \u001b[0m\u001b[32m'preprocessing'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "\u001b[2;32m│   │   \u001b[0m\u001b[32m'encoding'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'imputation'\u001b[0m: \u001b[1m{\u001b[0m\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_tabular_imputer'\u001b[0m\u001b[1m]\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ffill'\u001b[0m, \u001b[32m'ts_tabular_imputer'\u001b[0m, \u001b[32m'bfill'\u001b[0m\u001b[1m]\u001b[0m\n",
@@ -197,6 +201,8 @@
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'prediction.one_off.regression'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.prediction.one_off.regression.BaseOneOffRegressor'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'prediction.temporal.classification'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.prediction.temporal.classification.BaseTemporalClassifier'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'prediction.temporal.regression'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.prediction.temporal.regression.BaseTemporalRegressor'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
+       "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.encoding.static'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.preprocessing.encoding._base.BaseEncoder'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
+       "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.encoding.temporal'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.preprocessing.encoding._base.BaseEncoder'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.imputation.static'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.preprocessing.imputation._base.BaseImputer'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.imputation.temporal'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.preprocessing.imputation._base.BaseImputer'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.nop'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.core._base_transformer.BaseTransformer'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
@@ -215,6 +221,8 @@
        "\u001b[39m    \u001b[0m\u001b[32m'prediction.one_off.regression'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.prediction.one_off.regression.BaseOneOffRegressor'\u001b[0m\u001b[39m>,\u001b[0m\n",
        "\u001b[39m    \u001b[0m\u001b[32m'prediction.temporal.classification'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.prediction.temporal.classification.BaseTemporalClassifier'\u001b[0m\u001b[39m>,\u001b[0m\n",
        "\u001b[39m    \u001b[0m\u001b[32m'prediction.temporal.regression'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.prediction.temporal.regression.BaseTemporalRegressor'\u001b[0m\u001b[39m>,\u001b[0m\n",
+       "\u001b[39m    \u001b[0m\u001b[32m'preprocessing.encoding.static'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.preprocessing.encoding._base.BaseEncoder'\u001b[0m\u001b[39m>,\u001b[0m\n",
+       "\u001b[39m    \u001b[0m\u001b[32m'preprocessing.encoding.temporal'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.preprocessing.encoding._base.BaseEncoder'\u001b[0m\u001b[39m>,\u001b[0m\n",
        "\u001b[39m    \u001b[0m\u001b[32m'preprocessing.imputation.static'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.preprocessing.imputation._base.BaseImputer'\u001b[0m\u001b[39m>,\u001b[0m\n",
        "\u001b[39m    \u001b[0m\u001b[32m'preprocessing.imputation.temporal'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.preprocessing.imputation._base.BaseImputer'\u001b[0m\u001b[39m>,\u001b[0m\n",
        "\u001b[39m    \u001b[0m\u001b[32m'preprocessing.nop'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.core._base_transformer.BaseTransformer'\u001b[0m\u001b[39m>,\u001b[0m\n",
@@ -466,6 +474,7 @@
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"font-weight: bold\">}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'encoding'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_onehot_encoder'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_onehot_encoder'</span><span style=\"font-weight: bold\">]}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'imputation'</span>: <span style=\"font-weight: bold\">{</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_tabular_imputer'</span><span style=\"font-weight: bold\">]</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ffill'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_tabular_imputer'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'bfill'</span><span style=\"font-weight: bold\">]</span>\n",
@@ -500,6 +509,7 @@
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
        "\u001b[2;32m│   \u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   \u001b[0m\u001b[32m'preprocessing'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "\u001b[2;32m│   │   \u001b[0m\u001b[32m'encoding'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'imputation'\u001b[0m: \u001b[1m{\u001b[0m\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_tabular_imputer'\u001b[0m\u001b[1m]\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ffill'\u001b[0m, \u001b[32m'ts_tabular_imputer'\u001b[0m, \u001b[32m'bfill'\u001b[0m\u001b[1m]\u001b[0m\n",
@@ -561,6 +571,7 @@
       "MyClassifierClassifier(\n",
       "    name='my_classifier',\n",
       "    category='prediction.one_off.classification',\n",
+      "    plugin_type='method',\n",
       "    params={'some_parameter': 1, 'other_parameter': 0.5}\n",
       ")\n"
      ]
@@ -718,7 +729,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/usage/tutorial01_plugins.ipynb b/docs/user_guide/usage/tutorial01_plugins.ipynb
index 809f83f0..f69a6ba5 100644
--- a/docs/user_guide/usage/tutorial01_plugins.ipynb
+++ b/docs/user_guide/usage/tutorial01_plugins.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "3c1bc4d6",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/usage/tutorial01_plugins.ipynb)"
@@ -38,7 +38,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [
     {
@@ -66,7 +66,7 @@
       "        'window_size': 1,\n",
       "        'device': None,\n",
       "        'dataloader_sampler': None,\n",
-      "        'dropout': 0.0,\n",
+      "        'dropout': 0,\n",
       "        'nonlin': 'relu',\n",
       "        'random_state': 0,\n",
       "        'clipping_value': 1,\n",
@@ -100,7 +100,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 3,
    "metadata": {},
    "outputs": [
     {
@@ -128,7 +128,7 @@
       "        'window_size': 1,\n",
       "        'device': None,\n",
       "        'dataloader_sampler': None,\n",
-      "        'dropout': 0.0,\n",
+      "        'dropout': 0,\n",
       "        'nonlin': 'relu',\n",
       "        'random_state': 0,\n",
       "        'clipping_value': 1,\n",
@@ -174,7 +174,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 4,
    "metadata": {},
    "outputs": [
     {
@@ -189,6 +189,7 @@
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
        "    <span style=\"font-weight: bold\">}</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'encoding'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_onehot_encoder'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_onehot_encoder'</span><span style=\"font-weight: bold\">]}</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'imputation'</span>: <span style=\"font-weight: bold\">{</span>\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_tabular_imputer'</span><span style=\"font-weight: bold\">]</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ffill'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_tabular_imputer'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'bfill'</span><span style=\"font-weight: bold\">]</span>\n",
@@ -217,6 +218,7 @@
        "        \u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
        "    \u001b[1m}\u001b[0m,\n",
        "    \u001b[32m'preprocessing'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "        \u001b[32m'encoding'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
        "        \u001b[32m'imputation'\u001b[0m: \u001b[1m{\u001b[0m\n",
        "            \u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_tabular_imputer'\u001b[0m\u001b[1m]\u001b[0m,\n",
        "            \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ffill'\u001b[0m, \u001b[32m'ts_tabular_imputer'\u001b[0m, \u001b[32m'bfill'\u001b[0m\u001b[1m]\u001b[0m\n",
@@ -258,14 +260,14 @@
    "source": [
     "Note that plugin categories are hierarchical (nested).\n",
     "\n",
-    "To quickly view the plugin fully qualified name (`fqn`) for all plugins, use `plugin_loader.list_fqns()`.\n",
+    "To quickly view the plugin fully qualified name (`fqn`) for all plugins, use `plugin_loader.list_full_names()`.\n",
     "\n",
     "These are the names to use in `plugin_loader.{get,get_class}` calls."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 5,
    "metadata": {},
    "outputs": [
     {
@@ -281,6 +283,8 @@
        " 'prediction.one_off.regression.cde_regressor',\n",
        " 'prediction.temporal.classification.seq2seq_classifier',\n",
        " 'prediction.temporal.regression.seq2seq_regressor',\n",
+       " 'preprocessing.encoding.static.static_onehot_encoder',\n",
+       " 'preprocessing.encoding.temporal.ts_onehot_encoder',\n",
        " 'preprocessing.imputation.static.static_tabular_imputer',\n",
        " 'preprocessing.imputation.temporal.ffill',\n",
        " 'preprocessing.imputation.temporal.ts_tabular_imputer',\n",
@@ -298,13 +302,132 @@
        " 'treatments.temporal.regression.crn_regressor']"
       ]
      },
-     "execution_count": 10,
+     "execution_count": 5,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "plugin_loader.list_fqns()"
+    "plugin_loader.list_full_names()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### A note on `Plugin` types\n",
+    "\n",
+    "All the `Plugin`s so far have been of the `\"method\"` *plugin type*. This is the default plugin type.\n",
+    "\n",
+    "TemporAI has other plugin types. You can list plugin types as below."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['method']"
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "plugin_loader.list_plugin_types()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "You can list all plugins across all the different types by passing `plugin_type=\"all\"`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">{</span>\n",
+       "    <span style=\"color: #008000; text-decoration-color: #008000\">'method'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'prediction'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'one_off'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'cde_classifier'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ode_classifier'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'nn_classifier'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'laplace_ode_classifier'</span><span style=\"font-weight: bold\">]</span>,\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'laplace_ode_regressor'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'nn_regressor'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ode_regressor'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'cde_regressor'</span><span style=\"font-weight: bold\">]</span>\n",
+       "            <span style=\"font-weight: bold\">}</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
+       "        <span style=\"font-weight: bold\">}</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'encoding'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_onehot_encoder'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_onehot_encoder'</span><span style=\"font-weight: bold\">]}</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'imputation'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_tabular_imputer'</span><span style=\"font-weight: bold\">]</span>,\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ffill'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_tabular_imputer'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'bfill'</span><span style=\"font-weight: bold\">]</span>\n",
+       "            <span style=\"font-weight: bold\">}</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'nop'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'nop_transformer'</span><span style=\"font-weight: bold\">]</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'scaling'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_minmax_scaler'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'static_standard_scaler'</span><span style=\"font-weight: bold\">]</span>,\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_minmax_scaler'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_standard_scaler'</span><span style=\"font-weight: bold\">]</span>\n",
+       "            <span style=\"font-weight: bold\">}</span>\n",
+       "        <span style=\"font-weight: bold\">}</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'time_to_event'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_coxph'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_xgb'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'dynamic_deephit'</span><span style=\"font-weight: bold\">]</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'treatments'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'one_off'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'synctwin_regressor'</span><span style=\"font-weight: bold\">]}</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'crn_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'crn_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
+       "        <span style=\"font-weight: bold\">}</span>\n",
+       "    <span style=\"font-weight: bold\">}</span>\n",
+       "<span style=\"font-weight: bold\">}</span>\n",
+       "</pre>\n"
+      ],
+      "text/plain": [
+       "\u001b[1m{\u001b[0m\n",
+       "    \u001b[32m'method'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "        \u001b[32m'prediction'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "            \u001b[32m'one_off'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "                \u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'cde_classifier'\u001b[0m, \u001b[32m'ode_classifier'\u001b[0m, \u001b[32m'nn_classifier'\u001b[0m, \u001b[32m'laplace_ode_classifier'\u001b[0m\u001b[1m]\u001b[0m,\n",
+       "                \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'laplace_ode_regressor'\u001b[0m, \u001b[32m'nn_regressor'\u001b[0m, \u001b[32m'ode_regressor'\u001b[0m, \u001b[32m'cde_regressor'\u001b[0m\u001b[1m]\u001b[0m\n",
+       "            \u001b[1m}\u001b[0m,\n",
+       "            \u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
+       "        \u001b[1m}\u001b[0m,\n",
+       "        \u001b[32m'preprocessing'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "            \u001b[32m'encoding'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
+       "            \u001b[32m'imputation'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "                \u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_tabular_imputer'\u001b[0m\u001b[1m]\u001b[0m,\n",
+       "                \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ffill'\u001b[0m, \u001b[32m'ts_tabular_imputer'\u001b[0m, \u001b[32m'bfill'\u001b[0m\u001b[1m]\u001b[0m\n",
+       "            \u001b[1m}\u001b[0m,\n",
+       "            \u001b[32m'nop'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'nop_transformer'\u001b[0m\u001b[1m]\u001b[0m,\n",
+       "            \u001b[32m'scaling'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "                \u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_minmax_scaler'\u001b[0m, \u001b[32m'static_standard_scaler'\u001b[0m\u001b[1m]\u001b[0m,\n",
+       "                \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_minmax_scaler'\u001b[0m, \u001b[32m'ts_standard_scaler'\u001b[0m\u001b[1m]\u001b[0m\n",
+       "            \u001b[1m}\u001b[0m\n",
+       "        \u001b[1m}\u001b[0m,\n",
+       "        \u001b[32m'time_to_event'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_coxph'\u001b[0m, \u001b[32m'ts_xgb'\u001b[0m, \u001b[32m'dynamic_deephit'\u001b[0m\u001b[1m]\u001b[0m,\n",
+       "        \u001b[32m'treatments'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "            \u001b[32m'one_off'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'synctwin_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
+       "            \u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'crn_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'crn_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
+       "        \u001b[1m}\u001b[0m\n",
+       "    \u001b[1m}\u001b[0m\n",
+       "\u001b[1m}\u001b[0m\n"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "from rich.pretty import pprint\n",
+    "\n",
+    "plugins_across_all_types = plugin_loader.list(plugin_type=\"all\")\n",
+    "\n",
+    "pprint(plugins_across_all_types, indent_guides=False)"
    ]
   }
  ],
@@ -324,7 +447,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/usage/tutorial02_imputation.ipynb b/docs/user_guide/usage/tutorial02_imputation.ipynb
index 16b40f3e..2201625a 100644
--- a/docs/user_guide/usage/tutorial02_imputation.ipynb
+++ b/docs/user_guide/usage/tutorial02_imputation.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "6b466f2d",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/usage/tutorial02_imputation.ipynb)"
@@ -30,7 +30,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 5,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [
     {
@@ -40,7 +40,7 @@
        " 'temporal': ['ffill', 'ts_tabular_imputer', 'bfill']}"
       ]
      },
-     "execution_count": 5,
+     "execution_count": 2,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -61,9 +61,16 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 3,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 | Iteration imputation: select_model_by_column: True, select_model_by_iteration: True\n"
+     ]
+    },
     {
      "name": "stdout",
      "output_type": "stream",
@@ -76,6 +83,7 @@
       "StaticTabularImputer(\n",
       "    name='static_tabular_imputer',\n",
       "    category='preprocessing.imputation.static',\n",
+      "    plugin_type='method',\n",
       "    params={\n",
       "        'imputer': 'ice',\n",
       "        'random_state': 0,\n",
@@ -98,7 +106,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 4,
    "metadata": {},
    "outputs": [
     {
@@ -244,7 +252,7 @@
        "[100 rows x 4 columns]"
       ]
      },
-     "execution_count": 7,
+     "execution_count": 4,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -259,9 +267,56 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 5,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > HyperImpute using inner optimization\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 0\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.22005514968324613 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 1\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21670750510884584 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 2\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.2166465658117811 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 3\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.2166456843686172 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 4\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 5\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 6\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 7\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 8\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 9\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 10\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>>> Early stopping on objective diff iteration\n"
+     ]
+    },
     {
      "name": "stdout",
      "output_type": "stream",
@@ -405,7 +460,7 @@
        "[100 rows x 4 columns]"
       ]
      },
-     "execution_count": 8,
+     "execution_count": 5,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -430,7 +485,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 6,
    "metadata": {},
    "outputs": [
     {
@@ -445,6 +500,7 @@
       "BFillImputer(\n",
       "    name='bfill',\n",
       "    category='preprocessing.imputation.temporal',\n",
+      "    plugin_type='method',\n",
       "    params={}\n",
       ")\n"
      ]
@@ -463,7 +519,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 7,
    "metadata": {},
    "outputs": [
     {
@@ -627,7 +683,7 @@
        "[1000 rows x 5 columns]"
       ]
      },
-     "execution_count": 10,
+     "execution_count": 7,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -642,7 +698,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 8,
    "metadata": {},
    "outputs": [
     {
@@ -806,7 +862,7 @@
        "[1000 rows x 5 columns]"
       ]
      },
-     "execution_count": 11,
+     "execution_count": 8,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -838,7 +894,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/usage/tutorial03_scaling.ipynb b/docs/user_guide/usage/tutorial03_scaling.ipynb
index ac2ef564..09ddb7c8 100644
--- a/docs/user_guide/usage/tutorial03_scaling.ipynb
+++ b/docs/user_guide/usage/tutorial03_scaling.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "e73f6f82",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/usage/tutorial03_scaling.ipynb)"
@@ -76,7 +76,8 @@
       "StaticMinMaxScaler(\n",
       "    name='static_minmax_scaler',\n",
       "    category='preprocessing.scaling.static',\n",
-      "    params={}\n",
+      "    plugin_type='method',\n",
+      "    params={'feature_range': [0, 1], 'clip': False}\n",
       ")\n"
      ]
     }
@@ -567,7 +568,8 @@
       "TimeSeriesStandardScaler(\n",
       "    name='ts_standard_scaler',\n",
       "    category='preprocessing.scaling.temporal',\n",
-      "    params={}\n",
+      "    plugin_type='method',\n",
+      "    params={'with_mean': True, 'with_std': True}\n",
       ")\n"
      ]
     }
@@ -1098,7 +1100,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/usage/tutorial04_prediction.ipynb b/docs/user_guide/usage/tutorial04_prediction.ipynb
index 8d8af98e..8fb49fd1 100644
--- a/docs/user_guide/usage/tutorial04_prediction.ipynb
+++ b/docs/user_guide/usage/tutorial04_prediction.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "31fade59",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/usage/tutorial04_prediction.ipynb)"
@@ -95,6 +95,7 @@
       "NeuralNetClassifier(\n",
       "    name='nn_classifier',\n",
       "    category='prediction.one_off.classification',\n",
+      "    plugin_type='method',\n",
       "    params={\n",
       "        'n_static_units_hidden': 100,\n",
       "        'n_static_layers_hidden': 2,\n",
@@ -109,7 +110,7 @@
       "        'window_size': 1,\n",
       "        'device': None,\n",
       "        'dataloader_sampler': None,\n",
-      "        'dropout': 0.0,\n",
+      "        'dropout': 0,\n",
       "        'nonlin': 'relu',\n",
       "        'random_state': 0,\n",
       "        'clipping_value': 1,\n",
@@ -248,12 +249,24 @@
    "execution_count": 5,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:20:14 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.68824702501297, validation loss: 0.6883962154388428\n",
+      "2023-10-07 22:20:14 | INFO     | tempor.models.ts_model:_train:379 | Epoch:10| train loss: 0.6999298334121704, validation loss: 0.6879696846008301\n",
+      "2023-10-07 22:20:15 | INFO     | tempor.models.ts_model:_train:379 | Epoch:20| train loss: 0.6818332672119141, validation loss: 0.6867876648902893\n",
+      "2023-10-07 22:20:15 | INFO     | tempor.models.ts_model:_train:379 | Epoch:30| train loss: 0.6943979263305664, validation loss: 0.685184121131897\n",
+      "2023-10-07 22:20:15 | INFO     | tempor.models.ts_model:_train:379 | Epoch:40| train loss: 0.6284184455871582, validation loss: 0.6934055089950562\n"
+     ]
+    },
     {
      "data": {
       "text/plain": [
        "NeuralNetClassifier(\n",
        "    name='nn_classifier',\n",
        "    category='prediction.one_off.classification',\n",
+       "    plugin_type='method',\n",
        "    params={\n",
        "        'n_static_units_hidden': 100,\n",
        "        'n_static_layers_hidden': 2,\n",
@@ -268,7 +281,7 @@
        "        'window_size': 1,\n",
        "        'device': None,\n",
        "        'dataloader_sampler': None,\n",
-       "        'dropout': 0.0,\n",
+       "        'dropout': 0,\n",
        "        'nonlin': 'relu',\n",
        "        'random_state': 0,\n",
        "        'clipping_value': 1,\n",
@@ -430,6 +443,7 @@
       "Seq2seqRegressor(\n",
       "    name='seq2seq_regressor',\n",
       "    category='prediction.temporal.regression',\n",
+      "    plugin_type='method',\n",
       "    params={\n",
       "        'encoder_rnn_type': 'LSTM',\n",
       "        'encoder_hidden_size': 100,\n",
@@ -792,7 +806,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/usage/tutorial05_time_to_event.ipynb b/docs/user_guide/usage/tutorial05_time_to_event.ipynb
index fec2cd87..d4fc92ed 100644
--- a/docs/user_guide/usage/tutorial05_time_to_event.ipynb
+++ b/docs/user_guide/usage/tutorial05_time_to_event.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "6b60407a",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/usage/tutorial05_time_to_event.ipynb)"
@@ -78,6 +78,7 @@
       "DynamicDeepHitTimeToEventAnalysis(\n",
       "    name='dynamic_deephit',\n",
       "    category='time_to_event',\n",
+      "    plugin_type='method',\n",
       "    params={\n",
       "        'n_iter': 50,\n",
       "        'batch_size': 100,\n",
@@ -91,6 +92,7 @@
       "        'sigma': 0.21,\n",
       "        'dropout': 0.06,\n",
       "        'device': 'cpu',\n",
+      "        'val_size': 0.1,\n",
       "        'patience': 20,\n",
       "        'output_mode': 'MLP',\n",
       "        'random_state': 0\n",
@@ -233,6 +235,7 @@
        "DynamicDeepHitTimeToEventAnalysis(\n",
        "    name='dynamic_deephit',\n",
        "    category='time_to_event',\n",
+       "    plugin_type='method',\n",
        "    params={\n",
        "        'n_iter': 50,\n",
        "        'batch_size': 100,\n",
@@ -246,6 +249,7 @@
        "        'sigma': 0.21,\n",
        "        'dropout': 0.06,\n",
        "        'device': 'cpu',\n",
+       "        'val_size': 0.1,\n",
        "        'patience': 20,\n",
        "        'output_mode': 'MLP',\n",
        "        'random_state': 0\n",
@@ -265,7 +269,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 6,
    "metadata": {},
    "outputs": [
     {
@@ -338,7 +342,7 @@
        "    <tr>\n",
        "      <th rowspan=\"3\" valign=\"top\">312</th>\n",
        "      <th>0.25</th>\n",
-       "      <td>0.248833</td>\n",
+       "      <td>0.248834</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>0.50</th>\n",
@@ -365,14 +369,14 @@
        "...                         ...\n",
        "311        0.50        0.039302\n",
        "           0.75        0.048346\n",
-       "312        0.25        0.248833\n",
+       "312        0.25        0.248834\n",
        "           0.50        0.390042\n",
        "           0.75        0.444533\n",
        "\n",
        "[936 rows x 1 columns]"
       ]
      },
-     "execution_count": 12,
+     "execution_count": 6,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -412,7 +416,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/usage/tutorial06_treatments.ipynb b/docs/user_guide/usage/tutorial06_treatments.ipynb
index 062b1422..17e70967 100644
--- a/docs/user_guide/usage/tutorial06_treatments.ipynb
+++ b/docs/user_guide/usage/tutorial06_treatments.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "f0170ff7",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/usage/tutorial06_treatments.ipynb)"
@@ -96,6 +96,7 @@
       "CRNTreatmentsRegressor(\n",
       "    name='crn_regressor',\n",
       "    category='treatments.temporal.regression',\n",
+      "    plugin_type='method',\n",
       "    params={\n",
       "        'encoder_rnn_type': 'LSTM',\n",
       "        'encoder_hidden_size': 100,\n",
@@ -403,47 +404,47 @@
       "Preparing data for decoder training...\n",
       "Preparing data for decoder training DONE.\n",
       "=== Training stage: 1. Train encoder ===\n",
-      "Epoch: 0, Prediction Loss: 76.050, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 76.050\n",
-      "Epoch: 1, Prediction Loss: 37.508, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 37.508\n",
-      "Epoch: 2, Prediction Loss: 21.953, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 21.953\n",
-      "Epoch: 3, Prediction Loss: 18.895, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 18.895\n",
-      "Epoch: 4, Prediction Loss: 19.568, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 19.568\n",
-      "Epoch: 5, Prediction Loss: 16.534, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 16.534\n",
-      "Epoch: 6, Prediction Loss: 12.039, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 12.039\n",
-      "Epoch: 7, Prediction Loss: 10.009, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 10.009\n",
-      "Epoch: 8, Prediction Loss: 8.666, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 8.666\n",
-      "Epoch: 9, Prediction Loss: 6.788, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 6.788\n",
-      "Epoch: 10, Prediction Loss: 5.674, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 5.674\n",
-      "Epoch: 11, Prediction Loss: 5.016, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 5.016\n",
-      "Epoch: 12, Prediction Loss: 4.605, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.605\n",
-      "Epoch: 13, Prediction Loss: 4.349, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.349\n",
-      "Epoch: 14, Prediction Loss: 4.096, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.096\n",
-      "Epoch: 15, Prediction Loss: 4.008, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.008\n",
-      "Epoch: 16, Prediction Loss: 4.159, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.159\n",
-      "Epoch: 17, Prediction Loss: 3.980, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.980\n",
-      "Epoch: 18, Prediction Loss: 3.904, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.904\n",
-      "Epoch: 19, Prediction Loss: 3.995, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.995\n",
+      "Epoch: 0, Prediction Loss: 73.902, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 73.902\n",
+      "Epoch: 1, Prediction Loss: 33.630, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 33.630\n",
+      "Epoch: 2, Prediction Loss: 19.597, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 19.597\n",
+      "Epoch: 3, Prediction Loss: 19.476, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 19.476\n",
+      "Epoch: 4, Prediction Loss: 20.131, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 20.131\n",
+      "Epoch: 5, Prediction Loss: 15.780, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 15.780\n",
+      "Epoch: 6, Prediction Loss: 12.235, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 12.235\n",
+      "Epoch: 7, Prediction Loss: 10.043, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 10.043\n",
+      "Epoch: 8, Prediction Loss: 8.313, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 8.313\n",
+      "Epoch: 9, Prediction Loss: 6.753, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 6.753\n",
+      "Epoch: 10, Prediction Loss: 5.567, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 5.567\n",
+      "Epoch: 11, Prediction Loss: 4.777, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.777\n",
+      "Epoch: 12, Prediction Loss: 4.359, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.359\n",
+      "Epoch: 13, Prediction Loss: 4.267, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.267\n",
+      "Epoch: 14, Prediction Loss: 4.099, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.099\n",
+      "Epoch: 15, Prediction Loss: 3.897, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.897\n",
+      "Epoch: 16, Prediction Loss: 3.876, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.876\n",
+      "Epoch: 17, Prediction Loss: 3.865, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.865\n",
+      "Epoch: 18, Prediction Loss: 3.774, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.774\n",
+      "Epoch: 19, Prediction Loss: 3.796, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.796\n",
       "=== Training stage: 2. Train decoder ===\n",
-      "Epoch: 0, Prediction Loss: 34.805, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 34.805\n",
-      "Epoch: 1, Prediction Loss: 13.675, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 13.675\n",
-      "Epoch: 2, Prediction Loss: 7.021, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 7.021\n",
-      "Epoch: 3, Prediction Loss: 4.086, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.086\n",
-      "Epoch: 4, Prediction Loss: 3.847, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.847\n",
-      "Epoch: 5, Prediction Loss: 3.795, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.795\n",
-      "Epoch: 6, Prediction Loss: 3.762, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.762\n",
-      "Epoch: 7, Prediction Loss: 3.800, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.800\n",
-      "Epoch: 8, Prediction Loss: 3.792, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.792\n",
-      "Epoch: 9, Prediction Loss: 3.703, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.703\n",
-      "Epoch: 10, Prediction Loss: 3.683, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.683\n",
-      "Epoch: 11, Prediction Loss: 3.734, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.734\n",
-      "Epoch: 12, Prediction Loss: 3.690, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.690\n",
-      "Epoch: 13, Prediction Loss: 3.728, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.728\n",
-      "Epoch: 14, Prediction Loss: 3.694, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.694\n",
-      "Epoch: 15, Prediction Loss: 3.647, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.647\n",
-      "Epoch: 16, Prediction Loss: 3.639, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.639\n",
-      "Epoch: 17, Prediction Loss: 3.612, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.612\n",
-      "Epoch: 18, Prediction Loss: 3.633, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.633\n",
-      "Epoch: 19, Prediction Loss: 3.604, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.604\n"
+      "Epoch: 0, Prediction Loss: 38.872, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 38.872\n",
+      "Epoch: 1, Prediction Loss: 14.391, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 14.391\n",
+      "Epoch: 2, Prediction Loss: 7.017, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 7.017\n",
+      "Epoch: 3, Prediction Loss: 3.957, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.957\n",
+      "Epoch: 4, Prediction Loss: 3.851, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.851\n",
+      "Epoch: 5, Prediction Loss: 3.786, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.786\n",
+      "Epoch: 6, Prediction Loss: 3.766, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.766\n",
+      "Epoch: 7, Prediction Loss: 3.748, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.748\n",
+      "Epoch: 8, Prediction Loss: 3.720, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.720\n",
+      "Epoch: 9, Prediction Loss: 3.717, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.717\n",
+      "Epoch: 10, Prediction Loss: 3.714, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.714\n",
+      "Epoch: 11, Prediction Loss: 3.688, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.688\n",
+      "Epoch: 12, Prediction Loss: 3.660, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.660\n",
+      "Epoch: 13, Prediction Loss: 3.696, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.696\n",
+      "Epoch: 14, Prediction Loss: 3.653, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.653\n",
+      "Epoch: 15, Prediction Loss: 3.649, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.649\n",
+      "Epoch: 16, Prediction Loss: 3.638, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.638\n",
+      "Epoch: 17, Prediction Loss: 3.667, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.667\n",
+      "Epoch: 18, Prediction Loss: 3.621, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.621\n",
+      "Epoch: 19, Prediction Loss: 3.626, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.626\n"
      ]
     }
    ],
@@ -473,23 +474,23 @@
       "TimeSeries() with data:\n",
       "                 0         1\n",
       "time_idx                    \n",
-      "5         6.339921  5.118720\n",
-      "6         6.379971  5.159422\n",
-      "7         6.380514  5.159956\n",
-      "8         6.380521  5.159964\n",
-      "9         6.380521  5.159964\n",
-      "10        6.380521  5.159964\n",
+      "5         6.281449  4.965402\n",
+      "6         6.435705  5.133381\n",
+      "7         6.441704  5.139909\n",
+      "8         6.441934  5.140160\n",
+      "9         6.441943  5.140169\n",
+      "10        6.441943  5.140169\n",
       "\n",
       "Treatment scenario 1, [0 0 0 0 0 0]\n",
       "TimeSeries() with data:\n",
       "                 0         1\n",
       "time_idx                    \n",
-      "5         6.694273  5.142348\n",
-      "6         6.732183  5.177425\n",
-      "7         6.732780  5.178019\n",
-      "8         6.732789  5.178029\n",
-      "9         6.732790  5.178029\n",
-      "10        6.732790  5.178029\n",
+      "5         6.634320  4.977645\n",
+      "6         6.721170  5.071841\n",
+      "7         6.726741  5.078034\n",
+      "8         6.727103  5.078438\n",
+      "9         6.727127  5.078464\n",
+      "10        6.727128  5.078465\n",
       "\n"
      ]
     }
@@ -534,7 +535,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/usage/tutorial07_pipeline.ipynb b/docs/user_guide/usage/tutorial07_pipeline.ipynb
index 53a7d74b..b0c7abc5 100644
--- a/docs/user_guide/usage/tutorial07_pipeline.ipynb
+++ b/docs/user_guide/usage/tutorial07_pipeline.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "b88a6d09",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/usage/tutorial07_pipeline.ipynb)"
@@ -112,6 +112,14 @@
      "metadata": {},
      "output_type": "display_data"
     },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:24:00 | INFO     | hyperimpute.logger:log_and_print:65 | Iteration imputation: select_model_by_column: True, select_model_by_iteration: True\n",
+      "2023-10-07 22:24:00 | INFO     | hyperimpute.logger:log_and_print:65 | Iteration imputation: select_model_by_column: True, select_model_by_iteration: True\n"
+     ]
+    },
     {
      "name": "stdout",
      "output_type": "stream",
@@ -144,7 +152,7 @@
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'window_size'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'device'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'dataloader_sampler'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
-       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'random_state'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'clipping_value'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
@@ -178,7 +186,7 @@
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'window_size'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'device'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'dataloader_sampler'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
-       "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'random_state'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'clipping_value'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
@@ -240,6 +248,58 @@
    "execution_count": 4,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > HyperImpute using inner optimization\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 0\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 1\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 2\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 3\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 4\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 5\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 6\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |      >>>> Early stopping on objective diff iteration\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > HyperImpute using inner optimization\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 0\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 1\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 2\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 3\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 4\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 5\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 6\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |      >>>> Early stopping on objective diff iteration\n",
+      "2023-10-07 22:24:03 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.688586950302124, validation loss: 0.6886438131332397\n",
+      "2023-10-07 22:24:03 | INFO     | tempor.models.ts_model:_train:379 | Epoch:10| train loss: 0.6998531222343445, validation loss: 0.6888602375984192\n",
+      "2023-10-07 22:24:03 | INFO     | tempor.models.ts_model:_train:379 | Epoch:20| train loss: 0.6862186193466187, validation loss: 0.689547061920166\n",
+      "2023-10-07 22:24:03 | INFO     | tempor.models.ts_model:_train:379 | Epoch:30| train loss: 0.6913824677467346, validation loss: 0.6873278617858887\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:40| train loss: 0.6604955792427063, validation loss: 0.689150333404541\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:50| train loss: 0.6746629476547241, validation loss: 0.6878216862678528\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:60| train loss: 0.7084729075431824, validation loss: 0.6860194802284241\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:70| train loss: 0.6851019263267517, validation loss: 0.683639645576477\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:80| train loss: 0.6695638298988342, validation loss: 0.6823517084121704\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:90| train loss: 0.6456660032272339, validation loss: 0.6871115565299988\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > HyperImpute using inner optimization\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 0\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 1\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 2\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 3\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 4\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 5\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 6\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |      >>>> Early stopping on objective diff iteration\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > HyperImpute using inner optimization\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 0\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 1\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 2\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 3\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 4\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 5\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 6\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |      >>>> Early stopping on objective diff iteration\n"
+     ]
+    },
     {
      "data": {
       "text/html": [
@@ -371,7 +431,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/usage/tutorial08_benchmarks.ipynb b/docs/user_guide/usage/tutorial08_benchmarks.ipynb
index 9fb686d2..e7a78245 100644
--- a/docs/user_guide/usage/tutorial08_benchmarks.ipynb
+++ b/docs/user_guide/usage/tutorial08_benchmarks.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "c4a51e5b",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/usage/tutorial08_benchmarks.ipynb)"
@@ -43,14 +43,14 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 19:18:40 | INFO     | tempor.benchmarks.benchmark:benchmark_models:91 | Test case: model_1\n",
-      "2023-05-14 19:18:42 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.68637615442276, validation loss: 0.6680578589439392\n",
-      "2023-05-14 19:18:43 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6887814402580261, validation loss: 0.6939960718154907\n",
-      "2023-05-14 19:18:43 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6906945109367371, validation loss: 0.6966598033905029\n",
-      "2023-05-14 19:18:43 | INFO     | tempor.benchmarks.benchmark:benchmark_models:91 | Test case: model_2\n",
-      "2023-05-14 19:18:48 | INFO     | tempor.models.ts_ode:_train:608 | Epoch:99| train loss: 0.6465951204299927, validation loss: 0.5632617473602295\n",
-      "2023-05-14 19:18:52 | INFO     | tempor.models.ts_ode:_train:608 | Epoch:99| train loss: 0.913261890411377, validation loss: 0.8132617473602295\n",
-      "2023-05-14 19:18:57 | INFO     | tempor.models.ts_ode:_train:608 | Epoch:99| train loss: 0.7132617831230164, validation loss: 0.8132617473602295\n"
+      "2023-10-07 22:24:21 | INFO     | tempor.benchmarks.benchmark:benchmark_models:100 | Test case: model_1\n",
+      "2023-10-07 22:24:23 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.68637615442276, validation loss: 0.6680578589439392\n",
+      "2023-10-07 22:24:24 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6887814402580261, validation loss: 0.6939960718154907\n",
+      "2023-10-07 22:24:25 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6906945109367371, validation loss: 0.6966598033905029\n",
+      "2023-10-07 22:24:25 | INFO     | tempor.benchmarks.benchmark:benchmark_models:100 | Test case: model_2\n",
+      "2023-10-07 22:24:31 | INFO     | tempor.models.ts_ode:_train:607 | Epoch:99| train loss: 0.6465951204299927, validation loss: 0.5632617473602295\n",
+      "2023-10-07 22:24:37 | INFO     | tempor.models.ts_ode:_train:607 | Epoch:99| train loss: 0.913261890411377, validation loss: 0.8132617473602295\n",
+      "2023-10-07 22:24:42 | INFO     | tempor.models.ts_ode:_train:607 | Epoch:99| train loss: 0.7132617831230164, validation loss: 0.8132617473602295\n"
      ]
     },
     {
@@ -518,7 +518,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/docs/user_guide/usage/tutorial09_automl.ipynb b/docs/user_guide/usage/tutorial09_automl.ipynb
index a5f34618..dd4e3473 100644
--- a/docs/user_guide/usage/tutorial09_automl.ipynb
+++ b/docs/user_guide/usage/tutorial09_automl.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "294f2d70",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/usage/tutorial09_automl.ipynb)"
@@ -61,10 +61,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_set_up_tuners:354 | Setting up estimators and tuners for study my_automl_study.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator cde_classifier.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator ode_classifier.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator nn_classifier.\n"
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_set_up_tuners:365 | Setting up estimators and tuners for study my_automl_study.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator cde_classifier.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator ode_classifier.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator nn_classifier.\n"
      ]
     }
    ],
@@ -120,10 +120,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_set_up_tuners:354 | Setting up estimators and tuners for study my_automl_study.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator cde_classifier.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator ode_classifier.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator nn_classifier.\n"
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_set_up_tuners:365 | Setting up estimators and tuners for study my_automl_study.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator cde_classifier.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator ode_classifier.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator nn_classifier.\n"
      ]
     }
    ],
@@ -178,79 +178,79 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator 'cde_classifier' 1/3.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator 'cde_classifier' 1/3.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from CDEClassifier:\n",
       "{'n_iter': 2, 'n_temporal_units_hidden': 13, 'lr': 0.01}\n",
-      "2023-05-14 21:48:49 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:26 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from CDEClassifier:\n",
       "{'n_iter': 2, 'n_temporal_units_hidden': 11, 'lr': 0.0001}\n",
-      "2023-05-14 21:48:53 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:30 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from CDEClassifier:\n",
       "{'n_iter': 2, 'n_temporal_units_hidden': 20, 'lr': 0.001}\n",
-      "2023-05-14 21:48:56 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator 'ode_classifier' 2/3.\n",
-      "2023-05-14 21:48:56 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:48:56 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:34 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator 'ode_classifier' 2/3.\n",
+      "2023-10-07 22:25:34 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:25:34 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from ODEClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 13, 'lr': 0.01}\n",
-      "2023-05-14 21:48:59 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:38 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from ODEClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}\n",
-      "2023-05-14 21:49:02 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:41 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from ODEClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 20, 'lr': 0.001}\n",
-      "2023-05-14 21:49:05 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator 'nn_classifier' 3/3.\n",
-      "2023-05-14 21:49:05 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:49:05 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:45 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator 'nn_classifier' 3/3.\n",
+      "2023-10-07 22:25:45 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:25:45 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from NeuralNetClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 13, 'lr': 0.01}\n",
-      "2023-05-14 21:49:06 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.6882655620574951\n",
-      "2023-05-14 21:49:07 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6865323185920715\n",
-      "2023-05-14 21:49:07 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6861071586608887\n",
-      "2023-05-14 21:49:08 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6825112104415894\n",
-      "2023-05-14 21:49:08 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6819757223129272\n",
-      "2023-05-14 21:49:08 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:45 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.6882655620574951\n",
+      "2023-10-07 22:25:46 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6865323185920715\n",
+      "2023-10-07 22:25:47 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6861070990562439\n",
+      "2023-10-07 22:25:47 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6825112104415894\n",
+      "2023-10-07 22:25:48 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6819757223129272\n",
+      "2023-10-07 22:25:48 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from NeuralNetClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}\n",
-      "2023-05-14 21:49:09 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.691270649433136\n",
-      "2023-05-14 21:49:09 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6910805106163025\n",
-      "2023-05-14 21:49:10 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6900344491004944\n",
-      "2023-05-14 21:49:10 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6906693577766418\n",
-      "2023-05-14 21:49:11 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6910874843597412\n",
-      "2023-05-14 21:49:11 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:49 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.691270649433136\n",
+      "2023-10-07 22:25:49 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6910805106163025\n",
+      "2023-10-07 22:25:50 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6900344491004944\n",
+      "2023-10-07 22:25:50 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6906693577766418\n",
+      "2023-10-07 22:25:51 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6910874843597412\n",
+      "2023-10-07 22:25:51 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from NeuralNetClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 20, 'lr': 0.001}\n",
-      "2023-05-14 21:49:11 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.6896670460700989\n",
-      "2023-05-14 21:49:12 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6886401772499084\n",
-      "2023-05-14 21:49:12 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6884845495223999\n",
-      "2023-05-14 21:49:13 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6887120604515076\n",
-      "2023-05-14 21:49:13 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6893669962882996\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:25:52 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.6896671056747437\n",
+      "2023-10-07 22:25:53 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6886401772499084\n",
+      "2023-10-07 22:25:53 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6884845495223999\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6887120604515076\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6893669962882996\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for cde_classifier scores:\n",
       "[0.47310606060606064, 0.48396464646464643, 0.4840277777777778].\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for ode_classifier scores:\n",
       "[0.47992424242424236, 0.48409090909090907, 0.484090909090909].\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for nn_classifier scores:\n",
       "[0.37064393939393936, 0.5370580808080809, 0.4579545454545454].\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:448 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:460 | \n",
       "All estimator definitions searched:\n",
       "['cde_classifier', 'ode_classifier', 'nn_classifier']\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:449 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:461 | \n",
       "Best scores for each estimator searched:\n",
       "[0.4840277777777778, 0.48409090909090907, 0.5370580808080809]\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:450 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:462 | \n",
       "Best hyperparameters for each estimator searched:\n",
       "[{'n_iter': 2, 'n_temporal_units_hidden': 20, 'lr': 0.001}, {'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}, {'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}]\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:571 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:587 | \n",
       "Selected score 0.5370580808080809 for nn_classifier with hyperparameters:\n",
       "{'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:571 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:587 | \n",
       "Selected score 0.48409090909090907 for ode_classifier with hyperparameters:\n",
       "{'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:571 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:587 | \n",
       "Selected score 0.4840277777777778 for cde_classifier with hyperparameters:\n",
       "{'n_iter': 2, 'n_temporal_units_hidden': 20, 'lr': 0.001}\n"
      ]
@@ -273,6 +273,7 @@
        "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">NeuralNetClassifier</span><span style=\"font-weight: bold\">(</span>\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'nn_classifier'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">category</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'prediction.one_off.classification'</span>,\n",
+       "    <span style=\"color: #808000; text-decoration-color: #808000\">plugin_type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'method'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">params</span>=<span style=\"font-weight: bold\">{</span>\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_static_units_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">100</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_static_layers_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2</span>,\n",
@@ -287,7 +288,7 @@
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'window_size'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'device'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'dataloader_sampler'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
-       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'random_state'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'clipping_value'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
@@ -301,6 +302,7 @@
        "\u001b[1;35mNeuralNetClassifier\u001b[0m\u001b[1m(\u001b[0m\n",
        "    \u001b[33mname\u001b[0m=\u001b[32m'nn_classifier'\u001b[0m,\n",
        "    \u001b[33mcategory\u001b[0m=\u001b[32m'prediction.one_off.classification'\u001b[0m,\n",
+       "    \u001b[33mplugin_type\u001b[0m=\u001b[32m'method'\u001b[0m,\n",
        "    \u001b[33mparams\u001b[0m=\u001b[1m{\u001b[0m\n",
        "        \u001b[32m'n_static_units_hidden'\u001b[0m: \u001b[1;36m100\u001b[0m,\n",
        "        \u001b[32m'n_static_layers_hidden'\u001b[0m: \u001b[1;36m2\u001b[0m,\n",
@@ -315,7 +317,7 @@
        "        \u001b[32m'window_size'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "        \u001b[32m'device'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
        "        \u001b[32m'dataloader_sampler'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
-       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "        \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
        "        \u001b[32m'random_state'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "        \u001b[32m'clipping_value'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
@@ -334,11 +336,12 @@
        "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ODEClassifier</span><span style=\"font-weight: bold\">(</span>\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'ode_classifier'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">category</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'prediction.one_off.classification'</span>,\n",
+       "    <span style=\"color: #808000; text-decoration-color: #808000\">plugin_type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'method'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">params</span>=<span style=\"font-weight: bold\">{</span>\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_units_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">11</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_layers_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
-       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'atol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'rtol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'interpolation'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'cubic'</span>,\n",
@@ -361,11 +364,12 @@
        "\u001b[1;35mODEClassifier\u001b[0m\u001b[1m(\u001b[0m\n",
        "    \u001b[33mname\u001b[0m=\u001b[32m'ode_classifier'\u001b[0m,\n",
        "    \u001b[33mcategory\u001b[0m=\u001b[32m'prediction.one_off.classification'\u001b[0m,\n",
+       "    \u001b[33mplugin_type\u001b[0m=\u001b[32m'method'\u001b[0m,\n",
        "    \u001b[33mparams\u001b[0m=\u001b[1m{\u001b[0m\n",
        "        \u001b[32m'n_units_hidden'\u001b[0m: \u001b[1;36m11\u001b[0m,\n",
        "        \u001b[32m'n_layers_hidden'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "        \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
-       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "        \u001b[32m'atol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "        \u001b[32m'rtol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "        \u001b[32m'interpolation'\u001b[0m: \u001b[32m'cubic'\u001b[0m,\n",
@@ -393,11 +397,12 @@
        "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">CDEClassifier</span><span style=\"font-weight: bold\">(</span>\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'cde_classifier'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">category</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'prediction.one_off.classification'</span>,\n",
+       "    <span style=\"color: #808000; text-decoration-color: #808000\">plugin_type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'method'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">params</span>=<span style=\"font-weight: bold\">{</span>\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_units_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">100</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_layers_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
-       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'atol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'rtol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'interpolation'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'cubic'</span>,\n",
@@ -420,11 +425,12 @@
        "\u001b[1;35mCDEClassifier\u001b[0m\u001b[1m(\u001b[0m\n",
        "    \u001b[33mname\u001b[0m=\u001b[32m'cde_classifier'\u001b[0m,\n",
        "    \u001b[33mcategory\u001b[0m=\u001b[32m'prediction.one_off.classification'\u001b[0m,\n",
+       "    \u001b[33mplugin_type\u001b[0m=\u001b[32m'method'\u001b[0m,\n",
        "    \u001b[33mparams\u001b[0m=\u001b[1m{\u001b[0m\n",
        "        \u001b[32m'n_units_hidden'\u001b[0m: \u001b[1;36m100\u001b[0m,\n",
        "        \u001b[32m'n_layers_hidden'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "        \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
-       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "        \u001b[32m'atol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "        \u001b[32m'rtol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "        \u001b[32m'interpolation'\u001b[0m: \u001b[32m'cubic'\u001b[0m,\n",
@@ -487,10 +493,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_set_up_tuners:354 | Setting up estimators and tuners for study my_automl_study.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with cde_classifier>.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with ode_classifier>.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with nn_classifier>.\n"
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_set_up_tuners:365 | Setting up estimators and tuners for study my_automl_study.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with cde_classifier>.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with ode_classifier>.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with nn_classifier>.\n"
      ]
     }
    ],
@@ -574,10 +580,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_set_up_tuners:354 | Setting up estimators and tuners for study my_automl_study.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with cde_classifier>.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with ode_classifier>.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with nn_classifier>.\n"
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_set_up_tuners:365 | Setting up estimators and tuners for study my_automl_study.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with cde_classifier>.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with ode_classifier>.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with nn_classifier>.\n"
      ]
     }
    ],
@@ -639,79 +645,79 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator '<Pipeline with cde_classifier>' 1/3.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator '<Pipeline with cde_classifier>' 1/3.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.cde_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'softimpute'}, 'static_minmax_scaler': {'clip': True}, 'ts_standard_scaler': {}, 'cde_classifier': {'n_iter': 2, 'n_temporal_units_hidden': 17, 'lr': 0.001}}}\n",
-      "2023-05-14 21:49:30 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:26:27 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_minmax_scaler->prediction.one_off.classification.cde_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'mean'}, 'static_minmax_scaler': {'clip': False}, 'ts_minmax_scaler': {'clip': False}, 'cde_classifier': {'n_iter': 2, 'n_temporal_units_hidden': 14, 'lr': 0.001}}}\n",
-      "2023-05-14 21:49:36 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:26:33 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_standard_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.cde_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'most_frequent'}, 'static_standard_scaler': {}, 'ts_standard_scaler': {}, 'cde_classifier': {'n_iter': 2, 'n_temporal_units_hidden': 6, 'lr': 0.0001}}}\n",
-      "2023-05-14 21:49:42 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator '<Pipeline with ode_classifier>' 2/3.\n",
-      "2023-05-14 21:49:42 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:49:42 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:26:40 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator '<Pipeline with ode_classifier>' 2/3.\n",
+      "2023-10-07 22:26:40 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:26:40 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.ode_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'softimpute'}, 'static_minmax_scaler': {'clip': True}, 'ts_standard_scaler': {}, 'ode_classifier': {'n_iter': 2, 'n_units_hidden': 17, 'lr': 0.001}}}\n",
-      "2023-05-14 21:50:00 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:26:59 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_minmax_scaler->prediction.one_off.classification.ode_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'mean'}, 'static_minmax_scaler': {'clip': False}, 'ts_minmax_scaler': {'clip': False}, 'ode_classifier': {'n_iter': 2, 'n_units_hidden': 14, 'lr': 0.001}}}\n",
-      "2023-05-14 21:50:06 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:27:05 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_standard_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.ode_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'most_frequent'}, 'static_standard_scaler': {}, 'ts_standard_scaler': {}, 'ode_classifier': {'n_iter': 2, 'n_units_hidden': 6, 'lr': 0.0001}}}\n",
-      "2023-05-14 21:50:11 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator '<Pipeline with nn_classifier>' 3/3.\n",
-      "2023-05-14 21:50:11 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:50:11 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:27:11 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator '<Pipeline with nn_classifier>' 3/3.\n",
+      "2023-10-07 22:27:11 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:27:11 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.nn_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'softimpute'}, 'static_minmax_scaler': {'clip': True}, 'ts_standard_scaler': {}, 'nn_classifier': {'n_iter': 2, 'n_units_hidden': 17, 'lr': 0.001}}}\n",
-      "2023-05-14 21:50:14 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6918608546257019, validation loss: 0.6910383105278015\n",
-      "2023-05-14 21:50:17 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6909429430961609, validation loss: 0.6872987151145935\n",
-      "2023-05-14 21:50:21 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692150354385376, validation loss: 0.6879752278327942\n",
-      "2023-05-14 21:50:24 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6926363706588745, validation loss: 0.6881052851676941\n",
-      "2023-05-14 21:50:27 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6915659308433533, validation loss: 0.6888220310211182\n",
-      "2023-05-14 21:50:28 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:27:13 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6918608546257019, validation loss: 0.6910383105278015\n",
+      "2023-10-07 22:27:16 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6909429430961609, validation loss: 0.6872987151145935\n",
+      "2023-10-07 22:27:19 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692150354385376, validation loss: 0.6879752278327942\n",
+      "2023-10-07 22:27:22 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6926363706588745, validation loss: 0.6881052851676941\n",
+      "2023-10-07 22:27:25 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6915659308433533, validation loss: 0.6888220310211182\n",
+      "2023-10-07 22:27:26 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_minmax_scaler->prediction.one_off.classification.nn_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'mean'}, 'static_minmax_scaler': {'clip': False}, 'ts_minmax_scaler': {'clip': False}, 'nn_classifier': {'n_iter': 2, 'n_units_hidden': 14, 'lr': 0.001}}}\n",
-      "2023-05-14 21:50:28 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6920319199562073, validation loss: 0.6892786622047424\n",
-      "2023-05-14 21:50:29 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6913070678710938, validation loss: 0.6893746852874756\n",
-      "2023-05-14 21:50:30 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6924894452095032, validation loss: 0.6886722445487976\n",
-      "2023-05-14 21:50:31 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6930248141288757, validation loss: 0.6894596815109253\n",
-      "2023-05-14 21:50:32 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6921922564506531, validation loss: 0.6893032789230347\n",
-      "2023-05-14 21:50:33 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:27:27 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6920319199562073, validation loss: 0.6892786622047424\n",
+      "2023-10-07 22:27:28 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6913070678710938, validation loss: 0.6893746852874756\n",
+      "2023-10-07 22:27:29 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6924894452095032, validation loss: 0.6886722445487976\n",
+      "2023-10-07 22:27:30 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6930248141288757, validation loss: 0.6894596815109253\n",
+      "2023-10-07 22:27:31 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6921922564506531, validation loss: 0.6893032789230347\n",
+      "2023-10-07 22:27:31 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_standard_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.nn_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'most_frequent'}, 'static_standard_scaler': {}, 'ts_standard_scaler': {}, 'nn_classifier': {'n_iter': 2, 'n_units_hidden': 6, 'lr': 0.0001}}}\n",
-      "2023-05-14 21:50:33 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6914154291152954, validation loss: 0.6911771297454834\n",
-      "2023-05-14 21:50:34 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.690178394317627, validation loss: 0.6934390664100647\n",
-      "2023-05-14 21:50:35 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6933540105819702, validation loss: 0.6896734833717346\n",
-      "2023-05-14 21:50:36 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.694333553314209, validation loss: 0.690070390701294\n",
-      "2023-05-14 21:50:37 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6921719312667847, validation loss: 0.6909489631652832\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:27:32 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6914154291152954, validation loss: 0.6911771297454834\n",
+      "2023-10-07 22:27:33 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.690178394317627, validation loss: 0.6934390664100647\n",
+      "2023-10-07 22:27:34 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6933540105819702, validation loss: 0.6896734833717346\n",
+      "2023-10-07 22:27:35 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.694333553314209, validation loss: 0.690070390701294\n",
+      "2023-10-07 22:27:36 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6921719312667847, validation loss: 0.6909489631652832\n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for <Pipeline with cde_classifier> scores:\n",
       "[0.4716540404040404, 0.47575757575757577, 0.4657828282828283].\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for <Pipeline with ode_classifier> scores:\n",
       "[0.47575757575757577, 0.4779040404040404, 0.4779671717171716].\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for <Pipeline with nn_classifier> scores:\n",
       "[0.48478535353535346, 0.4361742424242424, 0.5071338383838383].\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:448 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:460 | \n",
       "All estimator definitions searched:\n",
       "['<Pipeline with cde_classifier>', '<Pipeline with ode_classifier>', '<Pipeline with nn_classifier>']\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:449 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:461 | \n",
       "Best scores for each estimator searched:\n",
       "[0.47575757575757577, 0.4779671717171716, 0.5071338383838383]\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:450 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:462 | \n",
       "Best hyperparameters for each estimator searched:\n",
       "[{'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'mean', '<candidates>(preprocessing.scaling.static)': 'static_minmax_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_minmax_scaler', '[ts_minmax_scaler](clip)': False, '[cde_classifier](n_iter)': 2, '[cde_classifier](n_temporal_units_hidden)': 14, '[cde_classifier](lr)': 0.001}, {'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'most_frequent', '<candidates>(preprocessing.scaling.static)': 'static_standard_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_standard_scaler', '[ts_minmax_scaler](clip)': False, '[ode_classifier](n_iter)': 2, '[ode_classifier](n_units_hidden)': 6, '[ode_classifier](lr)': 0.0001}, {'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'most_frequent', '<candidates>(preprocessing.scaling.static)': 'static_standard_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_standard_scaler', '[ts_minmax_scaler](clip)': False, '[nn_classifier](n_iter)': 2, '[nn_classifier](n_units_hidden)': 6, '[nn_classifier](lr)': 0.0001}]\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:748 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:768 | \n",
       "Selected score 0.5071338383838383 for <Pipeline with nn_classifier> with hyperparameters:\n",
       "{'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'most_frequent', '<candidates>(preprocessing.scaling.static)': 'static_standard_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_standard_scaler', '[ts_minmax_scaler](clip)': False, '[nn_classifier](n_iter)': 2, '[nn_classifier](n_units_hidden)': 6, '[nn_classifier](lr)': 0.0001}\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:748 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:768 | \n",
       "Selected score 0.4779671717171716 for <Pipeline with ode_classifier> with hyperparameters:\n",
       "{'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'most_frequent', '<candidates>(preprocessing.scaling.static)': 'static_standard_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_standard_scaler', '[ts_minmax_scaler](clip)': False, '[ode_classifier](n_iter)': 2, '[ode_classifier](n_units_hidden)': 6, '[ode_classifier](lr)': 0.0001}\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:748 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:768 | \n",
       "Selected score 0.47575757575757577 for <Pipeline with cde_classifier> with hyperparameters:\n",
       "{'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'mean', '<candidates>(preprocessing.scaling.static)': 'static_minmax_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_minmax_scaler', '[ts_minmax_scaler](clip)': False, '[cde_classifier](n_iter)': 2, '[cde_classifier](n_temporal_units_hidden)': 14, '[cde_classifier](lr)': 0.001}\n"
      ]
@@ -754,7 +760,7 @@
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'window_size'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'device'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'dataloader_sampler'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
-       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'random_state'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'clipping_value'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
@@ -791,7 +797,7 @@
        "            \u001b[32m'window_size'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "            \u001b[32m'device'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
        "            \u001b[32m'dataloader_sampler'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
-       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "            \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
        "            \u001b[32m'random_state'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "            \u001b[32m'clipping_value'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
@@ -823,7 +829,7 @@
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'n_units_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">6</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'n_layers_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
-       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'atol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'rtol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'interpolation'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'cubic'</span>,\n",
@@ -859,7 +865,7 @@
        "            \u001b[32m'n_units_hidden'\u001b[0m: \u001b[1;36m6\u001b[0m,\n",
        "            \u001b[32m'n_layers_hidden'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "            \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
-       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "            \u001b[32m'atol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "            \u001b[32m'rtol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "            \u001b[32m'interpolation'\u001b[0m: \u001b[32m'cubic'\u001b[0m,\n",
@@ -896,7 +902,7 @@
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'n_units_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">100</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'n_layers_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
-       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'atol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'rtol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'interpolation'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'cubic'</span>,\n",
@@ -928,7 +934,7 @@
        "            \u001b[32m'n_units_hidden'\u001b[0m: \u001b[1;36m100\u001b[0m,\n",
        "            \u001b[32m'n_layers_hidden'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "            \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
-       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "            \u001b[32m'atol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "            \u001b[32m'rtol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "            \u001b[32m'interpolation'\u001b[0m: \u001b[32m'cubic'\u001b[0m,\n",
@@ -980,10 +986,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_set_up_tuners:354 | Setting up estimators and tuners for study my_automl_study.\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator cde_classifier.\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator ode_classifier.\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator nn_classifier.\n"
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_set_up_tuners:365 | Setting up estimators and tuners for study my_automl_study.\n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator cde_classifier.\n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator ode_classifier.\n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator nn_classifier.\n"
      ]
     }
    ],
@@ -1051,7 +1057,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/src/tempor/automl/pipeline_selector.py b/src/tempor/automl/pipeline_selector.py
index 777a2d3b..421f9a07 100644
--- a/src/tempor/automl/pipeline_selector.py
+++ b/src/tempor/automl/pipeline_selector.py
@@ -230,7 +230,7 @@ def pipeline_class_from_hps(self, hps: Dict[str, Any]) -> Tuple[Type[PipelineBas
                 pipeline_def.append(get_fqn(prefix, selected))
                 pipeline_init_params[selected] = selected_hps
 
-        pipeline_def.append(self.predictor.fqn())
+        pipeline_def.append(self.predictor.full_name())
         predictor_hps = self._get_relevant_hps(self.predictor.name, hps)
         pipeline_init_params[self.predictor.name] = predictor_hps
 
diff --git a/src/tempor/benchmarks/benchmark.py b/src/tempor/benchmarks/benchmark.py
index df42e91e..20a0cc6a 100644
--- a/src/tempor/benchmarks/benchmark.py
+++ b/src/tempor/benchmarks/benchmark.py
@@ -1,9 +1,11 @@
 from typing import Any, Callable, Dict, List, Optional, Tuple
 
 import matplotlib.pyplot as plt
+import numpy as np
 import pandas as pd
 import pydantic
 import seaborn as sns
+from packaging.version import Version
 
 from tempor.core.types import PredictiveTaskType
 from tempor.data import data_typing, dataset
@@ -131,7 +133,7 @@ def benchmark_models(
 
 
 @pydantic.validate_arguments(config=pydantic.ConfigDict(arbitrary_types_allowed=True))  # type: ignore [operator]
-def visualize_benchmark(results: Dict[str, pd.DataFrame], palette: str = "viridis") -> Any:
+def visualize_benchmark(results: Dict[str, pd.DataFrame], palette: str = "viridis", plot_block: bool = True) -> Any:
     # Pre-format DF for plotting.
     for k, v in results.items():
         v["method"] = k
@@ -146,12 +148,35 @@ def visualize_benchmark(results: Dict[str, pd.DataFrame], palette: str = "viridi
     axes = []
     for metric in err.index:
         set_options = dict(title=f"Benchmark results: {metric}", ylabel=f"{metric} (CV mean)", xlabel="Benchmark case")
-        out = sns.barplot(
-            df_sns[df_sns["metric"] == metric], x="method", y="mean", palette=palette, yerr=err.loc[metric, :]
-        )
+        try:
+            out = sns.barplot(
+                df_sns[df_sns["metric"] == metric],
+                x="method",
+                y="mean",
+                palette=palette,
+                hue="method",
+                yerr=err.loc[metric, :],
+            )
+        except ValueError as ex:
+            if "'yerr'" in str(ex) and Version(sns.__version__) >= Version("0.13.0"):  # pragma: no cover
+                # Known issue with seaborn 0.13.0+. If the y values are non-unique, it seems to expect the yerr values
+                # only as many as there are unique y values. We hence remap using numpy.unique with index return.
+                values = df_sns[df_sns["metric"] == metric]["mean"]
+                _, unique_indexes = np.unique(values, return_index=True)
+                err_remapped = err.loc[metric, :][unique_indexes]
+                out = sns.barplot(
+                    df_sns[df_sns["metric"] == metric],
+                    x="method",
+                    y="mean",
+                    palette=palette,
+                    hue="method",
+                    yerr=err_remapped,
+                )
+            else:  # pragma: no cover
+                raise
         out.set(**set_options)
         axes.append(out)
         log.print(f"Plotting bar plot for metric: {metric}")  # type: ignore [attr-defined]
-        plt.show()
+        plt.show(block=plot_block)
 
     return axes
diff --git a/src/tempor/core/utils.py b/src/tempor/core/utils.py
index 961a5b11..d3e11f23 100644
--- a/src/tempor/core/utils.py
+++ b/src/tempor/core/utils.py
@@ -1,6 +1,6 @@
-from typing import Any, Dict, Tuple, Type
+from typing import Any, Dict, Iterable, List, Tuple, Type
 
-from typing_extensions import get_args
+from typing_extensions import Literal, get_args
 
 
 def get_class_full_name(o: object):
@@ -46,8 +46,16 @@ def ensure_literal_matches_dict_keys(
         )
 
 
+PreferArgOrKwarg = Literal["arg", "kwarg", "raise"]
+
+
 def get_from_args_or_kwargs(
-    args: Tuple, kwargs: Dict, argument_name: str, argument_type: Type, position_if_args: int
+    args: Tuple,
+    kwargs: Dict,
+    argument_name: str,
+    argument_type: Type,
+    position_if_args: int,
+    prefer: PreferArgOrKwarg = "raise",
 ) -> Tuple[Any, Tuple, Dict]:
     """Will attempt to get the function argument as defined by ``argument_name``, ``argument_type``, and
     ``position_if_args`` from ``args`` and ``kwargs``. Will return `None` if no such argument found.
@@ -56,7 +64,9 @@ def get_from_args_or_kwargs(
     Algorithm:
         1. Check if an ``arg`` of type ``argument_type`` is found at index ``position_if_args`` in ``args``.
         2. Check if a ``kwarg`` by key ``argument_name`` is found in ``kwargs``.
-        3. If both 1 and 2 are found raise `RuntimeError`.
+        3. If both 1 and 2 are found raise `RuntimeError` if ``prefer`` is set to ``"raise"``. Otherwise take the \
+            ``arg`` or ``kwarg`` item as specified by ``prefer`` accordingly. The other item will be left as it was \
+            originally provided in ``args``/``kwargs``.
         4. If ``kwarg`` from 2 is not of type ``argument_type`` raise `TypeError`.
         5. Return 1 or 2 if argument is found, else return `None`. Also return ``args`` and ``kwargs``\
             with the argument "popped".
@@ -72,6 +82,9 @@ def get_from_args_or_kwargs(
             The type of the argument to confirm.
         position_if_args (int):
             The index in ``args`` at which the argument should be found, if it is provided by ``args``.
+        prefer (PreferArgOrKwarg, optional):
+            Whether to prefer the ``arg`` or the ``kwarg`` if both are found, or to raise an exception if this is set \
+            to ``"raise"``. Defaults to ``"raise"``.
 
     Raises:
         RuntimeError: Error in case the argument appears to have been provided by both ``args`` and ``kwargs``.
@@ -90,13 +103,37 @@ def get_from_args_or_kwargs(
             args = tuple([x for i, x in enumerate(args) if i != position_if_args])
     from_kwargs = kwargs.pop(argument_name, None)
     if from_args is not None and from_kwargs is not None:
-        raise RuntimeError(
-            f"Argument `{argument_name}` appears to have been passed as `kwargs` (by key '{argument_name}') "
-            f"and as `args` (at position {position_if_args}), but it should be passed in only one of these ways"
-        )
+        if prefer == "raise":
+            raise RuntimeError(
+                f"Argument `{argument_name}` appears to have been passed as `kwargs` (by key '{argument_name}') "
+                f"and as `args` (at position {position_if_args}), but it should be passed in only one of these ways"
+            )
+        elif prefer == "kwarg":
+            args_list = list(args)
+            args_list.insert(position_if_args, from_args)
+            args = tuple(args_list)
+            from_args = None
+        else:
+            kwargs[argument_name] = from_kwargs
+            from_kwargs = None
     if from_kwargs is not None and not isinstance(from_kwargs, argument_type):
         raise TypeError(
             f"Argument `{argument_name}` was passed as `kwargs` (by key '{argument_name}') but was not of "
             f"expected type `{argument_type}`"
         )
     return from_args if from_args is not None else from_kwargs, args, kwargs
+
+
+def unique_in_order_of_appearance(iterable: Iterable) -> List:
+    """Return unique elements from ``iterable`` in order of their appearance.
+
+    Note:
+        All items in ``iterable`` must be hashable.
+
+    Args:
+        iterable (Iterable): The iterable to get unique elements from.
+
+    Returns:
+        List: List of unique elements in order of their appearance.
+    """
+    return list(dict.fromkeys(iterable))
diff --git a/src/tempor/plugins/core/_base_estimator.py b/src/tempor/plugins/core/_base_estimator.py
index 446417e4..e4a7e203 100644
--- a/src/tempor/plugins/core/_base_estimator.py
+++ b/src/tempor/plugins/core/_base_estimator.py
@@ -73,6 +73,7 @@ def is_fitted(self) -> bool:
     def __rich_repr__(self):
         yield "name", self.name
         yield "category", self.category
+        yield "plugin_type", self.plugin_type
         yield "params", omegaconf.OmegaConf.to_container(self.params)
 
     def __repr__(self) -> str:
diff --git a/src/tempor/plugins/core/_plugin.py b/src/tempor/plugins/core/_plugin.py
index 76f15e06..8610c6c7 100644
--- a/src/tempor/plugins/core/_plugin.py
+++ b/src/tempor/plugins/core/_plugin.py
@@ -5,31 +5,209 @@
 import os
 import os.path
 import sys
-from typing import TYPE_CHECKING, Any, Callable, ClassVar, Dict, List, Type, TypeVar
+from typing import TYPE_CHECKING, Any, Callable, ClassVar, Dict, List, Optional, Tuple, Type, TypeVar, Union, overload
 
-from typing_extensions import ParamSpec
+from typing_extensions import Literal, ParamSpec, get_args
 
 import tempor
+import tempor.core.utils as core_utils
 from tempor.log import logger
 
 from . import utils
 
 PLUGIN_NAME_NOT_SET = "NOT_SET"
 PLUGIN_CATEGORY_NOT_SET = "NOT_SET"
+PLUGIN_TYPE_NOT_SET = "NOT_SET"
+
 
 P = ParamSpec("P")
 T = TypeVar("T")
 
+# Type aliases:
+PluginType = str
+"""Type alias to indicate plugin type, such as ``'method'``."""
+PluginTypeArgAll = Literal["all"]
+"""Literal for argument options indicating all plugin types."""
+PluginTypeArg = Union[None, PluginTypeArgAll, str]
+"""Plugin type argument type. May be `PluginType` (`str`), None, or `PluginTypeArgAll` (``"all"``)"""
+PluginName = str
+"""Type alias to indicate plugin name, such as ``'my_nn_classifier'``."""
+PluginFullName = str
+"""Type alias to indicate plugin full name (with all [sub]categories),
+such as ``'prediction.one_off.classification.my_nn_classifier'``.
+"""
+PluginCategory = str
+"""Type alias to indicate plugin category (including all [sub]categories),
+such as ``'prediction.one_off.classification'``.
+"""
+
+# Internal type aliases:
+_PluginFqn = str
+"""Type alias to indicate plugin FQN, including both [plugin_type] and category,
+such as ``'[method].prediction.one_off.classification.my_nn_classifier'``.
+"""
+_PluginCategoryFqn = str
+"""Type alias to indicate plugin category FQN, including both [plugin_type] and category,
+such as ``'[method].prediction.one_off.classification'``.
+"""
+
+# Default plugin type:
+DEFAULT_PLUGIN_TYPE = "method"
+"""Default plugin type to which plugins will be assigned if no plugin type is specified
+(plugin type set to ``None``).
+"""
+
+# All plugin types indicator:
+ALL_PLUGIN_TYPES_INDICATOR = get_args(PluginTypeArgAll)[0]
+"""A string that indicates all plugins."""
+
+
+# Local helpers. ---
+
+
+def parse_plugin_type(plugin_type: PluginTypeArg, must_be_one_of: Optional[List[str]] = None) -> PluginTypeArg:
+    """Get the default plugin type if ``plugin_type`` is ``None``. If ``plugin_type`` is ``"all"``, raise error,
+    as that is a reserved value.
+
+    Args:
+        plugin_type (PluginType): Plugin type.
+        must_be_one_of (List[str]): List of plugin types that ``plugin_type`` must be one of.
+
+    Returns:
+        PluginType: Default plugin type if ``plugin_type`` is ``None``, otherwise ``plugin_type``.
+    """
+    if plugin_type == ALL_PLUGIN_TYPES_INDICATOR:
+        raise ValueError(f"Plugin type cannot be '{plugin_type}' as that is a reserved value.")
+    if plugin_type is None:
+        return DEFAULT_PLUGIN_TYPE
+    if must_be_one_of and plugin_type not in must_be_one_of:
+        raise ValueError(f"Plugin type must be one of {must_be_one_of} but was '{plugin_type}'")
+    return plugin_type
+
+
+def create_fqn(suffix: Union[PluginCategory, PluginFullName], plugin_type: PluginTypeArg) -> str:
+    """Create a fully-qualified name for a plugin or category, like `[plugin_type].category.name` or
+    `[plugin_type].category` respectively.
+
+    Args:
+        suffix (Union[PluginCategory, PluginFullName]): Plugin category or plugin full name.
+        plugin_type (PluginType): Plugin type.
+
+    Returns:
+        str: Fully-qualified name.
+    """
+    if plugin_type is None:
+        raise ValueError("Plugin type cannot be `None`. Did you forget to call `get_default_plugin_type`?")
+    return f"[{plugin_type}].{suffix}"
+
+
+def filter_list_by_plugin_type(lst: List[_PluginFqn], plugin_type: PluginTypeArg) -> List[PluginFullName]:
+    """Filter a list of plugin FQNs by plugin type.
+
+    Args:
+        lst (List[_PluginFqn]): List of plugin FQNs.
+        plugin_type (PluginType): Plugin type.
+
+    Returns:
+        List[PluginFullName]: Filtered list which will only include FQNs with the specified ``plugin_type``.
+    """
+    return [x for x in lst if x.split(".")[0] == f"[{plugin_type}]"]
+
+
+def filter_dict_by_plugin_type(d: Dict[_PluginFqn, Any], plugin_type: PluginTypeArg) -> Dict[PluginFullName, Any]:
+    """Filter a dictionary with plugin FQN keys by plugin type.
+
+    Args:
+        d (Dict[_PluginFqn, Any]): Dictionary to filter.
+        plugin_type (PluginType): Plugin type.
+
+    Returns:
+        Dict[PluginFullName, Any]: Filtered dictionary which will only include items where FQN keys match the \
+            specified ``plugin_type``.
+    """
+    return {k: v for k, v in d.items() if k.split(".")[0] == f"[{plugin_type}]"}
+
+
+def _parse_fqn_format(fqn: str) -> Tuple[PluginTypeArg, str]:
+    """Parse a plugin FQN or category FQN into its plugin type and remainder (``category`` or ``category.name``) parts.
+
+    Args:
+        fqn (str): Plugin FQN or category FQN.
+
+    Raises:
+        ValueError: Raised if the FQN is of incorrect format, that is, doesn't begin with ``[<plugin_type>].<...>``.
+
+    Returns:
+        Tuple[PluginType, str]: Plugin type, remainder (``category`` or ``category.name``).
+    """
+    first_element = fqn.split(".")[0]
+    if not (first_element[0] == "[" and first_element[-1] == "]"):
+        raise ValueError(f"FQN '{fqn}' is of incorrect format, expected to begin with `[<plugin_type>].<...>`")
+    plugin_type = first_element[1:-1]
+    remainder = ".".join(fqn.split(".")[1:])
+    return plugin_type, remainder
+
+
+def remove_plugin_type_from_fqn(fqn: Union[_PluginCategoryFqn, _PluginFqn]) -> Union[PluginCategory, PluginFullName]:
+    """Remove the plugin type part of a plugin FQN or category FQN.
+
+    Args:
+        fqn (Union[_PluginCategoryFqn, _PluginFqn]): Plugin FQN of plugin category FQN.
+
+    Returns:
+        str: The FQN with the plugin type part removed.
+    """
+    _, remainder = _parse_fqn_format(fqn)
+    return remainder
+
+
+def get_plugin_type_from_fqn(fqn: Union[_PluginCategoryFqn, _PluginFqn]) -> PluginTypeArg:
+    """Get the plugin type part of a plugin FQN or category FQN.
+
+    Args:
+        fqn (Union[_PluginCategoryFqn, _PluginFqn]): Plugin FQN of plugin category FQN.
+
+    Returns:
+        PluginType: The plugin type.
+    """
+    plugin_type, _ = _parse_fqn_format(fqn)
+    return plugin_type
+
+
+# Local helpers (end). ---
+
 
 class Plugin:
-    name: ClassVar[str] = PLUGIN_NAME_NOT_SET
-    category: ClassVar[str] = PLUGIN_CATEGORY_NOT_SET
+    """The base class that all plugins must inherit from."""
+
+    name: ClassVar[PluginName] = PLUGIN_NAME_NOT_SET
+    """Plugin name, such as ``'my_nn_classifier'``. Must be set by the plugin class using ``@register_plugin``."""
+    category: ClassVar[PluginCategory] = PLUGIN_CATEGORY_NOT_SET
+    """Plugin category, such as ``'prediction.one_off.classification'``.
+    Must be set by the plugin class using ``@register_plugin``.
+    """
+    plugin_type: ClassVar[PluginTypeArg] = PLUGIN_TYPE_NOT_SET
+    """Plugin type, such as ``'method'``. May be optionally set by the plugin class using ``@register_plugin``,
+    else will set the default plugin type.
+    """
 
     @classmethod
-    def fqn(cls) -> str:
-        """The fully-qualified name of the plugin: category.name"""
+    def full_name(cls) -> PluginFullName:
+        """The full name of the plugin with its category: ``category.subcategory.name``.
+        There may be 0 or more subcategories.
+        """
         return f"{cls.category}.{cls.name}"
 
+    @classmethod
+    def _fqn(cls) -> _PluginFqn:
+        """The fully-qualified name of the plugin with its plugin type: ``[plugin_type].category.subcategory.name``"""
+        return f"{create_fqn(cls.category, cls.plugin_type)}.{cls.name}"
+
+    @classmethod
+    def _category_fqn(cls) -> _PluginCategoryFqn:
+        """The fully-qualified name of the plugin's category: ``[plugin_type].category.subcategory``"""
+        return f"{create_fqn(cls.category, cls.plugin_type)}"
+
     def __init__(self) -> None:
         if self.name == PLUGIN_NAME_NOT_SET:
             raise ValueError(f"Plugin {self.__class__.__name__} `name` was not set, use @{register_plugin.__name__}")
@@ -37,19 +215,47 @@ def __init__(self) -> None:
             raise ValueError(
                 f"Plugin {self.__class__.__name__} `category` was not set, use @{register_plugin.__name__}"
             )
+        if self.plugin_type == PLUGIN_TYPE_NOT_SET:
+            raise ValueError(
+                f"Plugin {self.__class__.__name__} `plugin_type` was not set, use @{register_plugin.__name__}"
+            )
 
 
-PLUGIN_CATEGORY_REGISTRY: Dict[str, Type[Plugin]] = dict()
-PLUGIN_REGISTRY: Dict[str, Type[Plugin]] = dict()
-
-
-def register_plugin_category(category: str, expected_class: Type) -> None:
+# Important dicts that store plugin information:
+PLUGIN_CATEGORY_REGISTRY: Dict[_PluginCategoryFqn, Type[Plugin]] = dict()
+"""Important dictionary for plugin functionality. Records all plugin categories
+(``'[plugin_type].category.<0 or more subcategories if applicable>'``) and their corresponding plugin classes."""
+PLUGIN_REGISTRY: Dict[_PluginFqn, Type[Plugin]] = dict()
+"""Important dictionary for plugin functionality. Records all plugins by their fully-qualified name
+``'[plugin_type].category.<0 or more subcategories if applicable>.plugin_name'``."""
+
+
+def register_plugin_category(category: PluginCategory, expected_class: Type, plugin_type: PluginTypeArg = None) -> None:
+    """A decorator to register a plugin category (with optional subcategories). If ``plugin_type`` is provided,
+    this will also be assigned (or created, if such plugin type doesn't yet exist), otherwise the default plugin type
+    will be used.
+
+    Args:
+        category (PluginCategory): Plugin category, dot-separated, with optional subcategories, \
+            such as ``'prediction.one_off.classification'``.
+        expected_class (Type): The expected plugin class for this category. The plugin class must be a subclass of \
+            this class. Note that this class must itself be a subclass of ``Plugin``.
+        plugin_type (PluginType, optional): Plugin type to register the category under. Different plugin types should \
+            be used to indicate different domains of your code (e.g. methods vs metrics vs datasets). \
+            Defaults to `None`.
+
+    Raises:
+        TypeError: If the ``expected_class`` is not correctly defined.
+    """
+    plugin_type = parse_plugin_type(plugin_type)
+    logger.debug(f"Registering plugin type {plugin_type}")
     logger.debug(f"Registering plugin category {category}")
-    if category in PLUGIN_CATEGORY_REGISTRY:
-        raise TypeError(f"Plugin category {category} already registered")
+    category_fqn = create_fqn(suffix=category, plugin_type=plugin_type)
+    if category_fqn in PLUGIN_CATEGORY_REGISTRY:
+        raise TypeError(f"Plugin category {category} already registered under plugin type {plugin_type}")
     if not issubclass(expected_class, Plugin):
         raise TypeError(f"Plugin expected class for category should be a subclass of {Plugin} but was {expected_class}")
-    PLUGIN_CATEGORY_REGISTRY[category] = expected_class
+    PLUGIN_CATEGORY_REGISTRY[category_fqn] = expected_class
 
 
 def _check_same_class(class_1, class_2) -> bool:
@@ -60,8 +266,21 @@ def _check_same_class(class_1, class_2) -> bool:
     )
 
 
-def register_plugin(name: str, category: str):
-    def class_decorator(cls: Callable[P, T]) -> Callable[P, T]:
+def register_plugin(name: str, category: PluginCategory, plugin_type: PluginTypeArg = None):
+    """A decorator to register a plugin class. If ``plugin_type`` is provided, this will also be assigned,
+    otherwise the default plugin type will be used. The ``category`` must have already been registered with
+    ``@register_plugin_category`` before this can be used to register a plugin.
+
+    Args:
+        name (str): Plugin name, such as ``'my_nn_classifier'``.
+        category (PluginCategory): Plugin category, dot-separated, with optional subcategories, \
+            such as ``'prediction.one_off.classification'``.
+        plugin_type (PluginType, optional): Plugin type of the category. If left as `None`, default plugin type is \
+            assumed. ``plugin_type`` must correctly correspond to the ``category`` being specified. \
+            Defaults to `None`.
+    """
+
+    def _class_decorator(cls: Callable[P, T]) -> Callable[P, T]:
         # NOTE:
         # The Callable[<ParamSpec>, <TypeVar>] approach allows to preserve the type annotation of the parameters of the
         # wrapped class (its __init__ method, specifically). See resources:
@@ -77,105 +296,322 @@ def class_decorator(cls: Callable[P, T]) -> Callable[P, T]:
         cls.name = name
         cls.category = category
 
-        if cls.category not in PLUGIN_CATEGORY_REGISTRY:
+        _plugin_type = parse_plugin_type(plugin_type)
+        cls.plugin_type = _plugin_type
+
+        category_fqn = create_fqn(suffix=category, plugin_type=_plugin_type)
+
+        if category_fqn not in PLUGIN_CATEGORY_REGISTRY:
             raise TypeError(
-                f"Found plugin category {cls.category} which has not been registered with "
-                f"@{register_plugin_category.__name__}"
+                f"Found plugin category '{cls.category}' under plugin type '{cls.plugin_type}' which "
+                f"has not been registered with `@{register_plugin_category.__name__}`"
             )
         if not issubclass(cls, Plugin):
-            raise TypeError(f"Expected plugin class {cls.__name__} to be a subclass of {Plugin} but was {cls}")
-        if not issubclass(cls, PLUGIN_CATEGORY_REGISTRY[cls.category]):
+            raise TypeError(f"Expected plugin class `{cls.__name__}` to be a subclass of `{Plugin}` but was `{cls}`")
+        if not issubclass(cls, PLUGIN_CATEGORY_REGISTRY[category_fqn]):
             raise TypeError(
-                f"Expected plugin class {cls.__name__} to be a subclass of "
-                f"{PLUGIN_CATEGORY_REGISTRY[cls.category]} but was {cls}"
+                f"Expected plugin class `{cls.__name__}` to be a subclass of "
+                f"`{PLUGIN_CATEGORY_REGISTRY[category_fqn]}` but was `{cls}`"
             )
-        if cls.fqn() in PLUGIN_REGISTRY:
-            if not _check_same_class(cls, PLUGIN_REGISTRY[cls.fqn()]):
+        # pylint: disable-next=protected-access
+        if cls._fqn() in PLUGIN_REGISTRY:
+            # pylint: disable-next=protected-access
+            if not _check_same_class(cls, PLUGIN_REGISTRY[cls._fqn()]):
                 raise TypeError(
-                    f"Plugin with fully-qualified name {cls.fqn()} already registered (as class "
-                    f"{PLUGIN_REGISTRY[cls.fqn()]})"
+                    # pylint: disable-next=protected-access
+                    f"Plugin (plugin type '{cls.plugin_type}') with full name '{cls.full_name()}' has already been "
+                    f"registered (as class `{PLUGIN_REGISTRY[cls._fqn()]}`)"
                 )
             else:
                 # The same class is being reimported, do not raise error.
                 pass
         for existing_cls in PLUGIN_REGISTRY.values():
             # Cannot have the same plugin name (not just fqn), as this is not supported by Pipeline.
+            # TODO: Fix this - make non-unique name work with pipeline.
             if cls.name == existing_cls.name:
                 if not _check_same_class(cls, existing_cls):
-                    raise TypeError(f"Plugin with name {cls.name} already registered (as class {existing_cls})")
+                    raise TypeError(
+                        f"Plugin (plugin type '{cls.plugin_type}') with name '{cls.name}' has already been "
+                        f"registered (as class `{existing_cls}`). Must use a unique plugin name."
+                    )
                 else:  # pragma: no cover
                     # The same class is being reimported, do not raise error.
-                    # Some kind of coverage issues - this case *is* covered by test:
+                    # Some kind of coverage issue - this case *is* covered by test:
                     # test_plugins.py::TestRegistration::test_category_registration_reimport_allowed
                     pass
 
-        PLUGIN_REGISTRY[cls.fqn()] = cls
+        # pylint: disable-next=protected-access
+        PLUGIN_REGISTRY[cls._fqn()] = cls
 
         return cls
 
-    return class_decorator
+    return _class_decorator
 
 
+# TODO: Consider whether to enforce common base class across plugin_type/category.
 class PluginLoader:
+    """A class to load plugins. Provides functionality to list and get plugins."""
+
     def __init__(self) -> None:
         self._refresh()
 
     def _refresh(self):
+        # Internal method to refresh plugin registries.
+
         self._plugin_registry: Dict[str, Type[Plugin]] = PLUGIN_REGISTRY
 
-        name_by_category: Dict = dict()
+        name_by_category_nested: Dict = dict()
         for plugin_class in self._plugin_registry.values():
-            name_by_category = utils.append_by_dot_path(
-                name_by_category, key_path=plugin_class.category, value=plugin_class.name
+            name_by_category_nested = utils.append_by_dot_path(
+                name_by_category_nested,
+                key_path=plugin_class._category_fqn(),  # pylint: disable=protected-access
+                value=plugin_class.name,
             )
-        self._plugin_name_by_category = name_by_category
+        self._plugin_name_by_category_nested = name_by_category_nested
 
-        class_by_category: Dict = dict()
+        class_by_category_nested: Dict = dict()
         for plugin_class in self._plugin_registry.values():
-            class_by_category = utils.append_by_dot_path(
-                class_by_category, key_path=plugin_class.category, value=plugin_class
+            class_by_category_nested = utils.append_by_dot_path(
+                class_by_category_nested,
+                key_path=plugin_class._category_fqn(),  # pylint: disable=protected-access
+                value=plugin_class,
             )
-        self._plugin_class_by_category = class_by_category
-
-    def list(self) -> Dict:
+        self._plugin_class_by_category_nested = class_by_category_nested
+
+    def _handle_all_plugin_types_case(self, pt: PluginTypeArg, method: Callable, *args, **kwargs) -> Dict:
+        # If ``pt`` (plugin type) is "all", will call ``method`` for all plugin types and return a nested dictionary.
+        # Otherwise, just calls ``method`` and return what it returns.
+        # In either case, plugin type value(s) will be passed to ``method`` by ``plugin_type`` kwarg.
+        if pt == ALL_PLUGIN_TYPES_INDICATOR:
+            output = dict()
+            for actual_pt in self.list_plugin_types():
+                output[actual_pt] = method(*args, **kwargs, plugin_type=actual_pt)
+            return output
+        else:
+            return method(*args, **kwargs, plugin_type=pt)
+
+    def _list(self, plugin_type: PluginTypeArg = None) -> Dict:
         self._refresh()
-        return self._plugin_name_by_category
+        plugin_type = parse_plugin_type(plugin_type, must_be_one_of=self.list_plugin_types())
+        return self._plugin_name_by_category_nested[f"[{plugin_type}]"]
 
-    def list_fqns(self) -> List[str]:
-        self._refresh()
-        return list(self._plugin_registry.keys())
+    def list(self, plugin_type: PluginTypeArg = None) -> Dict:
+        """List all plugins of ``plugin_type`` as a nested dictionary, where the keys are the plugin categories
+        and optional subcategories. The values of the dictionary are the plugin names.
 
-    def list_classes(self) -> Dict:
-        self._refresh()
-        return self._plugin_class_by_category
+        If ``plugin_type`` is ``"all"``, will list for all plugin types, outputting inside a nested dictionary
+        with plugin type keys.
 
-    def list_categories(self) -> Dict[str, Type[Plugin]]:
-        self._refresh()
-        return PLUGIN_CATEGORY_REGISTRY
+        Args:
+            plugin_type (PluginType, optional): Plugin type for which to list. Use default category if `None`. \
+                Defaults to `None`.
 
-    def _raise_plugin_does_not_exist_error(self, name: str):
-        if name not in self._plugin_registry:
-            raise ValueError(f"Plugin {name} does not exist.")
+        Returns:
+            Dict: A dictionary as described above.
+        """
+        return self._handle_all_plugin_types_case(plugin_type, self._list)
 
-    def get(self, name: str, *args, **kwargs) -> Any:
+    def _list_full_names(self, plugin_type: PluginTypeArg = None) -> List[PluginFullName]:
         self._refresh()
-        self._raise_plugin_does_not_exist_error(name)
-        return self._plugin_registry[name](*args, **kwargs)
+        plugin_fqns = list(self._plugin_registry.keys())
+        plugin_type = parse_plugin_type(plugin_type, must_be_one_of=self.list_plugin_types())
+        plugin_fqns_filtered_by_type = filter_list_by_plugin_type(lst=plugin_fqns, plugin_type=plugin_type)
+        return [remove_plugin_type_from_fqn(n) for n in plugin_fqns_filtered_by_type]
+
+    def list_full_names(
+        self, plugin_type: PluginTypeArg = None
+    ) -> Union[List[PluginFullName], Dict[str, List[PluginFullName]]]:
+        """List all plugins of ``plugin_type`` as a list of plugin full names (including categories).
+
+        If ``plugin_type`` is ``"all"``, will list for all plugin types, outputting inside a nested dictionary
+        with plugin type keys.
+
+        Args:
+            plugin_type (PluginType, optional): Plugin type for which to list. Use default category if `None`. \
+                Defaults to `None`.
+
+        Returns:
+            Union[List[PluginFullName], Dict[str, List[PluginFullName]]]: A list as \
+                described above (``List[PluginFullName]``) if ``plugin_type`` is not ``"all"``. \
+                Otherwise a nested dictionary with plugin type keys and such lists as values \
+                (``Dict[str, List[PluginFullName]]]``).
+        """
+        return self._handle_all_plugin_types_case(plugin_type, self._list_full_names)
+
+    def _list_classes(self, plugin_type: PluginTypeArg = None) -> Dict:
+        self._refresh()
+        plugin_type = parse_plugin_type(plugin_type, must_be_one_of=self.list_plugin_types())
+        return self._plugin_class_by_category_nested[f"[{plugin_type}]"]
+
+    def list_classes(self, plugin_type: PluginTypeArg = None) -> Dict:
+        """List all plugin classes of ``plugin_type`` as a nested dictionary, where the keys are the plugin categories
+        and optional subcategories. The values of the dictionary are the plugin **classes**.
 
-    def get_class(self, name: str) -> Type:
+        If ``plugin_type`` is ``"all"``, will list for all plugin types, outputting inside a nested dictionary
+        with plugin type keys.
+
+        Args:
+            plugin_type (PluginType, optional): Plugin type for which to list. Use default category if `None`. \
+                Defaults to `None`.
+
+        Returns:
+            Dict: A dictionary as described above.
+        """
+        return self._handle_all_plugin_types_case(plugin_type, self._list_classes)
+
+    def _list_categories(self, plugin_type: PluginTypeArg = None) -> Dict[PluginFullName, Type[Plugin]]:
+        self._refresh()
+        plugin_type = parse_plugin_type(plugin_type, must_be_one_of=self.list_plugin_types())
+        categories_filtered_by_type = filter_dict_by_plugin_type(d=PLUGIN_CATEGORY_REGISTRY, plugin_type=plugin_type)
+        return {remove_plugin_type_from_fqn(k): v for k, v in categories_filtered_by_type.items()}
+
+    def list_categories(
+        self, plugin_type: PluginTypeArg = None
+    ) -> Union[Dict[PluginFullName, Type[Plugin]], Dict[PluginType, Dict[PluginFullName, Type[Plugin]]]]:
+        """List all plugin categories of ``plugin_type`` as a dictionary, where the keys are the plugin category names
+        (including optional subcategories) and the values are the **expected plugin classes** for that category.
+
+        If ``plugin_type`` is ``"all"``, will list for all plugin types, outputting inside a nested dictionary
+        with plugin type keys.
+
+        Args:
+            plugin_type (PluginType, optional): Plugin type for which to list. Use default category if `None`. \
+                Defaults to `None`.
+
+        Returns:
+            Union[Dict[PluginFullName, Type[Plugin]], Dict[PluginType, Dict[PluginFullName, Type[Plugin]]]]: A \
+                dictionary as described above (``Dict[PluginFullName, Type[Plugin]]``) if ``plugin_type`` is \
+                not ``"all"``. Otherwise a nested dictionary with plugin type keys and such dictionaries as values \
+                (``Dict[PluginType, Dict[PluginFullName, Type[Plugin]]]``).
+        """
+        return self._handle_all_plugin_types_case(plugin_type, self._list_categories)
+
+    def list_plugin_types(self) -> List[PluginType]:
+        """List all plugin types.
+
+        Returns:
+            List[str]: A list of plugin types.
+        """
         self._refresh()
-        self._raise_plugin_does_not_exist_error(name)
-        return self._plugin_registry[name]
+        return core_utils.unique_in_order_of_appearance(
+            [get_plugin_type_from_fqn(fqn) for fqn in self._plugin_registry.keys()]
+        )
+
+    def _raise_plugin_does_not_exist_error(self, fqn: str):
+        plugin_type = get_plugin_type_from_fqn(fqn)
+        plugin_full_name = remove_plugin_type_from_fqn(fqn)
+        if fqn not in self._plugin_registry:
+            raise ValueError(f"Plugin '{plugin_full_name}' (plugin type: {plugin_type}) does not exist.")
+
+    def _handle_get_args_kwargs(self, args, kwargs) -> Tuple[Any, Tuple, Dict]:
+        # "Pop" the `plugin_type` argument if such is found in args (position 0) or kwargs.
+        # If appears to be provided in both ways, prefer the value from kwargs and leave the string in args as is.
+        # If not, `plugin_type` will fall back to its default value.
+        plugin_type, args, kwargs = core_utils.get_from_args_or_kwargs(
+            args, kwargs, argument_name="plugin_type", argument_type=str, position_if_args=0, prefer="kwarg"
+        )
+        if plugin_type is None:
+            plugin_type = parse_plugin_type(None)
+        return plugin_type, args, kwargs
+
+    # Explicitly listing all the overloads for clarity of documentation.
+    @overload
+    def get(self, name: PluginFullName, *args, **kwargs) -> Type:
+        ...  # pragma: co cover
+
+    @overload
+    def get(  # type: ignore [misc]
+        self,
+        name: PluginFullName,
+        plugin_type: PluginTypeArg,
+        *args,
+        **kwargs,
+    ) -> Type:
+        ...  # pragma: co cover
+
+    @overload
+    def get(  # type: ignore [misc]
+        self,
+        name: PluginFullName,
+        *args,
+        plugin_type: PluginTypeArg = None,
+        **kwargs,
+    ) -> Type:
+        ...  # pragma: co cover
+
+    def get(self, name: PluginFullName, *args, **kwargs) -> Any:
+        """Get a plugin by its full name (including category, i.e. of form
+        ``'my_category.my_subcategory.my_plugin'``). Use ``*args`` and ``**kwargs`` to pass arguments to
+        the plugin initializer. The returned object is an instance of the plugin class. If the plugin is not of the
+        default plugin type, must provide ``plugin_type`` also.
+
+        The method can be called with ``plugin_type`` and plugin initializer arguments, as follows:
+
+        - As first positional argument after the plugin name:
+            >>> plugin_instance = get(  # doctest: +SKIP
+            ...     "my_category.my_subcategory.my_plugin",  # Plugin full name.
+            ...     "method",  # Plugin type provided as a positional argument (first).
+            ...     0.4,  # First positional argument to plugin initializer.
+            ...     123,  # Second positional argument to plugin initializer...
+            ...     kwarg=2,  # Keyword argument(s) to plugin initializer from here on.
+            ... )
+
+        - As keyword argument:
+            >>> plugin_instance = get(  # doctest: +SKIP
+            ...     "my_category.my_subcategory.my_plugin",  # Plugin full name.
+            ...     0.4,  # First positional argument to plugin initializer.
+            ...     123,  # Second positional argument to plugin initializer...
+            ...     plugin_type="method",  # Plugin type provided as a keyword argument.
+            ...     kwarg=2,  # Keyword argument(s) to plugin initializer from here on.
+            ... )
+
+        Args:
+            name (PluginFullName): Plugin full name including all (sub)categories, of form \
+                ``'my_category.my_subcategory.my_plugin'``
+
+        Returns:
+            Any: The plugin instance initialised with ``*args`` and ``**kwargs`` as provided.
+        """
+        plugin_type, args, kwargs = self._handle_get_args_kwargs(args, kwargs)
+        self._refresh()
+        plugin_type = parse_plugin_type(plugin_type, must_be_one_of=self.list_plugin_types())
+        fqn = create_fqn(suffix=name, plugin_type=plugin_type)
+        self._raise_plugin_does_not_exist_error(fqn)
+        return self._plugin_registry[fqn](*args, **kwargs)
+
+    def get_class(self, name: PluginFullName, plugin_type: PluginTypeArg = None) -> Type:
+        """Get a plugin class (not instance) by its full name (including category, i.e. of form
+        ``'my_category.my_subcategory.my_plugin'``). If the plugin is not of the default plugin type, must provide
+        ``plugin_type``.
+
+        Args:
+            name (PluginFullName): Plugin full name including all (sub)categories, of form \
+                ``'my_category.my_subcategory.my_plugin'``
+            plugin_type (PluginType, optional): Plugin type. If left as `None`, default plugin type is assumed. \
+                ``plugin_type`` must correctly correspond to the category implied by plugin full name. \
+                Defaults to `None`.
+
+        Returns:
+            Type: Plugin class (not instance).
+        """
+        self._refresh()
+        plugin_type = parse_plugin_type(plugin_type, must_be_one_of=self.list_plugin_types())
+        fqn = create_fqn(suffix=name, plugin_type=plugin_type)
+        self._raise_plugin_does_not_exist_error(fqn)
+        return self._plugin_registry[fqn]
 
 
 PLUGIN_FILENAME_PREFIX = "plugin_"
+"""Prefix expected for plugin filenames of python files that contain plugin code."""
 
 
 def _glob_plugin_paths(package_dir: str) -> List[str]:
+    # Get the paths of all python files in the package directory that begin with `PLUGIN_FILENAME_PREFIX`.
     return [f for f in glob.glob(os.path.join(package_dir, f"{PLUGIN_FILENAME_PREFIX}*.py")) if os.path.isfile(f)]
 
 
 def _module_name_from_path(path: str) -> str:
+    # Return a module name from a path to a python file, raise exception if not a python file.
     path = os.path.normpath(path)
     split = path[path.rfind(f"{tempor.import_name}{os.sep}") :].split(os.sep)
     if split[-1][-3:] != ".py":  # pragma: no cover
@@ -185,9 +621,20 @@ def _module_name_from_path(path: str) -> str:
     return ".".join(split)
 
 
-class importing:  # Functions as namespace, for clarity.
+class importing:
+    """A namespace for plugin importing functionality."""
+
     @staticmethod
     def import_plugins(init_file: str) -> None:
+        """Import all plugin modules inside the package directory associated with ``init_file`` (``__init__.py``).
+        Importing in this context means programmatic import and execution of the plugin modules.
+
+        Args:
+            init_file (str): The init file for the package directory containing the plugin modules (files).
+
+        Raises:
+            RuntimeError: Raised if there are import problems with any of the plugin modules.
+        """
         package_dir = os.path.dirname(init_file)
         logger.debug(f"Importing all plugin modules inside {package_dir}")
         paths = _glob_plugin_paths(package_dir=package_dir)
@@ -204,6 +651,15 @@ def import_plugins(init_file: str) -> None:
 
     @staticmethod
     def gather_modules_names(package_init_file: str) -> List[str]:
+        """Gather the names of all plugin modules inside the package directory associated with ``init_file``.
+        Useful for e.g. setting the ``__all__`` variable.
+
+        Args:
+            package_init_file (str): The init file for the package directory containing the plugin modules (files).
+
+        Returns:
+            List[str]: A list of plugin module names.
+        """
         package_dir = os.path.dirname(package_init_file)
         paths = _glob_plugin_paths(package_dir=package_dir)
         return [_module_name_from_path(f) for f in paths]
diff --git a/src/tempor/plugins/pipeline/generators.py b/src/tempor/plugins/pipeline/generators.py
index 1c7c8d54..cf3815b8 100644
--- a/src/tempor/plugins/pipeline/generators.py
+++ b/src/tempor/plugins/pipeline/generators.py
@@ -8,7 +8,7 @@
 
 def _generate_pipeline_seq_impl(plugins: Tuple[Type, ...]) -> Callable:
     def pipeline_seq_impl(*args: Any) -> str:  # pylint: disable=unused-argument
-        return "->".join(p.fqn() for p in plugins)
+        return "->".join(p.full_name() for p in plugins)
 
     return pipeline_seq_impl
 
diff --git a/tutorials/data/tutorial01_data_format.ipynb b/tutorials/data/tutorial01_data_format.ipynb
index 99d24331..dfab5910 100644
--- a/tutorials/data/tutorial01_data_format.ipynb
+++ b/tutorials/data/tutorial01_data_format.ipynb
@@ -53,7 +53,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 18,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -776,7 +776,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 25,
+   "execution_count": 10,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -785,7 +785,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 26,
+   "execution_count": 11,
    "metadata": {},
    "outputs": [
     {
@@ -884,7 +884,7 @@
        "sample_2   9               31       3.1        c"
       ]
      },
-     "execution_count": 26,
+     "execution_count": 11,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -897,7 +897,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 27,
+   "execution_count": 12,
    "metadata": {},
    "outputs": [
     {
@@ -919,7 +919,7 @@
        "        [-999.0, -999.0, -999.0]]], dtype=object)"
       ]
      },
-     "execution_count": 27,
+     "execution_count": 12,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -932,7 +932,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 28,
+   "execution_count": 13,
    "metadata": {},
    "outputs": [
     {
@@ -953,7 +953,7 @@
        " sample_2   9               31       3.1        c]"
       ]
      },
-     "execution_count": 28,
+     "execution_count": 13,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -966,7 +966,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 29,
+   "execution_count": 14,
    "metadata": {},
    "outputs": [
     {
@@ -987,7 +987,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 15,
    "metadata": {},
    "outputs": [
     {
@@ -1014,7 +1014,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 33,
+   "execution_count": 16,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -1027,7 +1027,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 34,
+   "execution_count": 17,
    "metadata": {},
    "outputs": [
     {
@@ -1112,7 +1112,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 35,
+   "execution_count": 18,
    "metadata": {},
    "outputs": [
     {
@@ -1236,7 +1236,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/data/tutorial02_datasets.ipynb b/tutorials/data/tutorial02_datasets.ipynb
index f43dda9c..38ac8e3b 100644
--- a/tutorials/data/tutorial02_datasets.ipynb
+++ b/tutorials/data/tutorial02_datasets.ipynb
@@ -2335,7 +2335,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/data/tutorial03_dataloaders.ipynb b/tutorials/data/tutorial03_dataloaders.ipynb
index 383e91b6..404d2127 100644
--- a/tutorials/data/tutorial03_dataloaders.ipynb
+++ b/tutorials/data/tutorial03_dataloaders.ipynb
@@ -84,7 +84,7 @@
     {
      "data": {
       "text/plain": [
-       "<tempor.utils.dataloaders.sine.SineDataLoader at 0x7f8155017fa0>"
+       "<tempor.utils.dataloaders.sine.SineDataLoader at 0x7fcd2dc85910>"
       ]
      },
      "execution_count": 3,
@@ -581,7 +581,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 21,
+   "execution_count": 8,
    "metadata": {},
    "outputs": [
     {
@@ -592,7 +592,13 @@
       "--------------------------------------------------------------------------------\n",
       "\n",
       "DummyTemporalPredictionDataLoader loads the following dataset:\n",
-      "\n",
+      "\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
       "TemporalPredictionDataset(\n",
       "    time_series=TimeSeriesSamples([100, *, 5]),\n",
       "    static=StaticSamples([100, 3]),\n",
@@ -2330,9 +2336,9 @@
       ],
       "text/plain": [
        "TimeSeriesSamples with data:\n",
-       "                     drug  ascites  hepatomegaly  spiders  edema  histologic   \n",
+       "                     drug  ascites  hepatomegaly  spiders  edema  histologic  \\\n",
        "sample_idx time_idx                                                            \n",
-       "1          0.569489   0.0      1.0           1.0      1.0    1.0         3.0  \\\n",
+       "1          0.569489   0.0      1.0           1.0      1.0    1.0         3.0   \n",
        "           1.095170   0.0      1.0           1.0      1.0    1.0         3.0   \n",
        "2          5.319790   0.0      1.0           1.0      1.0    1.0         2.0   \n",
        "           6.261636   0.0      1.0           1.0      1.0    1.0         2.0   \n",
@@ -2344,9 +2350,9 @@
        "           3.425145   1.0      0.0           0.0      0.0    0.0         1.0   \n",
        "           3.989158   1.0      0.0           0.0      1.0    0.0         1.0   \n",
        "\n",
-       "                     serBilir   serChol   albumin  alkaline      SGOT   \n",
+       "                     serBilir   serChol   albumin  alkaline      SGOT  \\\n",
        "sample_idx time_idx                                                     \n",
-       "1          0.569489  3.281890  0.000000 -0.894575  0.195532 -1.485263  \\\n",
+       "1          0.569489  3.281890  0.000000 -0.894575  0.195532 -1.485263   \n",
        "           1.095170  2.015877 -0.469461 -1.570646  0.285613  0.195488   \n",
        "2          5.319790  0.172710 -0.658914 -1.431455 -0.605844 -0.442126   \n",
        "           6.261636 -0.013468 -0.603657 -1.172958 -0.512364 -0.046806   \n",
@@ -2656,12 +2662,12 @@
        "    <tr>\n",
        "      <th>1</th>\n",
        "      <td>-1.001889</td>\n",
-       "      <td>-0.541524</td>\n",
+       "      <td>-0.541523</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>2</th>\n",
        "      <td>-1.070862</td>\n",
-       "      <td>-0.589326</td>\n",
+       "      <td>-0.589325</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>3</th>\n",
@@ -2683,7 +2689,7 @@
        "      <th rowspan=\"5\" valign=\"top\">39</th>\n",
        "      <th>5</th>\n",
        "      <td>0.959902</td>\n",
-       "      <td>-0.690057</td>\n",
+       "      <td>-0.690056</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>6</th>\n",
@@ -2693,12 +2699,12 @@
        "    <tr>\n",
        "      <th>7</th>\n",
        "      <td>2.233045</td>\n",
-       "      <td>0.637906</td>\n",
+       "      <td>0.637905</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>8</th>\n",
        "      <td>1.645018</td>\n",
-       "      <td>1.056963</td>\n",
+       "      <td>1.056957</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>9</th>\n",
@@ -2715,15 +2721,15 @@
        "                         k_in         p\n",
        "sample_idx time_idx                    \n",
        "0          0        -0.781441 -0.245827\n",
-       "           1        -1.001889 -0.541524\n",
-       "           2        -1.070862 -0.589326\n",
+       "           1        -1.001889 -0.541523\n",
+       "           2        -1.070862 -0.589325\n",
        "           3        -1.425115 -1.065485\n",
        "           4        -1.841006 -1.542429\n",
        "...                       ...       ...\n",
-       "39         5         0.959902 -0.690057\n",
+       "39         5         0.959902 -0.690056\n",
        "           6         1.683426 -0.128967\n",
-       "           7         2.233045  0.637906\n",
-       "           8         1.645018  1.056963\n",
+       "           7         2.233045  0.637905\n",
+       "           8         1.645018  1.056957\n",
        "           9         0.333051  1.048721\n",
        "\n",
        "[400 rows x 2 columns]"
@@ -2815,7 +2821,7 @@
        "    </tr>\n",
        "    <tr>\n",
        "      <th>9</th>\n",
-       "      <td>-0.431988</td>\n",
+       "      <td>-0.431990</td>\n",
        "    </tr>\n",
        "  </tbody>\n",
        "</table>\n",
@@ -2836,7 +2842,7 @@
        "           6        -1.495843\n",
        "           7        -1.193632\n",
        "           8        -0.850845\n",
-       "           9        -0.431988\n",
+       "           9        -0.431990\n",
        "\n",
        "[400 rows x 1 columns]"
       ]
@@ -3521,6 +3527,663 @@
      },
      "metadata": {},
      "output_type": "display_data"
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "\n",
+      "--------------------------------------------------------------------------------\n",
+      "\n",
+      "UCIDiabetesDataLoader loads the following dataset:\n",
+      "\n",
+      "Downloading file from URL: https://archive.ics.uci.edu/ml/machine-learning-databases/diabetes/Index\n",
+      "Downloading file from URL: https://archive.ics.uci.edu/ml/machine-learning-databases/diabetes/README\n",
+      "Downloading file from URL: https://archive.ics.uci.edu/ml/machine-learning-databases/diabetes/diabetes-data.tar.Z\n",
+      "TemporalPredictionDataset(\n",
+      "    time_series=TimeSeriesSamples([70, *, 18]),\n",
+      "    predictive=TemporalPredictionTaskData(\n",
+      "        targets=TimeSeriesSamples([70, *, 1])\n",
+      "    )\n",
+      ")\n",
+      "This contains:\n",
+      "\n",
+      "time_series:\n"
+     ]
+    },
+    {
+     "data": {
+      "text/html": [
+       "<p><span style=\"font-family: monospace;\">TimeSeriesSamples</span> with data:</p><div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th>typical_exercise_activity</th>\n",
+       "      <th>unspecified_special_event</th>\n",
+       "      <th>ultralente_insulin_dose</th>\n",
+       "      <th>more-than-usual_exercise_activity</th>\n",
+       "      <th>post-lunch_blood_glucose_measurement</th>\n",
+       "      <th>less-than-usual_meal_ingestion</th>\n",
+       "      <th>regular_insulin_dose</th>\n",
+       "      <th>post-breakfast_blood_glucose_measurement</th>\n",
+       "      <th>pre-breakfast_blood_glucose_measurement</th>\n",
+       "      <th>less-than-usual_exercise_activity</th>\n",
+       "      <th>pre-supper_blood_glucose_measurement</th>\n",
+       "      <th>pre-lunch_blood_glucose_measurement</th>\n",
+       "      <th>more-than-usual_meal_ingestion</th>\n",
+       "      <th>post-supper_blood_glucose_measurement</th>\n",
+       "      <th>unspecified_blood_glucose_measurement</th>\n",
+       "      <th>nph_insulin_dose</th>\n",
+       "      <th>pre-snack_blood_glucose_measurement</th>\n",
+       "      <th>typical_meal_ingestion</th>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>sample_idx</th>\n",
+       "      <th>time_idx</th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th rowspan=\"5\" valign=\"top\">0</th>\n",
+       "      <th>0</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>9.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>100.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>13.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>7.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>119.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>123.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>10.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>216.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>13.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>2.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>...</th>\n",
+       "      <th>...</th>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th rowspan=\"5\" valign=\"top\">69</th>\n",
+       "      <th>146</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>145.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>147</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>1.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>259.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>7.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>148</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>7.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>149</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>7.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>150</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>7.0</td>\n",
+       "      <td>NaN</td>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "<p>18199 rows × 18 columns</p>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "TimeSeriesSamples with data:\n",
+       "                     typical_exercise_activity  unspecified_special_event  \\\n",
+       "sample_idx time_idx                                                         \n",
+       "0          0                               NaN                        NaN   \n",
+       "           1                               NaN                        NaN   \n",
+       "           2                               NaN                        NaN   \n",
+       "           3                               NaN                        NaN   \n",
+       "           4                               NaN                        NaN   \n",
+       "...                                        ...                        ...   \n",
+       "69         146                             NaN                        NaN   \n",
+       "           147                             NaN                        NaN   \n",
+       "           148                             NaN                        NaN   \n",
+       "           149                             NaN                        NaN   \n",
+       "           150                             NaN                        NaN   \n",
+       "\n",
+       "                     ultralente_insulin_dose  \\\n",
+       "sample_idx time_idx                            \n",
+       "0          0                             NaN   \n",
+       "           1                             NaN   \n",
+       "           2                             NaN   \n",
+       "           3                             NaN   \n",
+       "           4                             NaN   \n",
+       "...                                      ...   \n",
+       "69         146                           NaN   \n",
+       "           147                           NaN   \n",
+       "           148                           NaN   \n",
+       "           149                           NaN   \n",
+       "           150                           NaN   \n",
+       "\n",
+       "                     more-than-usual_exercise_activity  \\\n",
+       "sample_idx time_idx                                      \n",
+       "0          0                                       NaN   \n",
+       "           1                                       NaN   \n",
+       "           2                                       NaN   \n",
+       "           3                                       NaN   \n",
+       "           4                                       NaN   \n",
+       "...                                                ...   \n",
+       "69         146                                     NaN   \n",
+       "           147                                     NaN   \n",
+       "           148                                     NaN   \n",
+       "           149                                     NaN   \n",
+       "           150                                     NaN   \n",
+       "\n",
+       "                     post-lunch_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                         \n",
+       "0          0                                          NaN   \n",
+       "           1                                          NaN   \n",
+       "           2                                          NaN   \n",
+       "           3                                          NaN   \n",
+       "           4                                          NaN   \n",
+       "...                                                   ...   \n",
+       "69         146                                        NaN   \n",
+       "           147                                        NaN   \n",
+       "           148                                        NaN   \n",
+       "           149                                        NaN   \n",
+       "           150                                        NaN   \n",
+       "\n",
+       "                     less-than-usual_meal_ingestion  regular_insulin_dose  \\\n",
+       "sample_idx time_idx                                                         \n",
+       "0          0                                    NaN                   9.0   \n",
+       "           1                                    NaN                   7.0   \n",
+       "           2                                    NaN                   NaN   \n",
+       "           3                                    NaN                  10.0   \n",
+       "           4                                    NaN                   2.0   \n",
+       "...                                             ...                   ...   \n",
+       "69         146                                  NaN                   NaN   \n",
+       "           147                                  NaN                   1.0   \n",
+       "           148                                  NaN                   NaN   \n",
+       "           149                                  NaN                   NaN   \n",
+       "           150                                  NaN                   NaN   \n",
+       "\n",
+       "                     post-breakfast_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                             \n",
+       "0          0                                              NaN   \n",
+       "           1                                              NaN   \n",
+       "           2                                              NaN   \n",
+       "           3                                              NaN   \n",
+       "           4                                              NaN   \n",
+       "...                                                       ...   \n",
+       "69         146                                            NaN   \n",
+       "           147                                            NaN   \n",
+       "           148                                            NaN   \n",
+       "           149                                            NaN   \n",
+       "           150                                            NaN   \n",
+       "\n",
+       "                     pre-breakfast_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                            \n",
+       "0          0                                           100.0   \n",
+       "           1                                             NaN   \n",
+       "           2                                             NaN   \n",
+       "           3                                           216.0   \n",
+       "           4                                             NaN   \n",
+       "...                                                      ...   \n",
+       "69         146                                           NaN   \n",
+       "           147                                         259.0   \n",
+       "           148                                           NaN   \n",
+       "           149                                           NaN   \n",
+       "           150                                           NaN   \n",
+       "\n",
+       "                     less-than-usual_exercise_activity  \\\n",
+       "sample_idx time_idx                                      \n",
+       "0          0                                       NaN   \n",
+       "           1                                       NaN   \n",
+       "           2                                       NaN   \n",
+       "           3                                       NaN   \n",
+       "           4                                       NaN   \n",
+       "...                                                ...   \n",
+       "69         146                                     NaN   \n",
+       "           147                                     NaN   \n",
+       "           148                                     NaN   \n",
+       "           149                                     NaN   \n",
+       "           150                                     NaN   \n",
+       "\n",
+       "                     pre-supper_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                         \n",
+       "0          0                                          NaN   \n",
+       "           1                                        119.0   \n",
+       "           2                                          NaN   \n",
+       "           3                                          NaN   \n",
+       "           4                                          NaN   \n",
+       "...                                                   ...   \n",
+       "69         146                                        NaN   \n",
+       "           147                                        NaN   \n",
+       "           148                                        NaN   \n",
+       "           149                                        NaN   \n",
+       "           150                                        NaN   \n",
+       "\n",
+       "                     pre-lunch_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                        \n",
+       "0          0                                         NaN   \n",
+       "           1                                         NaN   \n",
+       "           2                                         NaN   \n",
+       "           3                                         NaN   \n",
+       "           4                                         NaN   \n",
+       "...                                                  ...   \n",
+       "69         146                                       NaN   \n",
+       "           147                                       NaN   \n",
+       "           148                                       NaN   \n",
+       "           149                                       NaN   \n",
+       "           150                                       NaN   \n",
+       "\n",
+       "                     more-than-usual_meal_ingestion  \\\n",
+       "sample_idx time_idx                                   \n",
+       "0          0                                    NaN   \n",
+       "           1                                    NaN   \n",
+       "           2                                    NaN   \n",
+       "           3                                    NaN   \n",
+       "           4                                    NaN   \n",
+       "...                                             ...   \n",
+       "69         146                                  NaN   \n",
+       "           147                                  NaN   \n",
+       "           148                                  NaN   \n",
+       "           149                                  NaN   \n",
+       "           150                                  NaN   \n",
+       "\n",
+       "                     post-supper_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                          \n",
+       "0          0                                           NaN   \n",
+       "           1                                           NaN   \n",
+       "           2                                           NaN   \n",
+       "           3                                           NaN   \n",
+       "           4                                           NaN   \n",
+       "...                                                    ...   \n",
+       "69         146                                         NaN   \n",
+       "           147                                         NaN   \n",
+       "           148                                         NaN   \n",
+       "           149                                         NaN   \n",
+       "           150                                         NaN   \n",
+       "\n",
+       "                     unspecified_blood_glucose_measurement  nph_insulin_dose  \\\n",
+       "sample_idx time_idx                                                            \n",
+       "0          0                                           NaN              13.0   \n",
+       "           1                                           NaN               NaN   \n",
+       "           2                                         123.0               NaN   \n",
+       "           3                                           NaN              13.0   \n",
+       "           4                                           NaN               NaN   \n",
+       "...                                                    ...               ...   \n",
+       "69         146                                       145.0               NaN   \n",
+       "           147                                         NaN               7.0   \n",
+       "           148                                         NaN               7.0   \n",
+       "           149                                         NaN               7.0   \n",
+       "           150                                         NaN               7.0   \n",
+       "\n",
+       "                     pre-snack_blood_glucose_measurement  \\\n",
+       "sample_idx time_idx                                        \n",
+       "0          0                                         NaN   \n",
+       "           1                                         NaN   \n",
+       "           2                                         NaN   \n",
+       "           3                                         NaN   \n",
+       "           4                                         NaN   \n",
+       "...                                                  ...   \n",
+       "69         146                                       NaN   \n",
+       "           147                                       NaN   \n",
+       "           148                                       NaN   \n",
+       "           149                                       NaN   \n",
+       "           150                                       NaN   \n",
+       "\n",
+       "                     typical_meal_ingestion  \n",
+       "sample_idx time_idx                          \n",
+       "0          0                            NaN  \n",
+       "           1                            NaN  \n",
+       "           2                            NaN  \n",
+       "           3                            NaN  \n",
+       "           4                            NaN  \n",
+       "...                                     ...  \n",
+       "69         146                          NaN  \n",
+       "           147                          NaN  \n",
+       "           148                          NaN  \n",
+       "           149                          NaN  \n",
+       "           150                          NaN  \n",
+       "\n",
+       "[18199 rows x 18 columns]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "predictive.targets:\n"
+     ]
+    },
+    {
+     "data": {
+      "text/html": [
+       "<p><span style=\"font-family: monospace;\">TimeSeriesSamples</span> with data:</p><div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "      <th>hypoglycemic_symptoms</th>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>sample_idx</th>\n",
+       "      <th>time_idx</th>\n",
+       "      <th></th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th rowspan=\"5\" valign=\"top\">0</th>\n",
+       "      <th>0</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>...</th>\n",
+       "      <th>...</th>\n",
+       "      <td>...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th rowspan=\"5\" valign=\"top\">69</th>\n",
+       "      <th>146</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>147</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>148</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>149</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>150</th>\n",
+       "      <td>NaN</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "<p>18199 rows × 1 columns</p>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "TimeSeriesSamples with data:\n",
+       "                     hypoglycemic_symptoms\n",
+       "sample_idx time_idx                       \n",
+       "0          0                           NaN\n",
+       "           1                           NaN\n",
+       "           2                           NaN\n",
+       "           3                           NaN\n",
+       "           4                           NaN\n",
+       "...                                    ...\n",
+       "69         146                         NaN\n",
+       "           147                         NaN\n",
+       "           148                         NaN\n",
+       "           149                         NaN\n",
+       "           150                         NaN\n",
+       "\n",
+       "[18199 rows x 1 columns]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     }
    ],
    "source": [
@@ -3592,7 +4255,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/data/tutorial04_data_splitting.ipynb b/tutorials/data/tutorial04_data_splitting.ipynb
index f6ea5c50..745a6a39 100644
--- a/tutorials/data/tutorial04_data_splitting.ipynb
+++ b/tutorials/data/tutorial04_data_splitting.ipynb
@@ -19,7 +19,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -216,7 +216,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/extending/tutorial01_custom_plugin.ipynb b/tutorials/extending/tutorial01_custom_plugin.ipynb
index 23400e2f..0d43c979 100644
--- a/tutorials/extending/tutorial01_custom_plugin.ipynb
+++ b/tutorials/extending/tutorial01_custom_plugin.ipynb
@@ -19,7 +19,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -71,6 +71,8 @@
        " 'prediction.one_off.regression',\n",
        " 'prediction.temporal.classification',\n",
        " 'prediction.temporal.regression',\n",
+       " 'preprocessing.encoding.static',\n",
+       " 'preprocessing.encoding.temporal',\n",
        " 'preprocessing.imputation.static',\n",
        " 'preprocessing.imputation.temporal',\n",
        " 'preprocessing.nop',\n",
@@ -120,6 +122,7 @@
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"font-weight: bold\">}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'encoding'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_onehot_encoder'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_onehot_encoder'</span><span style=\"font-weight: bold\">]}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'imputation'</span>: <span style=\"font-weight: bold\">{</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_tabular_imputer'</span><span style=\"font-weight: bold\">]</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ffill'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_tabular_imputer'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'bfill'</span><span style=\"font-weight: bold\">]</span>\n",
@@ -148,6 +151,7 @@
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
        "\u001b[2;32m│   \u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   \u001b[0m\u001b[32m'preprocessing'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "\u001b[2;32m│   │   \u001b[0m\u001b[32m'encoding'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'imputation'\u001b[0m: \u001b[1m{\u001b[0m\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_tabular_imputer'\u001b[0m\u001b[1m]\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ffill'\u001b[0m, \u001b[32m'ts_tabular_imputer'\u001b[0m, \u001b[32m'bfill'\u001b[0m\u001b[1m]\u001b[0m\n",
@@ -208,6 +212,8 @@
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'prediction.one_off.regression'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.prediction.one_off.regression.BaseOneOffRegressor'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'prediction.temporal.classification'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.prediction.temporal.classification.BaseTemporalClassifier'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'prediction.temporal.regression'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.prediction.temporal.regression.BaseTemporalRegressor'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
+       "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.encoding.static'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.preprocessing.encoding._base.BaseEncoder'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
+       "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.encoding.temporal'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.preprocessing.encoding._base.BaseEncoder'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.imputation.static'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.preprocessing.imputation._base.BaseImputer'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.imputation.temporal'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.preprocessing.imputation._base.BaseImputer'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
        "<span style=\"color: #000000; text-decoration-color: #000000\">    </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.nop'</span><span style=\"color: #000000; text-decoration-color: #000000\">: &lt;class </span><span style=\"color: #008000; text-decoration-color: #008000\">'tempor.plugins.core._base_transformer.BaseTransformer'</span><span style=\"color: #000000; text-decoration-color: #000000\">&gt;,</span>\n",
@@ -226,6 +232,8 @@
        "\u001b[39m    \u001b[0m\u001b[32m'prediction.one_off.regression'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.prediction.one_off.regression.BaseOneOffRegressor'\u001b[0m\u001b[39m>,\u001b[0m\n",
        "\u001b[39m    \u001b[0m\u001b[32m'prediction.temporal.classification'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.prediction.temporal.classification.BaseTemporalClassifier'\u001b[0m\u001b[39m>,\u001b[0m\n",
        "\u001b[39m    \u001b[0m\u001b[32m'prediction.temporal.regression'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.prediction.temporal.regression.BaseTemporalRegressor'\u001b[0m\u001b[39m>,\u001b[0m\n",
+       "\u001b[39m    \u001b[0m\u001b[32m'preprocessing.encoding.static'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.preprocessing.encoding._base.BaseEncoder'\u001b[0m\u001b[39m>,\u001b[0m\n",
+       "\u001b[39m    \u001b[0m\u001b[32m'preprocessing.encoding.temporal'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.preprocessing.encoding._base.BaseEncoder'\u001b[0m\u001b[39m>,\u001b[0m\n",
        "\u001b[39m    \u001b[0m\u001b[32m'preprocessing.imputation.static'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.preprocessing.imputation._base.BaseImputer'\u001b[0m\u001b[39m>,\u001b[0m\n",
        "\u001b[39m    \u001b[0m\u001b[32m'preprocessing.imputation.temporal'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.preprocessing.imputation._base.BaseImputer'\u001b[0m\u001b[39m>,\u001b[0m\n",
        "\u001b[39m    \u001b[0m\u001b[32m'preprocessing.nop'\u001b[0m\u001b[39m: <class \u001b[0m\u001b[32m'tempor.plugins.core._base_transformer.BaseTransformer'\u001b[0m\u001b[39m>,\u001b[0m\n",
@@ -477,6 +485,7 @@
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"font-weight: bold\">}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'encoding'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_onehot_encoder'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_onehot_encoder'</span><span style=\"font-weight: bold\">]}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'imputation'</span>: <span style=\"font-weight: bold\">{</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_tabular_imputer'</span><span style=\"font-weight: bold\">]</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ffill'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_tabular_imputer'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'bfill'</span><span style=\"font-weight: bold\">]</span>\n",
@@ -511,6 +520,7 @@
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
        "\u001b[2;32m│   \u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   \u001b[0m\u001b[32m'preprocessing'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "\u001b[2;32m│   │   \u001b[0m\u001b[32m'encoding'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'imputation'\u001b[0m: \u001b[1m{\u001b[0m\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_tabular_imputer'\u001b[0m\u001b[1m]\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ffill'\u001b[0m, \u001b[32m'ts_tabular_imputer'\u001b[0m, \u001b[32m'bfill'\u001b[0m\u001b[1m]\u001b[0m\n",
@@ -572,6 +582,7 @@
       "MyClassifierClassifier(\n",
       "    name='my_classifier',\n",
       "    category='prediction.one_off.classification',\n",
+      "    plugin_type='method',\n",
       "    params={'some_parameter': 1, 'other_parameter': 0.5}\n",
       ")\n"
      ]
@@ -752,7 +763,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/usage/tutorial01_plugins.ipynb b/tutorials/usage/tutorial01_plugins.ipynb
index 62eb46b0..37d9f903 100644
--- a/tutorials/usage/tutorial01_plugins.ipynb
+++ b/tutorials/usage/tutorial01_plugins.ipynb
@@ -20,7 +20,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": null,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -50,7 +50,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [
     {
@@ -78,7 +78,7 @@
       "        'window_size': 1,\n",
       "        'device': None,\n",
       "        'dataloader_sampler': None,\n",
-      "        'dropout': 0.0,\n",
+      "        'dropout': 0,\n",
       "        'nonlin': 'relu',\n",
       "        'random_state': 0,\n",
       "        'clipping_value': 1,\n",
@@ -112,7 +112,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 3,
    "metadata": {},
    "outputs": [
     {
@@ -140,7 +140,7 @@
       "        'window_size': 1,\n",
       "        'device': None,\n",
       "        'dataloader_sampler': None,\n",
-      "        'dropout': 0.0,\n",
+      "        'dropout': 0,\n",
       "        'nonlin': 'relu',\n",
       "        'random_state': 0,\n",
       "        'clipping_value': 1,\n",
@@ -186,7 +186,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 4,
    "metadata": {},
    "outputs": [
     {
@@ -201,6 +201,7 @@
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
        "    <span style=\"font-weight: bold\">}</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'encoding'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_onehot_encoder'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_onehot_encoder'</span><span style=\"font-weight: bold\">]}</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'imputation'</span>: <span style=\"font-weight: bold\">{</span>\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_tabular_imputer'</span><span style=\"font-weight: bold\">]</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ffill'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_tabular_imputer'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'bfill'</span><span style=\"font-weight: bold\">]</span>\n",
@@ -229,6 +230,7 @@
        "        \u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
        "    \u001b[1m}\u001b[0m,\n",
        "    \u001b[32m'preprocessing'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "        \u001b[32m'encoding'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
        "        \u001b[32m'imputation'\u001b[0m: \u001b[1m{\u001b[0m\n",
        "            \u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_tabular_imputer'\u001b[0m\u001b[1m]\u001b[0m,\n",
        "            \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ffill'\u001b[0m, \u001b[32m'ts_tabular_imputer'\u001b[0m, \u001b[32m'bfill'\u001b[0m\u001b[1m]\u001b[0m\n",
@@ -270,14 +272,14 @@
    "source": [
     "Note that plugin categories are hierarchical (nested).\n",
     "\n",
-    "To quickly view the plugin fully qualified name (`fqn`) for all plugins, use `plugin_loader.list_fqns()`.\n",
+    "To quickly view the plugin fully qualified name (`fqn`) for all plugins, use `plugin_loader.list_full_names()`.\n",
     "\n",
     "These are the names to use in `plugin_loader.{get,get_class}` calls."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 5,
    "metadata": {},
    "outputs": [
     {
@@ -293,6 +295,8 @@
        " 'prediction.one_off.regression.cde_regressor',\n",
        " 'prediction.temporal.classification.seq2seq_classifier',\n",
        " 'prediction.temporal.regression.seq2seq_regressor',\n",
+       " 'preprocessing.encoding.static.static_onehot_encoder',\n",
+       " 'preprocessing.encoding.temporal.ts_onehot_encoder',\n",
        " 'preprocessing.imputation.static.static_tabular_imputer',\n",
        " 'preprocessing.imputation.temporal.ffill',\n",
        " 'preprocessing.imputation.temporal.ts_tabular_imputer',\n",
@@ -310,13 +314,132 @@
        " 'treatments.temporal.regression.crn_regressor']"
       ]
      },
-     "execution_count": 10,
+     "execution_count": 5,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "plugin_loader.list_full_names()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### A note on `Plugin` types\n",
+    "\n",
+    "All the `Plugin`s so far have been of the `\"method\"` *plugin type*. This is the default plugin type.\n",
+    "\n",
+    "TemporAI has other plugin types. You can list plugin types as below."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['method']"
+      ]
+     },
+     "execution_count": 6,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "plugin_loader.list_fqns()"
+    "plugin_loader.list_plugin_types()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "You can list all plugins across all the different types by passing `plugin_type=\"all\"`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">{</span>\n",
+       "    <span style=\"color: #008000; text-decoration-color: #008000\">'method'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'prediction'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'one_off'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'cde_classifier'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ode_classifier'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'nn_classifier'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'laplace_ode_classifier'</span><span style=\"font-weight: bold\">]</span>,\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'laplace_ode_regressor'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'nn_regressor'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ode_regressor'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'cde_regressor'</span><span style=\"font-weight: bold\">]</span>\n",
+       "            <span style=\"font-weight: bold\">}</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
+       "        <span style=\"font-weight: bold\">}</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'encoding'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_onehot_encoder'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_onehot_encoder'</span><span style=\"font-weight: bold\">]}</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'imputation'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_tabular_imputer'</span><span style=\"font-weight: bold\">]</span>,\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ffill'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_tabular_imputer'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'bfill'</span><span style=\"font-weight: bold\">]</span>\n",
+       "            <span style=\"font-weight: bold\">}</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'nop'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'nop_transformer'</span><span style=\"font-weight: bold\">]</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'scaling'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_minmax_scaler'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'static_standard_scaler'</span><span style=\"font-weight: bold\">]</span>,\n",
+       "                <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_minmax_scaler'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_standard_scaler'</span><span style=\"font-weight: bold\">]</span>\n",
+       "            <span style=\"font-weight: bold\">}</span>\n",
+       "        <span style=\"font-weight: bold\">}</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'time_to_event'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_coxph'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_xgb'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'dynamic_deephit'</span><span style=\"font-weight: bold\">]</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'treatments'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'one_off'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'synctwin_regressor'</span><span style=\"font-weight: bold\">]}</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'crn_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'crn_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
+       "        <span style=\"font-weight: bold\">}</span>\n",
+       "    <span style=\"font-weight: bold\">}</span>\n",
+       "<span style=\"font-weight: bold\">}</span>\n",
+       "</pre>\n"
+      ],
+      "text/plain": [
+       "\u001b[1m{\u001b[0m\n",
+       "    \u001b[32m'method'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "        \u001b[32m'prediction'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "            \u001b[32m'one_off'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "                \u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'cde_classifier'\u001b[0m, \u001b[32m'ode_classifier'\u001b[0m, \u001b[32m'nn_classifier'\u001b[0m, \u001b[32m'laplace_ode_classifier'\u001b[0m\u001b[1m]\u001b[0m,\n",
+       "                \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'laplace_ode_regressor'\u001b[0m, \u001b[32m'nn_regressor'\u001b[0m, \u001b[32m'ode_regressor'\u001b[0m, \u001b[32m'cde_regressor'\u001b[0m\u001b[1m]\u001b[0m\n",
+       "            \u001b[1m}\u001b[0m,\n",
+       "            \u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
+       "        \u001b[1m}\u001b[0m,\n",
+       "        \u001b[32m'preprocessing'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "            \u001b[32m'encoding'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
+       "            \u001b[32m'imputation'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "                \u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_tabular_imputer'\u001b[0m\u001b[1m]\u001b[0m,\n",
+       "                \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ffill'\u001b[0m, \u001b[32m'ts_tabular_imputer'\u001b[0m, \u001b[32m'bfill'\u001b[0m\u001b[1m]\u001b[0m\n",
+       "            \u001b[1m}\u001b[0m,\n",
+       "            \u001b[32m'nop'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'nop_transformer'\u001b[0m\u001b[1m]\u001b[0m,\n",
+       "            \u001b[32m'scaling'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "                \u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_minmax_scaler'\u001b[0m, \u001b[32m'static_standard_scaler'\u001b[0m\u001b[1m]\u001b[0m,\n",
+       "                \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_minmax_scaler'\u001b[0m, \u001b[32m'ts_standard_scaler'\u001b[0m\u001b[1m]\u001b[0m\n",
+       "            \u001b[1m}\u001b[0m\n",
+       "        \u001b[1m}\u001b[0m,\n",
+       "        \u001b[32m'time_to_event'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_coxph'\u001b[0m, \u001b[32m'ts_xgb'\u001b[0m, \u001b[32m'dynamic_deephit'\u001b[0m\u001b[1m]\u001b[0m,\n",
+       "        \u001b[32m'treatments'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "            \u001b[32m'one_off'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'synctwin_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
+       "            \u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'crn_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'crn_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
+       "        \u001b[1m}\u001b[0m\n",
+       "    \u001b[1m}\u001b[0m\n",
+       "\u001b[1m}\u001b[0m\n"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "from rich.pretty import pprint\n",
+    "\n",
+    "plugins_across_all_types = plugin_loader.list(plugin_type=\"all\")\n",
+    "\n",
+    "pprint(plugins_across_all_types, indent_guides=False)"
    ]
   },
   {
@@ -359,7 +482,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/usage/tutorial02_imputation.ipynb b/tutorials/usage/tutorial02_imputation.ipynb
index 91d67389..f91d80a4 100644
--- a/tutorials/usage/tutorial02_imputation.ipynb
+++ b/tutorials/usage/tutorial02_imputation.ipynb
@@ -19,7 +19,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
+   "execution_count": null,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -41,7 +41,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 5,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [
     {
@@ -51,7 +51,7 @@
        " 'temporal': ['ffill', 'ts_tabular_imputer', 'bfill']}"
       ]
      },
-     "execution_count": 5,
+     "execution_count": 2,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -72,9 +72,16 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 3,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 | Iteration imputation: select_model_by_column: True, select_model_by_iteration: True\n"
+     ]
+    },
     {
      "name": "stdout",
      "output_type": "stream",
@@ -87,6 +94,7 @@
       "StaticTabularImputer(\n",
       "    name='static_tabular_imputer',\n",
       "    category='preprocessing.imputation.static',\n",
+      "    plugin_type='method',\n",
       "    params={\n",
       "        'imputer': 'ice',\n",
       "        'random_state': 0,\n",
@@ -109,7 +117,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 4,
    "metadata": {},
    "outputs": [
     {
@@ -255,7 +263,7 @@
        "[100 rows x 4 columns]"
       ]
      },
-     "execution_count": 7,
+     "execution_count": 4,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -270,9 +278,56 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 5,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > HyperImpute using inner optimization\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 0\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.22005514968324613 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 1\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21670750510884584 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 2\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.2166465658117811 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 3\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.2166456843686172 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 4\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 5\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 6\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 7\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 8\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 9\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 10\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 0 <-- score -0.23109777030617995 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>> Column 1 <-- score -0.21664567863448503 <-- Model linear_regression\n",
+      "2023-10-07 22:18:00 | INFO     | hyperimpute.logger:log_and_print:65 |      >>>> Early stopping on objective diff iteration\n"
+     ]
+    },
     {
      "name": "stdout",
      "output_type": "stream",
@@ -416,7 +471,7 @@
        "[100 rows x 4 columns]"
       ]
      },
-     "execution_count": 8,
+     "execution_count": 5,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -441,7 +496,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 6,
    "metadata": {},
    "outputs": [
     {
@@ -456,6 +511,7 @@
       "BFillImputer(\n",
       "    name='bfill',\n",
       "    category='preprocessing.imputation.temporal',\n",
+      "    plugin_type='method',\n",
       "    params={}\n",
       ")\n"
      ]
@@ -474,7 +530,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 7,
    "metadata": {},
    "outputs": [
     {
@@ -638,7 +694,7 @@
        "[1000 rows x 5 columns]"
       ]
      },
-     "execution_count": 10,
+     "execution_count": 7,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -653,7 +709,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 8,
    "metadata": {},
    "outputs": [
     {
@@ -817,7 +873,7 @@
        "[1000 rows x 5 columns]"
       ]
      },
-     "execution_count": 11,
+     "execution_count": 8,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -872,7 +928,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/usage/tutorial03_scaling.ipynb b/tutorials/usage/tutorial03_scaling.ipynb
index 81cdb048..737d1d28 100644
--- a/tutorials/usage/tutorial03_scaling.ipynb
+++ b/tutorials/usage/tutorial03_scaling.ipynb
@@ -87,7 +87,8 @@
       "StaticMinMaxScaler(\n",
       "    name='static_minmax_scaler',\n",
       "    category='preprocessing.scaling.static',\n",
-      "    params={}\n",
+      "    plugin_type='method',\n",
+      "    params={'feature_range': [0, 1], 'clip': False}\n",
       ")\n"
      ]
     }
@@ -578,7 +579,8 @@
       "TimeSeriesStandardScaler(\n",
       "    name='ts_standard_scaler',\n",
       "    category='preprocessing.scaling.temporal',\n",
-      "    params={}\n",
+      "    plugin_type='method',\n",
+      "    params={'with_mean': True, 'with_std': True}\n",
       ")\n"
      ]
     }
@@ -1132,7 +1134,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/usage/tutorial04_prediction.ipynb b/tutorials/usage/tutorial04_prediction.ipynb
index fda30202..242770bc 100644
--- a/tutorials/usage/tutorial04_prediction.ipynb
+++ b/tutorials/usage/tutorial04_prediction.ipynb
@@ -106,6 +106,7 @@
       "NeuralNetClassifier(\n",
       "    name='nn_classifier',\n",
       "    category='prediction.one_off.classification',\n",
+      "    plugin_type='method',\n",
       "    params={\n",
       "        'n_static_units_hidden': 100,\n",
       "        'n_static_layers_hidden': 2,\n",
@@ -120,7 +121,7 @@
       "        'window_size': 1,\n",
       "        'device': None,\n",
       "        'dataloader_sampler': None,\n",
-      "        'dropout': 0.0,\n",
+      "        'dropout': 0,\n",
       "        'nonlin': 'relu',\n",
       "        'random_state': 0,\n",
       "        'clipping_value': 1,\n",
@@ -259,12 +260,24 @@
    "execution_count": 5,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:20:14 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.68824702501297, validation loss: 0.6883962154388428\n",
+      "2023-10-07 22:20:14 | INFO     | tempor.models.ts_model:_train:379 | Epoch:10| train loss: 0.6999298334121704, validation loss: 0.6879696846008301\n",
+      "2023-10-07 22:20:15 | INFO     | tempor.models.ts_model:_train:379 | Epoch:20| train loss: 0.6818332672119141, validation loss: 0.6867876648902893\n",
+      "2023-10-07 22:20:15 | INFO     | tempor.models.ts_model:_train:379 | Epoch:30| train loss: 0.6943979263305664, validation loss: 0.685184121131897\n",
+      "2023-10-07 22:20:15 | INFO     | tempor.models.ts_model:_train:379 | Epoch:40| train loss: 0.6284184455871582, validation loss: 0.6934055089950562\n"
+     ]
+    },
     {
      "data": {
       "text/plain": [
        "NeuralNetClassifier(\n",
        "    name='nn_classifier',\n",
        "    category='prediction.one_off.classification',\n",
+       "    plugin_type='method',\n",
        "    params={\n",
        "        'n_static_units_hidden': 100,\n",
        "        'n_static_layers_hidden': 2,\n",
@@ -279,7 +292,7 @@
        "        'window_size': 1,\n",
        "        'device': None,\n",
        "        'dataloader_sampler': None,\n",
-       "        'dropout': 0.0,\n",
+       "        'dropout': 0,\n",
        "        'nonlin': 'relu',\n",
        "        'random_state': 0,\n",
        "        'clipping_value': 1,\n",
@@ -441,6 +454,7 @@
       "Seq2seqRegressor(\n",
       "    name='seq2seq_regressor',\n",
       "    category='prediction.temporal.regression',\n",
+      "    plugin_type='method',\n",
       "    params={\n",
       "        'encoder_rnn_type': 'LSTM',\n",
       "        'encoder_hidden_size': 100,\n",
@@ -826,7 +840,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/usage/tutorial05_time_to_event.ipynb b/tutorials/usage/tutorial05_time_to_event.ipynb
index d90237d6..c31b340e 100644
--- a/tutorials/usage/tutorial05_time_to_event.ipynb
+++ b/tutorials/usage/tutorial05_time_to_event.ipynb
@@ -89,6 +89,7 @@
       "DynamicDeepHitTimeToEventAnalysis(\n",
       "    name='dynamic_deephit',\n",
       "    category='time_to_event',\n",
+      "    plugin_type='method',\n",
       "    params={\n",
       "        'n_iter': 50,\n",
       "        'batch_size': 100,\n",
@@ -102,6 +103,7 @@
       "        'sigma': 0.21,\n",
       "        'dropout': 0.06,\n",
       "        'device': 'cpu',\n",
+      "        'val_size': 0.1,\n",
       "        'patience': 20,\n",
       "        'output_mode': 'MLP',\n",
       "        'random_state': 0\n",
@@ -244,6 +246,7 @@
        "DynamicDeepHitTimeToEventAnalysis(\n",
        "    name='dynamic_deephit',\n",
        "    category='time_to_event',\n",
+       "    plugin_type='method',\n",
        "    params={\n",
        "        'n_iter': 50,\n",
        "        'batch_size': 100,\n",
@@ -257,6 +260,7 @@
        "        'sigma': 0.21,\n",
        "        'dropout': 0.06,\n",
        "        'device': 'cpu',\n",
+       "        'val_size': 0.1,\n",
        "        'patience': 20,\n",
        "        'output_mode': 'MLP',\n",
        "        'random_state': 0\n",
@@ -276,7 +280,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 6,
    "metadata": {},
    "outputs": [
     {
@@ -349,7 +353,7 @@
        "    <tr>\n",
        "      <th rowspan=\"3\" valign=\"top\">312</th>\n",
        "      <th>0.25</th>\n",
-       "      <td>0.248833</td>\n",
+       "      <td>0.248834</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>0.50</th>\n",
@@ -376,14 +380,14 @@
        "...                         ...\n",
        "311        0.50        0.039302\n",
        "           0.75        0.048346\n",
-       "312        0.25        0.248833\n",
+       "312        0.25        0.248834\n",
        "           0.50        0.390042\n",
        "           0.75        0.444533\n",
        "\n",
        "[936 rows x 1 columns]"
       ]
      },
-     "execution_count": 12,
+     "execution_count": 6,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -446,7 +450,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/usage/tutorial06_treatments.ipynb b/tutorials/usage/tutorial06_treatments.ipynb
index 9f72ce72..35bb3f16 100644
--- a/tutorials/usage/tutorial06_treatments.ipynb
+++ b/tutorials/usage/tutorial06_treatments.ipynb
@@ -107,6 +107,7 @@
       "CRNTreatmentsRegressor(\n",
       "    name='crn_regressor',\n",
       "    category='treatments.temporal.regression',\n",
+      "    plugin_type='method',\n",
       "    params={\n",
       "        'encoder_rnn_type': 'LSTM',\n",
       "        'encoder_hidden_size': 100,\n",
@@ -414,47 +415,47 @@
       "Preparing data for decoder training...\n",
       "Preparing data for decoder training DONE.\n",
       "=== Training stage: 1. Train encoder ===\n",
-      "Epoch: 0, Prediction Loss: 76.050, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 76.050\n",
-      "Epoch: 1, Prediction Loss: 37.508, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 37.508\n",
-      "Epoch: 2, Prediction Loss: 21.953, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 21.953\n",
-      "Epoch: 3, Prediction Loss: 18.895, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 18.895\n",
-      "Epoch: 4, Prediction Loss: 19.568, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 19.568\n",
-      "Epoch: 5, Prediction Loss: 16.534, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 16.534\n",
-      "Epoch: 6, Prediction Loss: 12.039, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 12.039\n",
-      "Epoch: 7, Prediction Loss: 10.009, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 10.009\n",
-      "Epoch: 8, Prediction Loss: 8.666, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 8.666\n",
-      "Epoch: 9, Prediction Loss: 6.788, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 6.788\n",
-      "Epoch: 10, Prediction Loss: 5.674, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 5.674\n",
-      "Epoch: 11, Prediction Loss: 5.016, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 5.016\n",
-      "Epoch: 12, Prediction Loss: 4.605, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.605\n",
-      "Epoch: 13, Prediction Loss: 4.349, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.349\n",
-      "Epoch: 14, Prediction Loss: 4.096, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.096\n",
-      "Epoch: 15, Prediction Loss: 4.008, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.008\n",
-      "Epoch: 16, Prediction Loss: 4.159, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.159\n",
-      "Epoch: 17, Prediction Loss: 3.980, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.980\n",
-      "Epoch: 18, Prediction Loss: 3.904, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.904\n",
-      "Epoch: 19, Prediction Loss: 3.995, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.995\n",
+      "Epoch: 0, Prediction Loss: 73.902, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 73.902\n",
+      "Epoch: 1, Prediction Loss: 33.630, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 33.630\n",
+      "Epoch: 2, Prediction Loss: 19.597, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 19.597\n",
+      "Epoch: 3, Prediction Loss: 19.476, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 19.476\n",
+      "Epoch: 4, Prediction Loss: 20.131, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 20.131\n",
+      "Epoch: 5, Prediction Loss: 15.780, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 15.780\n",
+      "Epoch: 6, Prediction Loss: 12.235, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 12.235\n",
+      "Epoch: 7, Prediction Loss: 10.043, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 10.043\n",
+      "Epoch: 8, Prediction Loss: 8.313, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 8.313\n",
+      "Epoch: 9, Prediction Loss: 6.753, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 6.753\n",
+      "Epoch: 10, Prediction Loss: 5.567, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 5.567\n",
+      "Epoch: 11, Prediction Loss: 4.777, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.777\n",
+      "Epoch: 12, Prediction Loss: 4.359, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.359\n",
+      "Epoch: 13, Prediction Loss: 4.267, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.267\n",
+      "Epoch: 14, Prediction Loss: 4.099, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.099\n",
+      "Epoch: 15, Prediction Loss: 3.897, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.897\n",
+      "Epoch: 16, Prediction Loss: 3.876, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.876\n",
+      "Epoch: 17, Prediction Loss: 3.865, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.865\n",
+      "Epoch: 18, Prediction Loss: 3.774, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.774\n",
+      "Epoch: 19, Prediction Loss: 3.796, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.796\n",
       "=== Training stage: 2. Train decoder ===\n",
-      "Epoch: 0, Prediction Loss: 34.805, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 34.805\n",
-      "Epoch: 1, Prediction Loss: 13.675, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 13.675\n",
-      "Epoch: 2, Prediction Loss: 7.021, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 7.021\n",
-      "Epoch: 3, Prediction Loss: 4.086, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 4.086\n",
-      "Epoch: 4, Prediction Loss: 3.847, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.847\n",
-      "Epoch: 5, Prediction Loss: 3.795, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.795\n",
-      "Epoch: 6, Prediction Loss: 3.762, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.762\n",
-      "Epoch: 7, Prediction Loss: 3.800, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.800\n",
-      "Epoch: 8, Prediction Loss: 3.792, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.792\n",
-      "Epoch: 9, Prediction Loss: 3.703, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.703\n",
-      "Epoch: 10, Prediction Loss: 3.683, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.683\n",
-      "Epoch: 11, Prediction Loss: 3.734, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.734\n",
-      "Epoch: 12, Prediction Loss: 3.690, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.690\n",
-      "Epoch: 13, Prediction Loss: 3.728, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.728\n",
-      "Epoch: 14, Prediction Loss: 3.694, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.694\n",
-      "Epoch: 15, Prediction Loss: 3.647, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.647\n",
-      "Epoch: 16, Prediction Loss: 3.639, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.639\n",
-      "Epoch: 17, Prediction Loss: 3.612, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.612\n",
-      "Epoch: 18, Prediction Loss: 3.633, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.633\n",
-      "Epoch: 19, Prediction Loss: 3.604, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.604\n"
+      "Epoch: 0, Prediction Loss: 38.872, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 38.872\n",
+      "Epoch: 1, Prediction Loss: 14.391, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 14.391\n",
+      "Epoch: 2, Prediction Loss: 7.017, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 7.017\n",
+      "Epoch: 3, Prediction Loss: 3.957, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.957\n",
+      "Epoch: 4, Prediction Loss: 3.851, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.851\n",
+      "Epoch: 5, Prediction Loss: 3.786, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.786\n",
+      "Epoch: 6, Prediction Loss: 3.766, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.766\n",
+      "Epoch: 7, Prediction Loss: 3.748, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.748\n",
+      "Epoch: 8, Prediction Loss: 3.720, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.720\n",
+      "Epoch: 9, Prediction Loss: 3.717, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.717\n",
+      "Epoch: 10, Prediction Loss: 3.714, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.714\n",
+      "Epoch: 11, Prediction Loss: 3.688, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.688\n",
+      "Epoch: 12, Prediction Loss: 3.660, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.660\n",
+      "Epoch: 13, Prediction Loss: 3.696, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.696\n",
+      "Epoch: 14, Prediction Loss: 3.653, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.653\n",
+      "Epoch: 15, Prediction Loss: 3.649, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.649\n",
+      "Epoch: 16, Prediction Loss: 3.638, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.638\n",
+      "Epoch: 17, Prediction Loss: 3.667, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.667\n",
+      "Epoch: 18, Prediction Loss: 3.621, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.621\n",
+      "Epoch: 19, Prediction Loss: 3.626, Lambda: 1.000, Treatment BR Loss: 0.000, Loss: 3.626\n"
      ]
     }
    ],
@@ -484,23 +485,23 @@
       "TimeSeries() with data:\n",
       "                 0         1\n",
       "time_idx                    \n",
-      "5         6.339921  5.118720\n",
-      "6         6.379971  5.159422\n",
-      "7         6.380514  5.159956\n",
-      "8         6.380521  5.159964\n",
-      "9         6.380521  5.159964\n",
-      "10        6.380521  5.159964\n",
+      "5         6.281449  4.965402\n",
+      "6         6.435705  5.133381\n",
+      "7         6.441704  5.139909\n",
+      "8         6.441934  5.140160\n",
+      "9         6.441943  5.140169\n",
+      "10        6.441943  5.140169\n",
       "\n",
       "Treatment scenario 1, [0 0 0 0 0 0]\n",
       "TimeSeries() with data:\n",
       "                 0         1\n",
       "time_idx                    \n",
-      "5         6.694273  5.142348\n",
-      "6         6.732183  5.177425\n",
-      "7         6.732780  5.178019\n",
-      "8         6.732789  5.178029\n",
-      "9         6.732790  5.178029\n",
-      "10        6.732790  5.178029\n",
+      "5         6.634320  4.977645\n",
+      "6         6.721170  5.071841\n",
+      "7         6.726741  5.078034\n",
+      "8         6.727103  5.078438\n",
+      "9         6.727127  5.078464\n",
+      "10        6.727128  5.078465\n",
       "\n"
      ]
     }
@@ -568,7 +569,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/usage/tutorial07_pipeline.ipynb b/tutorials/usage/tutorial07_pipeline.ipynb
index 01b7aaf6..7137eec3 100644
--- a/tutorials/usage/tutorial07_pipeline.ipynb
+++ b/tutorials/usage/tutorial07_pipeline.ipynb
@@ -19,7 +19,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -123,6 +123,14 @@
      "metadata": {},
      "output_type": "display_data"
     },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:24:00 | INFO     | hyperimpute.logger:log_and_print:65 | Iteration imputation: select_model_by_column: True, select_model_by_iteration: True\n",
+      "2023-10-07 22:24:00 | INFO     | hyperimpute.logger:log_and_print:65 | Iteration imputation: select_model_by_column: True, select_model_by_iteration: True\n"
+     ]
+    },
     {
      "name": "stdout",
      "output_type": "stream",
@@ -155,7 +163,7 @@
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'window_size'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'device'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'dataloader_sampler'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
-       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'random_state'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'clipping_value'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
@@ -189,7 +197,7 @@
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'window_size'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'device'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'dataloader_sampler'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
-       "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'random_state'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'clipping_value'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
@@ -251,6 +259,58 @@
    "execution_count": 4,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > HyperImpute using inner optimization\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 0\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 1\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 2\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 3\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 4\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 5\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 6\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |      >>>> Early stopping on objective diff iteration\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > HyperImpute using inner optimization\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 0\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 1\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 2\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 3\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 4\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 5\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 6\n",
+      "2023-10-07 22:24:01 | INFO     | hyperimpute.logger:log_and_print:65 |      >>>> Early stopping on objective diff iteration\n",
+      "2023-10-07 22:24:03 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.688586950302124, validation loss: 0.6886438131332397\n",
+      "2023-10-07 22:24:03 | INFO     | tempor.models.ts_model:_train:379 | Epoch:10| train loss: 0.6998531222343445, validation loss: 0.6888602375984192\n",
+      "2023-10-07 22:24:03 | INFO     | tempor.models.ts_model:_train:379 | Epoch:20| train loss: 0.6862186193466187, validation loss: 0.689547061920166\n",
+      "2023-10-07 22:24:03 | INFO     | tempor.models.ts_model:_train:379 | Epoch:30| train loss: 0.6913824677467346, validation loss: 0.6873278617858887\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:40| train loss: 0.6604955792427063, validation loss: 0.689150333404541\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:50| train loss: 0.6746629476547241, validation loss: 0.6878216862678528\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:60| train loss: 0.7084729075431824, validation loss: 0.6860194802284241\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:70| train loss: 0.6851019263267517, validation loss: 0.683639645576477\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:80| train loss: 0.6695638298988342, validation loss: 0.6823517084121704\n",
+      "2023-10-07 22:24:04 | INFO     | tempor.models.ts_model:_train:379 | Epoch:90| train loss: 0.6456660032272339, validation loss: 0.6871115565299988\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > HyperImpute using inner optimization\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 0\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 1\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 2\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 3\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 4\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 5\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 6\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |      >>>> Early stopping on objective diff iteration\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > HyperImpute using inner optimization\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 0\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 1\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 2\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 3\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 4\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 5\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |   > Imputation iter 6\n",
+      "2023-10-07 22:24:04 | INFO     | hyperimpute.logger:log_and_print:65 |      >>>> Early stopping on objective diff iteration\n"
+     ]
+    },
     {
      "data": {
       "text/html": [
@@ -405,7 +465,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/usage/tutorial08_benchmarks.ipynb b/tutorials/usage/tutorial08_benchmarks.ipynb
index c4881086..73db296b 100644
--- a/tutorials/usage/tutorial08_benchmarks.ipynb
+++ b/tutorials/usage/tutorial08_benchmarks.ipynb
@@ -19,7 +19,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -54,14 +54,14 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 19:18:40 | INFO     | tempor.benchmarks.benchmark:benchmark_models:91 | Test case: model_1\n",
-      "2023-05-14 19:18:42 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.68637615442276, validation loss: 0.6680578589439392\n",
-      "2023-05-14 19:18:43 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6887814402580261, validation loss: 0.6939960718154907\n",
-      "2023-05-14 19:18:43 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6906945109367371, validation loss: 0.6966598033905029\n",
-      "2023-05-14 19:18:43 | INFO     | tempor.benchmarks.benchmark:benchmark_models:91 | Test case: model_2\n",
-      "2023-05-14 19:18:48 | INFO     | tempor.models.ts_ode:_train:608 | Epoch:99| train loss: 0.6465951204299927, validation loss: 0.5632617473602295\n",
-      "2023-05-14 19:18:52 | INFO     | tempor.models.ts_ode:_train:608 | Epoch:99| train loss: 0.913261890411377, validation loss: 0.8132617473602295\n",
-      "2023-05-14 19:18:57 | INFO     | tempor.models.ts_ode:_train:608 | Epoch:99| train loss: 0.7132617831230164, validation loss: 0.8132617473602295\n"
+      "2023-10-07 22:24:21 | INFO     | tempor.benchmarks.benchmark:benchmark_models:100 | Test case: model_1\n",
+      "2023-10-07 22:24:23 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.68637615442276, validation loss: 0.6680578589439392\n",
+      "2023-10-07 22:24:24 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6887814402580261, validation loss: 0.6939960718154907\n",
+      "2023-10-07 22:24:25 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6906945109367371, validation loss: 0.6966598033905029\n",
+      "2023-10-07 22:24:25 | INFO     | tempor.benchmarks.benchmark:benchmark_models:100 | Test case: model_2\n",
+      "2023-10-07 22:24:31 | INFO     | tempor.models.ts_ode:_train:607 | Epoch:99| train loss: 0.6465951204299927, validation loss: 0.5632617473602295\n",
+      "2023-10-07 22:24:37 | INFO     | tempor.models.ts_ode:_train:607 | Epoch:99| train loss: 0.913261890411377, validation loss: 0.8132617473602295\n",
+      "2023-10-07 22:24:42 | INFO     | tempor.models.ts_ode:_train:607 | Epoch:99| train loss: 0.7132617831230164, validation loss: 0.8132617473602295\n"
      ]
     },
     {
@@ -552,7 +552,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },
diff --git a/tutorials/usage/tutorial09_automl.ipynb b/tutorials/usage/tutorial09_automl.ipynb
index 3e39802b..6b9aa908 100644
--- a/tutorials/usage/tutorial09_automl.ipynb
+++ b/tutorials/usage/tutorial09_automl.ipynb
@@ -19,7 +19,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -72,10 +72,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_set_up_tuners:354 | Setting up estimators and tuners for study my_automl_study.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator cde_classifier.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator ode_classifier.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator nn_classifier.\n"
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_set_up_tuners:365 | Setting up estimators and tuners for study my_automl_study.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator cde_classifier.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator ode_classifier.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator nn_classifier.\n"
      ]
     }
    ],
@@ -131,10 +131,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_set_up_tuners:354 | Setting up estimators and tuners for study my_automl_study.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator cde_classifier.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator ode_classifier.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator nn_classifier.\n"
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_set_up_tuners:365 | Setting up estimators and tuners for study my_automl_study.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator cde_classifier.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator ode_classifier.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator nn_classifier.\n"
      ]
     }
    ],
@@ -189,79 +189,79 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator 'cde_classifier' 1/3.\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:48:44 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator 'cde_classifier' 1/3.\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:25:21 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from CDEClassifier:\n",
       "{'n_iter': 2, 'n_temporal_units_hidden': 13, 'lr': 0.01}\n",
-      "2023-05-14 21:48:49 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:26 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from CDEClassifier:\n",
       "{'n_iter': 2, 'n_temporal_units_hidden': 11, 'lr': 0.0001}\n",
-      "2023-05-14 21:48:53 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:30 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from CDEClassifier:\n",
       "{'n_iter': 2, 'n_temporal_units_hidden': 20, 'lr': 0.001}\n",
-      "2023-05-14 21:48:56 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator 'ode_classifier' 2/3.\n",
-      "2023-05-14 21:48:56 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:48:56 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:34 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator 'ode_classifier' 2/3.\n",
+      "2023-10-07 22:25:34 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:25:34 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from ODEClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 13, 'lr': 0.01}\n",
-      "2023-05-14 21:48:59 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:38 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from ODEClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}\n",
-      "2023-05-14 21:49:02 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:41 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from ODEClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 20, 'lr': 0.001}\n",
-      "2023-05-14 21:49:05 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator 'nn_classifier' 3/3.\n",
-      "2023-05-14 21:49:05 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:49:05 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:45 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator 'nn_classifier' 3/3.\n",
+      "2023-10-07 22:25:45 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:25:45 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from NeuralNetClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 13, 'lr': 0.01}\n",
-      "2023-05-14 21:49:06 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.6882655620574951\n",
-      "2023-05-14 21:49:07 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6865323185920715\n",
-      "2023-05-14 21:49:07 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6861071586608887\n",
-      "2023-05-14 21:49:08 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6825112104415894\n",
-      "2023-05-14 21:49:08 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6819757223129272\n",
-      "2023-05-14 21:49:08 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:45 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.6882655620574951\n",
+      "2023-10-07 22:25:46 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6865323185920715\n",
+      "2023-10-07 22:25:47 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6861070990562439\n",
+      "2023-10-07 22:25:47 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6825112104415894\n",
+      "2023-10-07 22:25:48 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6819757223129272\n",
+      "2023-10-07 22:25:48 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from NeuralNetClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}\n",
-      "2023-05-14 21:49:09 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.691270649433136\n",
-      "2023-05-14 21:49:09 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6910805106163025\n",
-      "2023-05-14 21:49:10 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6900344491004944\n",
-      "2023-05-14 21:49:10 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6906693577766418\n",
-      "2023-05-14 21:49:11 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6910874843597412\n",
-      "2023-05-14 21:49:11 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:49 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.691270649433136\n",
+      "2023-10-07 22:25:49 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6910805106163025\n",
+      "2023-10-07 22:25:50 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6900344491004944\n",
+      "2023-10-07 22:25:50 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6906693577766418\n",
+      "2023-10-07 22:25:51 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6910874843597412\n",
+      "2023-10-07 22:25:51 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from NeuralNetClassifier:\n",
       "{'n_iter': 2, 'n_units_hidden': 20, 'lr': 0.001}\n",
-      "2023-05-14 21:49:11 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.6896670460700989\n",
-      "2023-05-14 21:49:12 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6886401772499084\n",
-      "2023-05-14 21:49:12 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6884845495223999\n",
-      "2023-05-14 21:49:13 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6887120604515076\n",
-      "2023-05-14 21:49:13 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6893669962882996\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:25:52 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919505596160889, validation loss: 0.6896671056747437\n",
+      "2023-10-07 22:25:53 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.691156268119812, validation loss: 0.6886401772499084\n",
+      "2023-10-07 22:25:53 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692247211933136, validation loss: 0.6884845495223999\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6928325891494751, validation loss: 0.6887120604515076\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6919053792953491, validation loss: 0.6893669962882996\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for cde_classifier scores:\n",
       "[0.47310606060606064, 0.48396464646464643, 0.4840277777777778].\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for ode_classifier scores:\n",
       "[0.47992424242424236, 0.48409090909090907, 0.484090909090909].\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for nn_classifier scores:\n",
       "[0.37064393939393936, 0.5370580808080809, 0.4579545454545454].\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:448 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:460 | \n",
       "All estimator definitions searched:\n",
       "['cde_classifier', 'ode_classifier', 'nn_classifier']\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:449 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:461 | \n",
       "Best scores for each estimator searched:\n",
       "[0.4840277777777778, 0.48409090909090907, 0.5370580808080809]\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:450 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:462 | \n",
       "Best hyperparameters for each estimator searched:\n",
       "[{'n_iter': 2, 'n_temporal_units_hidden': 20, 'lr': 0.001}, {'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}, {'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}]\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:571 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:587 | \n",
       "Selected score 0.5370580808080809 for nn_classifier with hyperparameters:\n",
       "{'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:571 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:587 | \n",
       "Selected score 0.48409090909090907 for ode_classifier with hyperparameters:\n",
       "{'n_iter': 2, 'n_units_hidden': 11, 'lr': 0.0001}\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:571 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:587 | \n",
       "Selected score 0.4840277777777778 for cde_classifier with hyperparameters:\n",
       "{'n_iter': 2, 'n_temporal_units_hidden': 20, 'lr': 0.001}\n"
      ]
@@ -284,6 +284,7 @@
        "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">NeuralNetClassifier</span><span style=\"font-weight: bold\">(</span>\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'nn_classifier'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">category</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'prediction.one_off.classification'</span>,\n",
+       "    <span style=\"color: #808000; text-decoration-color: #808000\">plugin_type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'method'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">params</span>=<span style=\"font-weight: bold\">{</span>\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_static_units_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">100</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_static_layers_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2</span>,\n",
@@ -298,7 +299,7 @@
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'window_size'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'device'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'dataloader_sampler'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
-       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'random_state'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'clipping_value'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
@@ -312,6 +313,7 @@
        "\u001b[1;35mNeuralNetClassifier\u001b[0m\u001b[1m(\u001b[0m\n",
        "    \u001b[33mname\u001b[0m=\u001b[32m'nn_classifier'\u001b[0m,\n",
        "    \u001b[33mcategory\u001b[0m=\u001b[32m'prediction.one_off.classification'\u001b[0m,\n",
+       "    \u001b[33mplugin_type\u001b[0m=\u001b[32m'method'\u001b[0m,\n",
        "    \u001b[33mparams\u001b[0m=\u001b[1m{\u001b[0m\n",
        "        \u001b[32m'n_static_units_hidden'\u001b[0m: \u001b[1;36m100\u001b[0m,\n",
        "        \u001b[32m'n_static_layers_hidden'\u001b[0m: \u001b[1;36m2\u001b[0m,\n",
@@ -326,7 +328,7 @@
        "        \u001b[32m'window_size'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "        \u001b[32m'device'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
        "        \u001b[32m'dataloader_sampler'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
-       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "        \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
        "        \u001b[32m'random_state'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "        \u001b[32m'clipping_value'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
@@ -345,11 +347,12 @@
        "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ODEClassifier</span><span style=\"font-weight: bold\">(</span>\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'ode_classifier'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">category</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'prediction.one_off.classification'</span>,\n",
+       "    <span style=\"color: #808000; text-decoration-color: #808000\">plugin_type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'method'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">params</span>=<span style=\"font-weight: bold\">{</span>\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_units_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">11</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_layers_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
-       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'atol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'rtol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'interpolation'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'cubic'</span>,\n",
@@ -372,11 +375,12 @@
        "\u001b[1;35mODEClassifier\u001b[0m\u001b[1m(\u001b[0m\n",
        "    \u001b[33mname\u001b[0m=\u001b[32m'ode_classifier'\u001b[0m,\n",
        "    \u001b[33mcategory\u001b[0m=\u001b[32m'prediction.one_off.classification'\u001b[0m,\n",
+       "    \u001b[33mplugin_type\u001b[0m=\u001b[32m'method'\u001b[0m,\n",
        "    \u001b[33mparams\u001b[0m=\u001b[1m{\u001b[0m\n",
        "        \u001b[32m'n_units_hidden'\u001b[0m: \u001b[1;36m11\u001b[0m,\n",
        "        \u001b[32m'n_layers_hidden'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "        \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
-       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "        \u001b[32m'atol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "        \u001b[32m'rtol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "        \u001b[32m'interpolation'\u001b[0m: \u001b[32m'cubic'\u001b[0m,\n",
@@ -404,11 +408,12 @@
        "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">CDEClassifier</span><span style=\"font-weight: bold\">(</span>\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'cde_classifier'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">category</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'prediction.one_off.classification'</span>,\n",
+       "    <span style=\"color: #808000; text-decoration-color: #808000\">plugin_type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'method'</span>,\n",
        "    <span style=\"color: #808000; text-decoration-color: #808000\">params</span>=<span style=\"font-weight: bold\">{</span>\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_units_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">100</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'n_layers_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
-       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "        <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'atol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'rtol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "        <span style=\"color: #008000; text-decoration-color: #008000\">'interpolation'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'cubic'</span>,\n",
@@ -431,11 +436,12 @@
        "\u001b[1;35mCDEClassifier\u001b[0m\u001b[1m(\u001b[0m\n",
        "    \u001b[33mname\u001b[0m=\u001b[32m'cde_classifier'\u001b[0m,\n",
        "    \u001b[33mcategory\u001b[0m=\u001b[32m'prediction.one_off.classification'\u001b[0m,\n",
+       "    \u001b[33mplugin_type\u001b[0m=\u001b[32m'method'\u001b[0m,\n",
        "    \u001b[33mparams\u001b[0m=\u001b[1m{\u001b[0m\n",
        "        \u001b[32m'n_units_hidden'\u001b[0m: \u001b[1;36m100\u001b[0m,\n",
        "        \u001b[32m'n_layers_hidden'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "        \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
-       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "        \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "        \u001b[32m'atol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "        \u001b[32m'rtol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "        \u001b[32m'interpolation'\u001b[0m: \u001b[32m'cubic'\u001b[0m,\n",
@@ -498,10 +504,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_set_up_tuners:354 | Setting up estimators and tuners for study my_automl_study.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with cde_classifier>.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with ode_classifier>.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with nn_classifier>.\n"
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_set_up_tuners:365 | Setting up estimators and tuners for study my_automl_study.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with cde_classifier>.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with ode_classifier>.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with nn_classifier>.\n"
      ]
     }
    ],
@@ -585,10 +591,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_set_up_tuners:354 | Setting up estimators and tuners for study my_automl_study.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with cde_classifier>.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with ode_classifier>.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:_init_estimator:733 | Creating estimator <Pipeline with nn_classifier>.\n"
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_set_up_tuners:365 | Setting up estimators and tuners for study my_automl_study.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with cde_classifier>.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with ode_classifier>.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:_init_estimator:753 | Creating estimator <Pipeline with nn_classifier>.\n"
      ]
     }
    ],
@@ -650,79 +656,79 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator '<Pipeline with cde_classifier>' 1/3.\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:49:14 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator '<Pipeline with cde_classifier>' 1/3.\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:25:54 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.cde_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'softimpute'}, 'static_minmax_scaler': {'clip': True}, 'ts_standard_scaler': {}, 'cde_classifier': {'n_iter': 2, 'n_temporal_units_hidden': 17, 'lr': 0.001}}}\n",
-      "2023-05-14 21:49:30 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:26:27 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_minmax_scaler->prediction.one_off.classification.cde_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'mean'}, 'static_minmax_scaler': {'clip': False}, 'ts_minmax_scaler': {'clip': False}, 'cde_classifier': {'n_iter': 2, 'n_temporal_units_hidden': 14, 'lr': 0.001}}}\n",
-      "2023-05-14 21:49:36 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:26:33 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_standard_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.cde_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'most_frequent'}, 'static_standard_scaler': {}, 'ts_standard_scaler': {}, 'cde_classifier': {'n_iter': 2, 'n_temporal_units_hidden': 6, 'lr': 0.0001}}}\n",
-      "2023-05-14 21:49:42 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator '<Pipeline with ode_classifier>' 2/3.\n",
-      "2023-05-14 21:49:42 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:49:42 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:26:40 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator '<Pipeline with ode_classifier>' 2/3.\n",
+      "2023-10-07 22:26:40 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:26:40 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.ode_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'softimpute'}, 'static_minmax_scaler': {'clip': True}, 'ts_standard_scaler': {}, 'ode_classifier': {'n_iter': 2, 'n_units_hidden': 17, 'lr': 0.001}}}\n",
-      "2023-05-14 21:50:00 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:26:59 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_minmax_scaler->prediction.one_off.classification.ode_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'mean'}, 'static_minmax_scaler': {'clip': False}, 'ts_minmax_scaler': {'clip': False}, 'ode_classifier': {'n_iter': 2, 'n_units_hidden': 14, 'lr': 0.001}}}\n",
-      "2023-05-14 21:50:06 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:27:05 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_standard_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.ode_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'most_frequent'}, 'static_standard_scaler': {}, 'ts_standard_scaler': {}, 'ode_classifier': {'n_iter': 2, 'n_units_hidden': 6, 'lr': 0.0001}}}\n",
-      "2023-05-14 21:50:11 | INFO     | tempor.automl.seeker:search:413 | Running  search for estimator '<Pipeline with nn_classifier>' 3/3.\n",
-      "2023-05-14 21:50:11 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
-      "2023-05-14 21:50:11 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:27:11 | INFO     | tempor.automl.seeker:search:424 | Running  search for estimator '<Pipeline with nn_classifier>' 3/3.\n",
+      "2023-10-07 22:27:11 | INFO     | tempor.automl.tuner:tune:205 | Baseline score computation skipped\n",
+      "2023-10-07 22:27:11 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.nn_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'softimpute'}, 'static_minmax_scaler': {'clip': True}, 'ts_standard_scaler': {}, 'nn_classifier': {'n_iter': 2, 'n_units_hidden': 17, 'lr': 0.001}}}\n",
-      "2023-05-14 21:50:14 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6918608546257019, validation loss: 0.6910383105278015\n",
-      "2023-05-14 21:50:17 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6909429430961609, validation loss: 0.6872987151145935\n",
-      "2023-05-14 21:50:21 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692150354385376, validation loss: 0.6879752278327942\n",
-      "2023-05-14 21:50:24 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6926363706588745, validation loss: 0.6881052851676941\n",
-      "2023-05-14 21:50:27 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6915659308433533, validation loss: 0.6888220310211182\n",
-      "2023-05-14 21:50:28 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:27:13 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6918608546257019, validation loss: 0.6910383105278015\n",
+      "2023-10-07 22:27:16 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6909429430961609, validation loss: 0.6872987151145935\n",
+      "2023-10-07 22:27:19 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.692150354385376, validation loss: 0.6879752278327942\n",
+      "2023-10-07 22:27:22 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6926363706588745, validation loss: 0.6881052851676941\n",
+      "2023-10-07 22:27:25 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6915659308433533, validation loss: 0.6888220310211182\n",
+      "2023-10-07 22:27:26 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_minmax_scaler->preprocessing.scaling.temporal.ts_minmax_scaler->prediction.one_off.classification.nn_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'mean'}, 'static_minmax_scaler': {'clip': False}, 'ts_minmax_scaler': {'clip': False}, 'nn_classifier': {'n_iter': 2, 'n_units_hidden': 14, 'lr': 0.001}}}\n",
-      "2023-05-14 21:50:28 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6920319199562073, validation loss: 0.6892786622047424\n",
-      "2023-05-14 21:50:29 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6913070678710938, validation loss: 0.6893746852874756\n",
-      "2023-05-14 21:50:30 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6924894452095032, validation loss: 0.6886722445487976\n",
-      "2023-05-14 21:50:31 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6930248141288757, validation loss: 0.6894596815109253\n",
-      "2023-05-14 21:50:32 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6921922564506531, validation loss: 0.6893032789230347\n",
-      "2023-05-14 21:50:33 | INFO     | tempor.automl.tuner:objective:227 | \n",
+      "2023-10-07 22:27:27 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6920319199562073, validation loss: 0.6892786622047424\n",
+      "2023-10-07 22:27:28 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6913070678710938, validation loss: 0.6893746852874756\n",
+      "2023-10-07 22:27:29 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6924894452095032, validation loss: 0.6886722445487976\n",
+      "2023-10-07 22:27:30 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6930248141288757, validation loss: 0.6894596815109253\n",
+      "2023-10-07 22:27:31 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6921922564506531, validation loss: 0.6893032789230347\n",
+      "2023-10-07 22:27:31 | INFO     | tempor.automl.tuner:objective:227 | \n",
       "Hyperparameters sampled from preprocessing.imputation.static.static_tabular_imputer->preprocessing.scaling.static.static_standard_scaler->preprocessing.scaling.temporal.ts_standard_scaler->prediction.one_off.classification.nn_classifier:\n",
       "{'plugin_params': {'static_tabular_imputer': {'imputer': 'most_frequent'}, 'static_standard_scaler': {}, 'ts_standard_scaler': {}, 'nn_classifier': {'n_iter': 2, 'n_units_hidden': 6, 'lr': 0.0001}}}\n",
-      "2023-05-14 21:50:33 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6914154291152954, validation loss: 0.6911771297454834\n",
-      "2023-05-14 21:50:34 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.690178394317627, validation loss: 0.6934390664100647\n",
-      "2023-05-14 21:50:35 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6933540105819702, validation loss: 0.6896734833717346\n",
-      "2023-05-14 21:50:36 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.694333553314209, validation loss: 0.690070390701294\n",
-      "2023-05-14 21:50:37 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6921719312667847, validation loss: 0.6909489631652832\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:27:32 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6914154291152954, validation loss: 0.6911771297454834\n",
+      "2023-10-07 22:27:33 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.690178394317627, validation loss: 0.6934390664100647\n",
+      "2023-10-07 22:27:34 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6933540105819702, validation loss: 0.6896734833717346\n",
+      "2023-10-07 22:27:35 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.694333553314209, validation loss: 0.690070390701294\n",
+      "2023-10-07 22:27:36 | INFO     | tempor.models.ts_model:_train:379 | Epoch:0| train loss: 0.6921719312667847, validation loss: 0.6909489631652832\n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for <Pipeline with cde_classifier> scores:\n",
       "[0.4716540404040404, 0.47575757575757577, 0.4657828282828283].\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for <Pipeline with ode_classifier> scores:\n",
       "[0.47575757575757577, 0.4779040404040404, 0.4779671717171716].\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:447 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:459 | \n",
       "Evaluation for <Pipeline with nn_classifier> scores:\n",
       "[0.48478535353535346, 0.4361742424242424, 0.5071338383838383].\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:448 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:460 | \n",
       "All estimator definitions searched:\n",
       "['<Pipeline with cde_classifier>', '<Pipeline with ode_classifier>', '<Pipeline with nn_classifier>']\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:449 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:461 | \n",
       "Best scores for each estimator searched:\n",
       "[0.47575757575757577, 0.4779671717171716, 0.5071338383838383]\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:search:450 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:search:462 | \n",
       "Best hyperparameters for each estimator searched:\n",
       "[{'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'mean', '<candidates>(preprocessing.scaling.static)': 'static_minmax_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_minmax_scaler', '[ts_minmax_scaler](clip)': False, '[cde_classifier](n_iter)': 2, '[cde_classifier](n_temporal_units_hidden)': 14, '[cde_classifier](lr)': 0.001}, {'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'most_frequent', '<candidates>(preprocessing.scaling.static)': 'static_standard_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_standard_scaler', '[ts_minmax_scaler](clip)': False, '[ode_classifier](n_iter)': 2, '[ode_classifier](n_units_hidden)': 6, '[ode_classifier](lr)': 0.0001}, {'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'most_frequent', '<candidates>(preprocessing.scaling.static)': 'static_standard_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_standard_scaler', '[ts_minmax_scaler](clip)': False, '[nn_classifier](n_iter)': 2, '[nn_classifier](n_units_hidden)': 6, '[nn_classifier](lr)': 0.0001}]\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:748 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:768 | \n",
       "Selected score 0.5071338383838383 for <Pipeline with nn_classifier> with hyperparameters:\n",
       "{'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'most_frequent', '<candidates>(preprocessing.scaling.static)': 'static_standard_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_standard_scaler', '[ts_minmax_scaler](clip)': False, '[nn_classifier](n_iter)': 2, '[nn_classifier](n_units_hidden)': 6, '[nn_classifier](lr)': 0.0001}\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:748 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:768 | \n",
       "Selected score 0.4779671717171716 for <Pipeline with ode_classifier> with hyperparameters:\n",
       "{'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'most_frequent', '<candidates>(preprocessing.scaling.static)': 'static_standard_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_standard_scaler', '[ts_minmax_scaler](clip)': False, '[ode_classifier](n_iter)': 2, '[ode_classifier](n_units_hidden)': 6, '[ode_classifier](lr)': 0.0001}\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:748 | \n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_create_estimator_with_hps:768 | \n",
       "Selected score 0.47575757575757577 for <Pipeline with cde_classifier> with hyperparameters:\n",
       "{'<candidates>(preprocessing.imputation.static)': 'static_tabular_imputer', '[static_tabular_imputer](imputer)': 'mean', '<candidates>(preprocessing.scaling.static)': 'static_minmax_scaler', '[static_minmax_scaler](clip)': False, '<candidates>(preprocessing.scaling.temporal)': 'ts_minmax_scaler', '[ts_minmax_scaler](clip)': False, '[cde_classifier](n_iter)': 2, '[cde_classifier](n_temporal_units_hidden)': 14, '[cde_classifier](lr)': 0.001}\n"
      ]
@@ -765,7 +771,7 @@
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'window_size'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'device'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'dataloader_sampler'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
-       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'random_state'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'clipping_value'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
@@ -802,7 +808,7 @@
        "            \u001b[32m'window_size'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "            \u001b[32m'device'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
        "            \u001b[32m'dataloader_sampler'\u001b[0m: \u001b[3;35mNone\u001b[0m,\n",
-       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "            \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
        "            \u001b[32m'random_state'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "            \u001b[32m'clipping_value'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
@@ -834,7 +840,7 @@
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'n_units_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">6</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'n_layers_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
-       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'atol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'rtol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'interpolation'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'cubic'</span>,\n",
@@ -870,7 +876,7 @@
        "            \u001b[32m'n_units_hidden'\u001b[0m: \u001b[1;36m6\u001b[0m,\n",
        "            \u001b[32m'n_layers_hidden'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "            \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
-       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "            \u001b[32m'atol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "            \u001b[32m'rtol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "            \u001b[32m'interpolation'\u001b[0m: \u001b[32m'cubic'\u001b[0m,\n",
@@ -907,7 +913,7 @@
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'n_units_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">100</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'n_layers_hidden'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'nonlin'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'relu'</span>,\n",
-       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.0</span>,\n",
+       "            <span style=\"color: #008000; text-decoration-color: #008000\">'dropout'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'atol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'rtol'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.01</span>,\n",
        "            <span style=\"color: #008000; text-decoration-color: #008000\">'interpolation'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'cubic'</span>,\n",
@@ -939,7 +945,7 @@
        "            \u001b[32m'n_units_hidden'\u001b[0m: \u001b[1;36m100\u001b[0m,\n",
        "            \u001b[32m'n_layers_hidden'\u001b[0m: \u001b[1;36m1\u001b[0m,\n",
        "            \u001b[32m'nonlin'\u001b[0m: \u001b[32m'relu'\u001b[0m,\n",
-       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0.0\u001b[0m,\n",
+       "            \u001b[32m'dropout'\u001b[0m: \u001b[1;36m0\u001b[0m,\n",
        "            \u001b[32m'atol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "            \u001b[32m'rtol'\u001b[0m: \u001b[1;36m0.01\u001b[0m,\n",
        "            \u001b[32m'interpolation'\u001b[0m: \u001b[32m'cubic'\u001b[0m,\n",
@@ -991,10 +997,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_set_up_tuners:354 | Setting up estimators and tuners for study my_automl_study.\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator cde_classifier.\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator ode_classifier.\n",
-      "2023-05-14 21:50:38 | INFO     | tempor.automl.seeker:_init_estimator:563 | Creating estimator nn_classifier.\n"
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_set_up_tuners:365 | Setting up estimators and tuners for study my_automl_study.\n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator cde_classifier.\n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator ode_classifier.\n",
+      "2023-10-07 22:27:36 | INFO     | tempor.automl.seeker:_init_estimator:579 | Creating estimator nn_classifier.\n"
      ]
     }
    ],
@@ -1085,7 +1091,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },


Test patch:
diff --git a/docs/user_guide/extending/tutorial02_testing_custom_plugin.ipynb b/docs/user_guide/extending/tutorial02_testing_custom_plugin.ipynb
index c956eaa4..d3b13b4c 100644
--- a/docs/user_guide/extending/tutorial02_testing_custom_plugin.ipynb
+++ b/docs/user_guide/extending/tutorial02_testing_custom_plugin.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "ce80952d",
+   "id": "",
    "metadata": {},
    "source": [
     "[![Test In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/vanderschaarlab/temporai/blob/main/tutorials/extending/tutorial02_testing_custom_plugin.ipynb)"
@@ -57,7 +57,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [
     {
@@ -75,6 +75,8 @@
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'prediction.one_off.regression'</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'prediction.temporal.classification'</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'prediction.temporal.regression'</span>,\n",
+       "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.encoding.static'</span>,\n",
+       "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.encoding.temporal'</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.imputation.static'</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.imputation.temporal'</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.nop'</span>,\n",
@@ -93,6 +95,8 @@
        "    \u001b[32m'prediction.one_off.regression'\u001b[0m,\n",
        "    \u001b[32m'prediction.temporal.classification'\u001b[0m,\n",
        "    \u001b[32m'prediction.temporal.regression'\u001b[0m,\n",
+       "    \u001b[32m'preprocessing.encoding.static'\u001b[0m,\n",
+       "    \u001b[32m'preprocessing.encoding.temporal'\u001b[0m,\n",
        "    \u001b[32m'preprocessing.imputation.static'\u001b[0m,\n",
        "    \u001b[32m'preprocessing.imputation.temporal'\u001b[0m,\n",
        "    \u001b[32m'preprocessing.nop'\u001b[0m,\n",
@@ -127,6 +131,7 @@
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"font-weight: bold\">}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'encoding'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_onehot_encoder'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_onehot_encoder'</span><span style=\"font-weight: bold\">]}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'imputation'</span>: <span style=\"font-weight: bold\">{</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_tabular_imputer'</span><span style=\"font-weight: bold\">]</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ffill'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_tabular_imputer'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'bfill'</span><span style=\"font-weight: bold\">]</span>\n",
@@ -155,6 +160,7 @@
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
        "\u001b[2;32m│   \u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   \u001b[0m\u001b[32m'preprocessing'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "\u001b[2;32m│   │   \u001b[0m\u001b[32m'encoding'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'imputation'\u001b[0m: \u001b[1m{\u001b[0m\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_tabular_imputer'\u001b[0m\u001b[1m]\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ffill'\u001b[0m, \u001b[32m'ts_tabular_imputer'\u001b[0m, \u001b[32m'bfill'\u001b[0m\u001b[1m]\u001b[0m\n",
@@ -265,7 +271,7 @@
     "    test_plugin = get_test_plugin(plugin_from, INIT_KWARGS)\n",
     "    assert test_plugin is not None\n",
     "    assert test_plugin.name == \"nn_classifier\"\n",
-    "    assert test_plugin.fqn() == \"prediction.one_off.classification.my_classifier\"\n",
+    "    assert test_plugin.full_name() == \"prediction.one_off.classification.my_classifier\"\n",
     "    assert len(test_plugin.hyperparameter_space()) == 9\n",
     "\n",
     "\n",
@@ -379,7 +385,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/tests/benchmarks/test_benchmark.py b/tests/benchmarks/test_benchmark.py
index 08ac5495..dad94b10 100644
--- a/tests/benchmarks/test_benchmark.py
+++ b/tests/benchmarks/test_benchmark.py
@@ -3,7 +3,7 @@
 
 import pytest
 
-from tempor.benchmarks import (  # visualize_benchmark,
+from tempor.benchmarks import (
     benchmark_models,
     classifier_supported_metrics,
     regression_supported_metrics,
@@ -24,6 +24,7 @@
 PREDICTOR_TIME_TO_EVENT = "time_to_event.dynamic_deephit"
 
 
+@pytest.mark.filterwarnings("ignore:.*All-NaN.*:RuntimeWarning")  # Expected matplotlib warnings.
 @pytest.mark.filterwarnings("ignore:.*Matplotlib.*:UserWarning")
 @pytest.mark.parametrize("data", TEST_ON_DATASETS_CLASSIFIER)
 def test_classifier_benchmark(data: str, request: pytest.FixtureRequest) -> None:
@@ -67,7 +68,7 @@ def test_classifier_benchmark(data: str, request: pytest.FixtureRequest) -> None
     if not sys.platform.startswith(("win", "darwin")):
         # TODO: There appears to be a problem running this on GH runners for Windows and MaxOS, hence disabled.
         # Investigate and resolve.
-        visualize_benchmark(per_test_score)
+        visualize_benchmark(per_test_score, plot_block=False)
 
 
 @pytest.mark.parametrize("data", TEST_ON_DATASETS_REGRESSOR)
diff --git a/tests/core/test_core_utils.py b/tests/core/test_core_utils.py
index 979aa20a..6ecfb8f1 100644
--- a/tests/core/test_core_utils.py
+++ b/tests/core/test_core_utils.py
@@ -1,4 +1,5 @@
 import re
+from typing import Callable
 
 import pytest
 from typing_extensions import Literal
@@ -52,89 +53,142 @@ class MyArgument:
     pass
 
 
-def my_function(*args, **kwargs):
+def get_from_args_or_kwargs_preset_prefer_raise(*args, **kwargs):
     value, args, kwargs = utils.get_from_args_or_kwargs(
-        args, kwargs, argument_name="my_arg", argument_type=MyArgument, position_if_args=0
+        args,
+        kwargs,
+        argument_name="my_arg",
+        argument_type=MyArgument,
+        position_if_args=0,
+        prefer="raise",
+    )
+    return value, args, kwargs
+
+
+def get_from_args_or_kwargs_preset_prefer_kwarg(*args, **kwargs):
+    value, args, kwargs = utils.get_from_args_or_kwargs(
+        args,
+        kwargs,
+        argument_name="my_arg",
+        argument_type=MyArgument,
+        position_if_args=0,
+        prefer="kwarg",
+    )
+    return value, args, kwargs
+
+
+def get_from_args_or_kwargs_preset_prefer_arg(*args, **kwargs):
+    value, args, kwargs = utils.get_from_args_or_kwargs(
+        args,
+        kwargs,
+        argument_name="my_arg",
+        argument_type=MyArgument,
+        position_if_args=0,
+        prefer="arg",
     )
     return value, args, kwargs
 
 
 class TestGetFromArgsOrKwargs:
-    def test_get_from_args(self):
+    @pytest.mark.parametrize(
+        "preset",
+        [
+            get_from_args_or_kwargs_preset_prefer_raise,
+            get_from_args_or_kwargs_preset_prefer_arg,
+            get_from_args_or_kwargs_preset_prefer_kwarg,
+        ],
+    )
+    def test_get_from_args(self, preset: Callable):
         my_arg = MyArgument()
 
-        value, args, kwargs = my_function(my_arg)
+        value, args, kwargs = preset(my_arg)
         assert value is my_arg
         assert value not in args and "my_arg" not in kwargs
         assert args == tuple()
         assert kwargs == dict()
 
-        value, args, kwargs = my_function(my_arg, "bar", "baz")
+        value, args, kwargs = preset(my_arg, "bar", "baz")
         assert value is my_arg
         assert value not in args and "my_arg" not in kwargs
         assert args == tuple(["bar", "baz"])
         assert kwargs == dict()
 
-        value, args, kwargs = my_function(my_arg, foobar="foobar", foobaz="foobaz")
+        value, args, kwargs = preset(my_arg, foobar="foobar", foobaz="foobaz")
         assert value is my_arg
         assert value not in args and "my_arg" not in kwargs
         assert args == tuple()
         assert kwargs == dict(foobar="foobar", foobaz="foobaz")
 
-        value, args, kwargs = my_function(my_arg, "bar", "baz", foobar="foobar", foobaz="foobaz")
+        value, args, kwargs = preset(my_arg, "bar", "baz", foobar="foobar", foobaz="foobaz")
         assert value is my_arg
         assert value not in args and "my_arg" not in kwargs
         assert args == tuple(["bar", "baz"])
         assert kwargs == dict(foobar="foobar", foobaz="foobaz")
 
-    def test_get_from_kwargs(self):
+    @pytest.mark.parametrize(
+        "preset",
+        [
+            get_from_args_or_kwargs_preset_prefer_raise,
+            get_from_args_or_kwargs_preset_prefer_arg,
+            get_from_args_or_kwargs_preset_prefer_kwarg,
+        ],
+    )
+    def test_get_from_kwargs(self, preset: Callable):
         my_arg = MyArgument()
 
-        value, args, kwargs = my_function(my_arg=my_arg)
+        value, args, kwargs = preset(my_arg=my_arg)
         assert value is my_arg
         assert value not in args and "my_arg" not in kwargs
         assert args == tuple()
         assert kwargs == dict()
 
-        value, args, kwargs = my_function("bar", "baz", my_arg=my_arg)
+        value, args, kwargs = preset("bar", "baz", my_arg=my_arg)
         assert value is my_arg
         assert value not in args and "my_arg" not in kwargs
         assert args == tuple(["bar", "baz"])
         assert kwargs == dict()
 
-        value, args, kwargs = my_function(my_arg=my_arg, foobar="foobar", foobaz="foobaz")
+        value, args, kwargs = preset(my_arg=my_arg, foobar="foobar", foobaz="foobaz")
         assert value is my_arg
         assert value not in args and "my_arg" not in kwargs
         assert args == tuple()
         assert kwargs == dict(foobar="foobar", foobaz="foobaz")
 
-        value, args, kwargs = my_function("bar", "baz", my_arg=my_arg, foobar="foobar", foobaz="foobaz")
+        value, args, kwargs = preset("bar", "baz", my_arg=my_arg, foobar="foobar", foobaz="foobaz")
         assert value is my_arg
         assert value not in args and "my_arg" not in kwargs
         assert args == tuple(["bar", "baz"])
         assert kwargs == dict(foobar="foobar", foobaz="foobaz")
 
-    def test_no_argument(self):
-        value, args, kwargs = my_function()
+    @pytest.mark.parametrize(
+        "preset",
+        [
+            get_from_args_or_kwargs_preset_prefer_raise,
+            get_from_args_or_kwargs_preset_prefer_arg,
+            get_from_args_or_kwargs_preset_prefer_kwarg,
+        ],
+    )
+    def test_no_argument(self, preset: Callable):
+        value, args, kwargs = preset()
         assert value is None
         assert args == tuple()
         assert kwargs == dict()
 
-        value, args, kwargs = my_function(12345)
+        value, args, kwargs = preset(12345)
         assert value is None
         assert args == tuple([12345])
         assert kwargs == dict()
 
-        value, args, kwargs = my_function(12345, "abc")
+        value, args, kwargs = preset(12345, "abc")
         assert value is None
         assert args == tuple([12345, "abc"])
         assert kwargs == dict()
 
-        value, args, kwargs = my_function(foobar=999, foobaz="foobaz")
+        value, args, kwargs = preset(foobar=999, foobaz="foobaz")
         assert args == tuple()
         assert kwargs == dict(foobar=999, foobaz="foobaz")
 
-        value, args, kwargs = my_function("abc", -12345, foobar=999, foobaz="foobaz")
+        value, args, kwargs = preset("abc", -12345, foobar=999, foobaz="foobaz")
         assert value is None
         assert args == tuple(["abc", -12345])
         assert kwargs == dict(foobar=999, foobaz="foobaz")
@@ -143,11 +197,43 @@ def test_exception_passed_as_both(self):
         my_arg = MyArgument()
 
         with pytest.raises(RuntimeError, match=".*as `kwargs`.*as `args`.*"):
-            my_function(my_arg, "bar", my_arg=my_arg, foobaz=1234)
+            get_from_args_or_kwargs_preset_prefer_raise(my_arg, "bar", my_arg=my_arg, foobaz=1234)
+
+    def test_prefer_kwarg_behavior(self):
+        my_arg_passed_as_arg = MyArgument()
+        my_arg_passed_as_kwarg = MyArgument()
+
+        value, args, kwargs = get_from_args_or_kwargs_preset_prefer_kwarg(
+            my_arg_passed_as_arg, "bar", 0.123, foobar="foobar", my_arg=my_arg_passed_as_kwarg, foobaz=1234
+        )
+
+        assert value == my_arg_passed_as_kwarg
+        assert args == tuple([my_arg_passed_as_arg, "bar", 0.123])
+        assert kwargs == dict(foobar="foobar", foobaz=1234)
+
+    def test_prefer_arg_behavior(self):
+        my_arg_passed_as_arg = MyArgument()
+        my_arg_passed_as_kwarg = MyArgument()
+
+        value, args, kwargs = get_from_args_or_kwargs_preset_prefer_arg(
+            my_arg_passed_as_arg, "bar", 0.123, foobar="foobar", my_arg=my_arg_passed_as_kwarg, foobaz=1234
+        )
 
-    def test_exception_kwargs_wrong_type(self):
+        assert value == my_arg_passed_as_arg
+        assert args == tuple(["bar", 0.123])
+        assert kwargs == dict(foobar="foobar", my_arg=my_arg_passed_as_kwarg, foobaz=1234)
+
+    @pytest.mark.parametrize(
+        "preset",
+        [
+            get_from_args_or_kwargs_preset_prefer_raise,
+            get_from_args_or_kwargs_preset_prefer_arg,
+            get_from_args_or_kwargs_preset_prefer_kwarg,
+        ],
+    )
+    def test_exception_kwargs_wrong_type(self, preset: Callable):
         with pytest.raises(TypeError, match=".*`kwargs`.*type.*"):
-            my_function("bar", "baz", my_arg="str", foobaz=1234)
+            preset("bar", "baz", my_arg="str", foobaz=1234)
 
 
 # Test get_from_args_or_kwargs (end) -----
@@ -173,3 +259,14 @@ def test_builtin(self):
 
 
 # Test get_class_full_name (end) ----------
+
+
+class TestUniqueInOrderOfAppearance:
+    def test_strs(self):
+        assert utils.unique_in_order_of_appearance(["a", "a", "b", "c", "c", "a", "b"]) == ["a", "b", "c"]
+
+    def test_ints(self):
+        assert utils.unique_in_order_of_appearance([1, 2, 2, 3, 3, 1, 1, 2]) == [1, 2, 3]
+
+    def test_mixed(self):
+        assert utils.unique_in_order_of_appearance([1, "a", 2, "a", 2, 3, 3, 1, 1, 2]) == [1, "a", 2, 3]
diff --git a/tests/plugins/core/test_base_estimator.py b/tests/plugins/core/test_base_estimator.py
index 5bda8dde..0d7422bc 100644
--- a/tests/plugins/core/test_base_estimator.py
+++ b/tests/plugins/core/test_base_estimator.py
@@ -25,6 +25,7 @@ def test_init_success_empty_params_definition_model(self):
         class MyModel(tempor.plugins.core.BaseEstimator):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
 
             @staticmethod
             def hyperparameter_space(*args: Any, **kwargs: Any):
@@ -43,6 +44,7 @@ class MyModel(tempor.plugins.core.BaseEstimator):
             ParamsDefinition = self.MyModelParams
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
 
             @staticmethod
             def hyperparameter_space(*args: Any, **kwargs: Any):
@@ -59,6 +61,7 @@ def test_init_success_params_provided(self):
         class MyModel(tempor.plugins.core.BaseEstimator):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
@@ -76,6 +79,7 @@ def test_init_success_no_default_and_provided(self):
         class MyModel(tempor.plugins.core.BaseEstimator):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
 
             ParamsDefinition = self.MyModelParamsWithNoDefault
 
@@ -93,6 +97,7 @@ def test_init_fails_no_default_and_not_provided(self):
         class MyModel(tempor.plugins.core.BaseEstimator):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParamsWithNoDefault
 
             @staticmethod
@@ -110,6 +115,7 @@ def test_init_fails_omegaconf_incompatible_type(self):
         class MyModel(tempor.plugins.core.BaseEstimator):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
@@ -126,6 +132,7 @@ def test_init_fails_wrong_type(self):
         class MyModel(tempor.plugins.core.BaseEstimator):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
@@ -142,6 +149,7 @@ def test_repr(self):
         class MyModel(tempor.plugins.core.BaseEstimator):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
@@ -164,6 +172,7 @@ def test_fit(self):
         class MyModel(tempor.plugins.core.BaseEstimator):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
@@ -188,6 +197,7 @@ def test_fit_fails_data_not_fit_ready(self):
         class MyModel(tempor.plugins.core.BaseEstimator):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
@@ -214,6 +224,7 @@ def test_sample_hyperparameters(self, override):
         class MyModel(tempor.plugins.core.BaseEstimator):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
diff --git a/tests/plugins/core/test_base_predictor.py b/tests/plugins/core/test_base_predictor.py
index 06d2bfe5..0d86c936 100644
--- a/tests/plugins/core/test_base_predictor.py
+++ b/tests/plugins/core/test_base_predictor.py
@@ -19,6 +19,7 @@ def test_predict(self):
         class MyModel(tempor.plugins.core.BasePredictor):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
@@ -53,6 +54,7 @@ def test_fit_predict(self):
         class MyModel(tempor.plugins.core.BasePredictor):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
@@ -83,6 +85,7 @@ def test_predict_fails_data_not_fitted(self):
         class MyModel(tempor.plugins.core.BasePredictor):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
@@ -118,6 +121,7 @@ def test_predict_fails_data_not_fit_ready(self):
         class MyModel(tempor.plugins.core.BasePredictor):
             name = "my_model"
             category = "my_category"
+            plugin_type = "my_plugin_type"
             ParamsDefinition = self.MyModelParams
 
             @staticmethod
diff --git a/tests/plugins/core/test_importing.py b/tests/plugins/core/test_importing.py
index 704ba189..02acddc8 100644
--- a/tests/plugins/core/test_importing.py
+++ b/tests/plugins/core/test_importing.py
@@ -44,6 +44,20 @@ class DummyPluginTempor(plugin_core.Plugin):
 
 """
 
+plugin_different_type_file = """
+import tempor.plugins.core._plugin as plugin_core
+
+
+@plugin_core.register_plugin(
+    name="dummy_different_type_plugin",
+    category="dummy_different_type_category",
+    plugin_type="my_plugin_type",
+)
+class DummyPluginDifferentCategory(plugin_core.Plugin):
+    pass
+
+"""
+
 
 def test_import_plugins(tmp_path: pathlib.Path, patch_plugins_core_module):
     test_plugins_dir = tmp_path / tempor.import_name / "dummy_plugins"
@@ -54,8 +68,13 @@ def test_import_plugins(tmp_path: pathlib.Path, patch_plugins_core_module):
         f.write(plugin_file_2)
     with open(test_plugins_dir / "plugin_tempor_file.py", "w", encoding="utf8") as f:
         f.write(plugin_tempor_file)
+    with open(test_plugins_dir / "plugin_different_type_file.py", "w", encoding="utf8") as f:
+        f.write(plugin_different_type_file)
 
     plugin_core.register_plugin_category("dummy_category", expected_class=plugin_core.Plugin)
+    plugin_core.register_plugin_category(
+        "dummy_different_type_category", expected_class=plugin_core.Plugin, plugin_type="my_plugin_type"
+    )
 
     init_file = os.path.join(str(test_plugins_dir), "__init__.py")
     plugin_core.importing.import_plugins(init_file)
@@ -63,15 +82,17 @@ def test_import_plugins(tmp_path: pathlib.Path, patch_plugins_core_module):
 
     assert sorted(
         [
-            "dummy_category.dummy_plugin_a",
-            "dummy_category.dummy_plugin_b",
-            "dummy_category.dummy_plugin_c",
-            "dummy_category.dummy_tempor_plugin",
+            f"[{plugin_core.DEFAULT_PLUGIN_TYPE}].dummy_category.dummy_plugin_a",
+            f"[{plugin_core.DEFAULT_PLUGIN_TYPE}].dummy_category.dummy_plugin_b",
+            f"[{plugin_core.DEFAULT_PLUGIN_TYPE}].dummy_category.dummy_plugin_c",
+            f"[{plugin_core.DEFAULT_PLUGIN_TYPE}].dummy_category.dummy_tempor_plugin",
+            "[my_plugin_type].dummy_different_type_category.dummy_different_type_plugin",
         ]
     ) == sorted(plugin_core.PLUGIN_REGISTRY.keys())
 
     assert sorted(
         [
+            "tempor.dummy_plugins.plugin_different_type_file",
             "tempor.dummy_plugins.plugin_tempor_file",
             "tempor.dummy_plugins.plugin_file_2",
             "tempor.dummy_plugins.plugin_file_1",
diff --git a/tests/plugins/core/test_plugins.py b/tests/plugins/core/test_plugins.py
index fce1f69d..0158032e 100644
--- a/tests/plugins/core/test_plugins.py
+++ b/tests/plugins/core/test_plugins.py
@@ -1,4 +1,4 @@
-# pylint: disable=unused-argument
+# pylint: disable=unused-argument,protected-access
 
 from unittest.mock import Mock
 
@@ -8,31 +8,151 @@
 from tempor.plugins import plugin_loader
 
 
+class TestHelpers:
+    def test_parse_plugin_type(self):
+        plugin_type_normal = plugin_core.parse_plugin_type("my_plugin_type", must_be_one_of=None)
+        assert plugin_type_normal == "my_plugin_type"
+
+        plugin_type_default = plugin_core.parse_plugin_type(None, must_be_one_of=None)
+        assert plugin_type_default == plugin_core.DEFAULT_PLUGIN_TYPE
+
+        with pytest.raises(ValueError, match=".*all.*reserved.*"):
+            plugin_core.parse_plugin_type("all", must_be_one_of=None)
+
+        plugin_type_must_be_one_of_ok = plugin_core.parse_plugin_type("a", must_be_one_of=["a", "b", "c"])
+        assert plugin_type_must_be_one_of_ok == "a"
+
+        with pytest.raises(ValueError, match=".*Plugin type.*one of.*"):
+            plugin_core.parse_plugin_type("x", must_be_one_of=["a", "b", "c"])
+
+    def test_create_fqn(self):
+        fqn = plugin_core.create_fqn(suffix="my_category.my_subcategory.my_plugin", plugin_type="my_plugin_type")
+        assert fqn == "[my_plugin_type].my_category.my_subcategory.my_plugin"
+
+    def test_create_fqn_fails_plugin_type_none(self):
+        with pytest.raises(ValueError, match=".*[Pp]lugin type.*None.*"):
+            plugin_core.create_fqn(suffix="my_category.my_subcategory.my_plugin", plugin_type=None)
+
+    def test_filter_list_by_plugin_type(self):
+        lst = [
+            "[my_plugin_type_A].my_category.my_subcategory.my_plugin_A1",
+            "[my_plugin_type_A].my_category.my_subcategory.my_plugin_A2",
+            "[my_plugin_type_B].my_category.my_subcategory.my_plugin_B1",
+            "random.stuff",
+        ]
+        filtered_A = plugin_core.filter_list_by_plugin_type(lst, plugin_type="my_plugin_type_A")
+        filtered_B = plugin_core.filter_list_by_plugin_type(lst, plugin_type="my_plugin_type_B")
+        assert filtered_A == [
+            "[my_plugin_type_A].my_category.my_subcategory.my_plugin_A1",
+            "[my_plugin_type_A].my_category.my_subcategory.my_plugin_A2",
+        ]
+        assert filtered_B == ["[my_plugin_type_B].my_category.my_subcategory.my_plugin_B1"]
+
+    def test_filter_dict_by_plugin_type(self):
+        d = {
+            "[my_plugin_type_A].my_category.my_subcategory.my_plugin_A1": "foo",
+            "[my_plugin_type_A].my_category.my_subcategory.my_plugin_A2": "bar",
+            "[my_plugin_type_B].my_category.my_subcategory.my_plugin_B1": "baz",
+            "random.stuff": "qux",
+        }
+        filtered_A = plugin_core.filter_dict_by_plugin_type(d, plugin_type="my_plugin_type_A")
+        filtered_B = plugin_core.filter_dict_by_plugin_type(d, plugin_type="my_plugin_type_B")
+        assert filtered_A == {
+            "[my_plugin_type_A].my_category.my_subcategory.my_plugin_A1": "foo",
+            "[my_plugin_type_A].my_category.my_subcategory.my_plugin_A2": "bar",
+        }
+        assert filtered_B == {"[my_plugin_type_B].my_category.my_subcategory.my_plugin_B1": "baz"}
+
+    def test_remove_plugin_type_from_fqn_success(self):
+        plugin_fqn = "[my_plugin_type].my_category.my_subcategory.my_plugin"
+        plugin_fqn_without_plugin_type = plugin_core.remove_plugin_type_from_fqn(plugin_fqn)
+        assert plugin_fqn_without_plugin_type == "my_category.my_subcategory.my_plugin"
+
+        category_fqn = "[my_plugin_type].my_category"
+        category_fqn_without_plugin_type = plugin_core.remove_plugin_type_from_fqn(category_fqn)
+        assert category_fqn_without_plugin_type == "my_category"
+
+    def test_remove_plugin_type_from_fqn_fails_incorrect_format(self):
+        fqn_incorrect_format = "/my_plugin_type>.my_category.my_subcategory.my_plugin"
+        with pytest.raises(ValueError, match=".*FQN.*incorrect.*"):
+            plugin_core.remove_plugin_type_from_fqn(fqn_incorrect_format)
+
+    def test_get_plugin_type_from_fqn(self):
+        plugin_fqn = "[my_plugin_type].my_category.my_subcategory.my_plugin"
+        plugin_fqn_without_plugin_type = plugin_core.get_plugin_type_from_fqn(plugin_fqn)
+        assert plugin_fqn_without_plugin_type == "my_plugin_type"
+
+        category_fqn = "[my_plugin_type].my_category"
+        category_fqn_without_plugin_type = plugin_core.get_plugin_type_from_fqn(category_fqn)
+        assert category_fqn_without_plugin_type == "my_plugin_type"
+
+
 class TestPluginClass:
-    def test_plugin_init_fails_no_name(self):
+    def test_init_success(self):
+        class NamelessPlugin(plugin_core.Plugin):
+            name = "my_name"
+            category = "my_category"
+            plugin_type = "my_plugin_type"
+
+        p = NamelessPlugin()
+        assert p.name == "my_name"
+        assert p.category == "my_category"
+        assert p.plugin_type == "my_plugin_type"
+
+    def test_name_helpers(self):
+        class NamelessPlugin(plugin_core.Plugin):
+            name = "my_name"
+            category = "my_category"
+            plugin_type = "my_plugin_type"
+
+        p = NamelessPlugin()
+
+        # Full name of plugin as user sees it:
+        assert p.full_name() == "my_category.my_name"
+        # FQN of plugin internally:
+        assert p._fqn() == "[my_plugin_type].my_category.my_name"
+        # FQN of plugin's category internally:
+        assert p._category_fqn() == "[my_plugin_type].my_category"
+
+    def test_init_fails_no_name(self):
         class NamelessPlugin(plugin_core.Plugin):
             category = "category_was_set"
+            plugin_type = "plugin_type_was_set"
 
         with pytest.raises(ValueError, match=".*name.*not set.*"):
             NamelessPlugin()
 
-    def test_plugin_init_fails_no_category(self):
+    def test_init_fails_no_category(self):
         class CategorylessPlugin(plugin_core.Plugin):
             name = "name_was_set"
+            plugin_type = "plugin_type_was_set"
 
         with pytest.raises(ValueError, match=".*category.*not set.*"):
             CategorylessPlugin()
 
+    def test_init_fails_no_plugin_type(self):
+        class PluginTypelessPlugin(plugin_core.Plugin):
+            name = "name_was_set"
+            category = "category_was_set"
+
+        with pytest.raises(ValueError, match=".*plugin_type.*not set.*"):
+            PluginTypelessPlugin()
+
 
 class TestRegistration:
     @pytest.fixture(autouse=True)
     def always_patch_module_in_this_test_class(self, patch_plugins_core_module):
         pass
 
+    def test_default_plugin_type(self):
+        assert plugin_core.DEFAULT_PLUGIN_TYPE == "method"
+
     def test_register_plugin_and_category_success(self):
-        plugin_core.register_plugin_category("dummy_category", expected_class=plugin_core.Plugin)
+        plugin_core.register_plugin_category(
+            "dummy_category", expected_class=plugin_core.Plugin, plugin_type="dummy_type"
+        )
 
-        @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category")
+        @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category", plugin_type="dummy_type")
         class DummyPlugin(plugin_core.Plugin):
             pass
 
@@ -41,82 +161,144 @@ class DummyPlugin(plugin_core.Plugin):
         assert isinstance(plugin, plugin_core.Plugin)
         assert plugin.name == "dummy_plugin"
         assert plugin.category == "dummy_category"
+        assert plugin.plugin_type == "dummy_type"
 
-        fqn = plugin.fqn()
+        full_name = plugin.full_name()
+        fqn = plugin._fqn()
 
-        assert fqn == "dummy_category.dummy_plugin"
+        assert full_name == "dummy_category.dummy_plugin"
 
-        assert "dummy_category" in plugin_core.PLUGIN_CATEGORY_REGISTRY
+        assert "[dummy_type].dummy_category" in plugin_core.PLUGIN_CATEGORY_REGISTRY
         assert fqn in plugin_core.PLUGIN_REGISTRY
 
-        assert plugin_core.PLUGIN_CATEGORY_REGISTRY["dummy_category"] == plugin_core.Plugin
+        assert plugin_core.PLUGIN_CATEGORY_REGISTRY["[dummy_type].dummy_category"] == plugin_core.Plugin
         assert plugin_core.PLUGIN_REGISTRY[fqn] == DummyPlugin
 
-    def test_register_multiple_plugins_and_categories_success(self):
-        plugin_core.register_plugin_category("dummy_category_A", expected_class=plugin_core.Plugin)
+    def test_register_multiple_plugins_and_categories_and_types_success(self):
+        plugin_core.register_plugin_category(
+            "dummy_category_A", expected_class=plugin_core.Plugin, plugin_type="dummy_type_X"
+        )
+
+        @plugin_core.register_plugin(name="dummy_plugin_A1", category="dummy_category_A", plugin_type="dummy_type_X")
+        class DummyXPluginA1(plugin_core.Plugin):
+            pass
 
-        @plugin_core.register_plugin(name="dummy_plugin_A1", category="dummy_category_A")
-        class DummyPluginA1(plugin_core.Plugin):
+        @plugin_core.register_plugin(name="dummy_plugin_A2", category="dummy_category_A", plugin_type="dummy_type_X")
+        class DummyXPluginA2(plugin_core.Plugin):
             pass
 
-        @plugin_core.register_plugin(name="dummy_plugin_A2", category="dummy_category_A")
-        class DummyPluginA2(plugin_core.Plugin):
+        plugin_core.register_plugin_category(
+            "dummy_category_B", expected_class=plugin_core.Plugin, plugin_type="dummy_type_X"
+        )
+
+        @plugin_core.register_plugin(name="dummy_plugin_B1", category="dummy_category_B", plugin_type="dummy_type_X")
+        class DummyXPluginB1(plugin_core.Plugin):
             pass
 
-        plugin_core.register_plugin_category("dummy_category_B", expected_class=plugin_core.Plugin)
+        plugin_core.register_plugin_category(
+            "dummy_category_C", expected_class=plugin_core.Plugin, plugin_type="dummy_type_Y"
+        )
 
-        @plugin_core.register_plugin(name="dummy_plugin_B1", category="dummy_category_B")
-        class DummyPluginB1(plugin_core.Plugin):
+        @plugin_core.register_plugin(name="dummy_plugin_C1", category="dummy_category_C", plugin_type="dummy_type_Y")
+        class DummyYPluginC1(plugin_core.Plugin):
             pass
 
-        p_a1 = DummyPluginA1()
-        p_a2 = DummyPluginA2()
-        p_b1 = DummyPluginB1()
+        pX_a1 = DummyXPluginA1()
+        pX_a2 = DummyXPluginA2()
+        pX_b1 = DummyXPluginB1()
+        pY_c1 = DummyYPluginC1()
 
-        assert plugin_core.PLUGIN_CATEGORY_REGISTRY["dummy_category_A"] == plugin_core.Plugin
-        assert plugin_core.PLUGIN_CATEGORY_REGISTRY["dummy_category_B"] == plugin_core.Plugin
-        assert plugin_core.PLUGIN_REGISTRY[p_a1.fqn()] == DummyPluginA1
-        assert plugin_core.PLUGIN_REGISTRY[p_a2.fqn()] == DummyPluginA2
-        assert plugin_core.PLUGIN_REGISTRY[p_b1.fqn()] == DummyPluginB1
+        assert plugin_core.PLUGIN_CATEGORY_REGISTRY["[dummy_type_X].dummy_category_A"] == plugin_core.Plugin
+        assert plugin_core.PLUGIN_CATEGORY_REGISTRY["[dummy_type_X].dummy_category_B"] == plugin_core.Plugin
+        assert plugin_core.PLUGIN_CATEGORY_REGISTRY["[dummy_type_Y].dummy_category_C"] == plugin_core.Plugin
+        assert plugin_core.PLUGIN_REGISTRY[pX_a1._fqn()] == DummyXPluginA1
+        assert plugin_core.PLUGIN_REGISTRY[pX_a2._fqn()] == DummyXPluginA2
+        assert plugin_core.PLUGIN_REGISTRY[pX_b1._fqn()] == DummyXPluginB1
+        assert plugin_core.PLUGIN_REGISTRY[pY_c1._fqn()] == DummyYPluginC1
 
     def test_category_registration_reimport_allowed(self):
-        plugin_core.register_plugin_category("dummy_category", expected_class=plugin_core.Plugin)
+        plugin_core.register_plugin_category(
+            "dummy_category", expected_class=plugin_core.Plugin, plugin_type="dummy_type"
+        )
 
-        @plugin_core.register_plugin(name="dummy_plugin_A", category="dummy_category")
+        @plugin_core.register_plugin(name="dummy_plugin_A", category="dummy_category", plugin_type="dummy_type")
         class DummyPluginA(plugin_core.Plugin):  # type: ignore  # pylint: disable=unused-variable
             pass
 
-        @plugin_core.register_plugin(name="dummy_plugin_A", category="dummy_category")
+        @plugin_core.register_plugin(name="dummy_plugin_A", category="dummy_category", plugin_type="dummy_type")
         # pylint: disable-next=function-redefined
         class DummyPluginA(plugin_core.Plugin):  # type: ignore  # pyright: ignore  # noqa: F811
             pass
 
     def test_category_registration_fails_duplicate(self):
-        plugin_core.register_plugin_category("same_category", expected_class=plugin_core.Plugin)
+        plugin_core.register_plugin_category(
+            "same_category", expected_class=plugin_core.Plugin, plugin_type="same_type"
+        )
 
         with pytest.raises(TypeError, match=".*category.*already registered.*"):
-            plugin_core.register_plugin_category("same_category", expected_class=plugin_core.Plugin)
+            plugin_core.register_plugin_category(
+                "same_category", expected_class=plugin_core.Plugin, plugin_type="same_type"
+            )
+
+    def test_diff_plugin_types_same_category_registration_ok(self):
+        plugin_core.register_plugin_category(
+            "same_category_name", expected_class=plugin_core.Plugin, plugin_type="dummy_type_X"
+        )
+
+        @plugin_core.register_plugin(name="dummy_plugin_A", category="same_category_name", plugin_type="dummy_type_X")
+        class DummyPluginA(plugin_core.Plugin):  # type: ignore  # pylint: disable=unused-variable
+            pass
+
+        plugin_core.register_plugin_category(
+            "same_category_name", expected_class=plugin_core.Plugin, plugin_type="dummy_type_Y"
+        )
+
+        @plugin_core.register_plugin(name="dummy_plugin_B", category="same_category_name", plugin_type="dummy_type_Y")
+        # pylint: disable-next=function-redefined
+        class DummyPluginA(plugin_core.Plugin):  # type: ignore  # pyright: ignore  # noqa: F811
+            pass
 
     def test_category_registration_fails_not_plugin(self):
         class DoesNotInheritPlugin:
             pass
 
         with pytest.raises(TypeError, match=".*subclass.*Plugin.*"):
-            plugin_core.register_plugin_category("dummy_category", expected_class=DoesNotInheritPlugin)
+            plugin_core.register_plugin_category(
+                "dummy_category", expected_class=DoesNotInheritPlugin, plugin_type="dummy_type"
+            )
 
     def test_plugin_registration_fails_unknown_category(self):
         with pytest.raises(TypeError, match=".*category.*not.*registered.*"):
 
-            @plugin_core.register_plugin(name="dummy_plugin", category="category_not_registered")
+            @plugin_core.register_plugin(
+                name="dummy_plugin", category="category_not_registered", plugin_type="dummy_type"
+            )
             class DummyPlugin(plugin_core.Plugin):  # pylint: disable=unused-variable
                 pass
 
+        with pytest.raises(TypeError, match=".*category.*not.*registered.*"):
+            plugin_core.register_plugin_category(
+                "category_registered", expected_class=plugin_core.Plugin, plugin_type="but_different_type"
+            )
+
+            @plugin_core.register_plugin(
+                name="dummy_plugin", category="category_registered", plugin_type="but_not_for_this_type"
+            )
+            class AnotherDummyPlugin(plugin_core.Plugin):  # pylint: disable=unused-variable
+                pass
+
     def test_plugin_registration_fails_not_plugin(self):
-        plugin_core.register_plugin_category("dummy_category", expected_class=plugin_core.Plugin)
+        plugin_core.register_plugin_category(
+            "dummy_category", expected_class=plugin_core.Plugin, plugin_type="dummy_type"
+        )
 
         with pytest.raises(TypeError, match=".*[Ee]xpected.*subclass.*Plugin.*"):
 
-            @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category")  # type: ignore
+            @plugin_core.register_plugin(
+                name="dummy_plugin",
+                category="dummy_category",
+                plugin_type="dummy_type",
+            )
             class DoesNotInheritPlugin:  # pylint: disable=unused-variable
                 pass
 
@@ -124,64 +306,172 @@ def test_plugin_registration_fails_wrong_class_for_category(self):
         class ExpectedClassForDummyCategory(plugin_core.Plugin):
             pass
 
-        plugin_core.register_plugin_category("dummy_category", expected_class=ExpectedClassForDummyCategory)
+        plugin_core.register_plugin_category(
+            "dummy_category", expected_class=ExpectedClassForDummyCategory, plugin_type="dummy_type"
+        )
 
         with pytest.raises(TypeError, match=".*[Ee]xpected.*subclass.*ExpectedClassForDummyCategory.*"):
 
-            @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category")
+            @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category", plugin_type="dummy_type")
             class UnexpectedClassPlugin(plugin_core.Plugin):  # pylint: disable=unused-variable
                 pass
 
     def test_plugin_registration_fails_duplicate_fqn(
         self,
     ):
-        plugin_core.register_plugin_category("dummy_category", expected_class=plugin_core.Plugin)
+        plugin_core.register_plugin_category(
+            "dummy_category", expected_class=plugin_core.Plugin, plugin_type="dummy_type"
+        )
 
-        @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category")
+        @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category", plugin_type="dummy_type")
         class DummyPlugin(plugin_core.Plugin):  # pylint: disable=unused-variable
             pass
 
-        with pytest.raises(TypeError, match=".*[Pp]lugin with fully-qualified name.*already registered.*"):
+        with pytest.raises(TypeError, match=".*[Pp]lugin.*with full name.*already been registered.*"):
 
-            @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category")
+            @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category", plugin_type="dummy_type")
             class DummyPluginDuplicate(plugin_core.Plugin):  # pylint: disable=unused-variable
                 pass
 
     def test_plugin_registration_fails_duplicate_name(
         self,
     ):
-        plugin_core.register_plugin_category("dummy_category", expected_class=plugin_core.Plugin)
-        plugin_core.register_plugin_category("dummy_category_2", expected_class=plugin_core.Plugin)
+        # NOTE: At some point this restriction might be lifted, at which point remove this test.
 
-        @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category")
+        plugin_core.register_plugin_category(
+            "dummy_category", expected_class=plugin_core.Plugin, plugin_type="dummy_type"
+        )
+        plugin_core.register_plugin_category(
+            "dummy_category_2", expected_class=plugin_core.Plugin, plugin_type="dummy_type"
+        )
+
+        @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category", plugin_type="dummy_type")
         class DummyPlugin(plugin_core.Plugin):  # pylint: disable=unused-variable
             pass
 
-        with pytest.raises(TypeError, match=".*[Pp]lugin with name.*already registered.*"):
+        with pytest.raises(TypeError, match=".*[Pp]lugin.*with name.*already been registered.*"):
 
-            @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category_2")
+            @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category_2", plugin_type="dummy_type")
             class DummyPluginDuplicate(plugin_core.Plugin):  # pylint: disable=unused-variable
                 pass
 
+    def test_default_plugin_type_value(self):
+        plugin_core.register_plugin_category("dummy_category", expected_class=plugin_core.Plugin)
+
+        @plugin_core.register_plugin(name="dummy_plugin", category="dummy_category")
+        class DummyPlugin(plugin_core.Plugin):
+            pass
+
+        plugin = DummyPlugin()
+
+        assert plugin.plugin_type == plugin_core.DEFAULT_PLUGIN_TYPE
+        assert plugin.full_name() == "dummy_category.dummy_plugin"
+        assert plugin._fqn() == f"[{plugin_core.DEFAULT_PLUGIN_TYPE}].dummy_category.dummy_plugin"
+        assert f"[{plugin_core.DEFAULT_PLUGIN_TYPE}].dummy_category" in plugin_core.PLUGIN_CATEGORY_REGISTRY
+
+
+# Prepare things for TestPluginLoader. ---
+
+plugin_type_foo = "plugin_type_foo"
+plugin_type_bar = "plugin_type_bar"
+category_a = "category_a"  # plugin_type_foo
+category_b_x = "category_b.x"  # plugin_type_foo
+category_b_y = "category_b.y"  # plugin_type_foo
+category_c = "category_c"  # plugin_type_bar
+PluginTypeFooCategoryAExpectedClass = Mock()
+PluginTypeFooCategoryBXExpectedClass = Mock()
+PluginTypeFooCategoryBYExpectedClass = Mock()
+PluginTypeBarCategoryCExpectedClass = Mock()
+
+
+class PluginFooA1(plugin_core.Plugin):
+    name = "plugin_a1"
+    category = category_a
+    plugin_type = plugin_type_foo
+
+
+MockPluginFooA1 = Mock(wraps=PluginFooA1)
+MockPluginFooA1.name = PluginFooA1.name
+
+
+class PluginFooA2(plugin_core.Plugin):
+    name = "plugin_a2"
+    category = category_a
+    plugin_type = plugin_type_foo
+
+    # For test_get():
+    def __init__(self, *args, **kwargs) -> None:
+        super().__init__()
+
+
+MockPluginFooA2 = Mock(wraps=PluginFooA2)
+MockPluginFooA2.name = PluginFooA2.name
 
-category_a = "category_a"
-category_b_x = "category_b.x"
-category_b_y = "category_b.y"
-CategoryAExpectedClass = Mock()
-CategoryBXExpectedClass = Mock()
-CategoryBYExpectedClass = Mock()
-PluginA1 = Mock(category=category_a)
-PluginA1.name = "plugin_a1"
-PluginA2 = Mock(category=category_a)
-PluginA2.name = "plugin_a2"
-PluginBX1 = Mock(category=category_b_x)
-PluginBX1.name = "plugin_bx1"
-PluginBX2 = Mock(category=category_b_x)
-PluginBX2.name = "plugin_bx2"
-PluginBY1 = Mock(category=category_b_y)
-PluginBY1.name = "plugin_by1"
-PluginBY2 = Mock(category=category_b_y)
-PluginBY2.name = "plugin_by2"
+
+class PluginFooBX1(plugin_core.Plugin):
+    name = "plugin_bx1"
+    category = category_b_x
+    plugin_type = plugin_type_foo
+
+
+MockPluginFooBX1 = Mock(wraps=PluginFooBX1)
+MockPluginFooBX1.name = PluginFooBX1.name
+
+
+class PluginFooBX2(plugin_core.Plugin):
+    name = "plugin_bx2"
+    category = category_b_x
+    plugin_type = plugin_type_foo
+
+
+MockPluginFooBX2 = Mock(wraps=PluginFooBX2)
+MockPluginFooBX2.name = PluginFooBX2.name
+
+
+class PluginFooBY1(plugin_core.Plugin):
+    name = "plugin_by1"
+    category = category_b_y
+    plugin_type = plugin_type_foo
+
+
+MockPluginFooBY1 = Mock(wraps=PluginFooBY1)
+MockPluginFooBY1.name = PluginFooBY1.name
+
+
+class PluginFooBY2(plugin_core.Plugin):
+    name = "plugin_by2"
+    category = category_b_y
+    plugin_type = plugin_type_foo
+
+    # For test_get():
+    def __init__(self, *args, **kwargs) -> None:
+        super().__init__()
+
+
+MockPluginFooBY2 = Mock(wraps=PluginFooBY2)
+MockPluginFooBY2.name = PluginFooBY2.name
+
+
+class PluginBarC1(plugin_core.Plugin):
+    name = "plugin_c1"
+    category = category_c
+    plugin_type = plugin_type_bar
+
+
+MockPluginBarC1 = Mock(wraps=PluginBarC1)
+MockPluginBarC1.name = PluginBarC1.name
+
+
+class PluginBarC2(plugin_core.Plugin):
+    name = "plugin_c2"
+    category = category_c
+    plugin_type = plugin_type_bar
+
+
+MockPluginBarC2 = Mock(wraps=PluginBarC2)
+MockPluginBarC2.name = PluginBarC2.name
+
+# Prepare things for TestPluginLoader (end). ---
 
 
 class TestPluginLoader:
@@ -192,24 +482,27 @@ def always_patch_module_in_this_test_class(self, patch_plugins_core_module):
     @pytest.fixture(autouse=True)
     def pre_fill_registry(self, always_patch_module_in_this_test_class):
         plugin_core.PLUGIN_CATEGORY_REGISTRY = {
-            category_a: CategoryAExpectedClass,
-            category_b_x: CategoryBXExpectedClass,
-            category_b_y: CategoryBYExpectedClass,
+            f"[{plugin_type_foo}].{category_a}": PluginTypeFooCategoryAExpectedClass,
+            f"[{plugin_type_foo}].{category_b_x}": PluginTypeFooCategoryBXExpectedClass,
+            f"[{plugin_type_foo}].{category_b_y}": PluginTypeFooCategoryBYExpectedClass,
+            f"[{plugin_type_bar}].{category_c}": PluginTypeBarCategoryCExpectedClass,
         }
         plugin_core.PLUGIN_REGISTRY = {
-            f"{PluginA1.category}.{PluginA1.name}": PluginA1,
-            f"{PluginA2.category}.{PluginA2.name}": PluginA2,
-            f"{PluginBX1.category}.{PluginBX1.name}": PluginBX1,
-            f"{PluginBX2.category}.{PluginBX2.name}": PluginBX2,
-            f"{PluginBY1.category}.{PluginBY1.name}": PluginBY1,
-            f"{PluginBY2.category}.{PluginBY2.name}": PluginBY2,
+            f"[{PluginFooA1.plugin_type}].{PluginFooA1.category}.{PluginFooA1.name}": MockPluginFooA1,
+            f"[{PluginFooA2.plugin_type}].{PluginFooA2.category}.{PluginFooA2.name}": MockPluginFooA2,
+            f"[{PluginFooBX1.plugin_type}].{PluginFooBX1.category}.{PluginFooBX1.name}": MockPluginFooBX1,
+            f"[{PluginFooBX2.plugin_type}].{PluginFooBX2.category}.{PluginFooBX2.name}": MockPluginFooBX2,
+            f"[{PluginFooBY1.plugin_type}].{PluginFooBY1.category}.{PluginFooBY1.name}": MockPluginFooBY1,
+            f"[{PluginFooBY2.plugin_type}].{PluginFooBY2.category}.{PluginFooBY2.name}": MockPluginFooBY2,
+            f"[{PluginBarC1.plugin_type}].{PluginBarC1.category}.{PluginBarC1.name}": MockPluginBarC1,
+            f"[{PluginBarC2.plugin_type}].{PluginBarC2.category}.{PluginBarC2.name}": MockPluginBarC2,
         }
 
     @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
     def test_list(self, loader):
-        listed = loader.list()
+        listed_foo = loader.list(plugin_type=plugin_type_foo)
 
-        assert listed == {
+        assert listed_foo == {
             "category_a": ["plugin_a1", "plugin_a2"],
             "category_b": {
                 "x": ["plugin_bx1", "plugin_bx2"],
@@ -217,23 +510,69 @@ def test_list(self, loader):
             },
         }
 
+        listed_bar = loader.list(plugin_type=plugin_type_bar)
+
+        assert listed_bar == {
+            "category_c": ["plugin_c1", "plugin_c2"],
+        }
+
+    @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
+    def test_list_all(self, loader):
+        listed_all = loader.list(plugin_type="all")
+
+        assert listed_all == {
+            plugin_type_foo: {
+                "category_a": ["plugin_a1", "plugin_a2"],
+                "category_b": {
+                    "x": ["plugin_bx1", "plugin_bx2"],
+                    "y": ["plugin_by1", "plugin_by2"],
+                },
+            },
+            plugin_type_bar: {
+                "category_c": ["plugin_c1", "plugin_c2"],
+            },
+        }
+
     @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
     def test_list_classes(self, loader):
-        listed = loader.list_classes()
+        listed_foo = loader.list_classes(plugin_type=plugin_type_foo)
 
-        assert listed == {
-            "category_a": [PluginA1, PluginA2],
+        assert listed_foo == {
+            "category_a": [MockPluginFooA1, MockPluginFooA2],
             "category_b": {
-                "x": [PluginBX1, PluginBX2],
-                "y": [PluginBY1, PluginBY2],
+                "x": [MockPluginFooBX1, MockPluginFooBX2],
+                "y": [MockPluginFooBY1, MockPluginFooBY2],
             },
         }
 
+        listed_bar = loader.list_classes(plugin_type=plugin_type_bar)
+
+        assert listed_bar == {
+            "category_c": [MockPluginBarC1, MockPluginBarC2],
+        }
+
     @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
-    def test_list_fqns(self, loader):
-        listed = loader.list_fqns()
+    def test_list_classes_all(self, loader):
+        listed_all = loader.list_classes(plugin_type="all")
+
+        assert listed_all == {
+            plugin_type_foo: {
+                "category_a": [MockPluginFooA1, MockPluginFooA2],
+                "category_b": {
+                    "x": [MockPluginFooBX1, MockPluginFooBX2],
+                    "y": [MockPluginFooBY1, MockPluginFooBY2],
+                },
+            },
+            plugin_type_bar: {
+                "category_c": [MockPluginBarC1, MockPluginBarC2],
+            },
+        }
 
-        assert listed == [
+    @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
+    def test_list_full_names(self, loader):
+        listed_foo = loader.list_full_names(plugin_type=plugin_type_foo)
+
+        assert listed_foo == [
             "category_a.plugin_a1",
             "category_a.plugin_a2",
             "category_b.x.plugin_bx1",
@@ -242,63 +581,186 @@ def test_list_fqns(self, loader):
             "category_b.y.plugin_by2",
         ]
 
+        listed_bar = loader.list_full_names(plugin_type=plugin_type_bar)
+
+        assert listed_bar == [
+            "category_c.plugin_c1",
+            "category_c.plugin_c2",
+        ]
+
+    @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
+    def test_list_full_names_all(self, loader):
+        listed_all = loader.list_full_names(plugin_type="all")
+
+        assert listed_all == {
+            plugin_type_foo: [
+                "category_a.plugin_a1",
+                "category_a.plugin_a2",
+                "category_b.x.plugin_bx1",
+                "category_b.x.plugin_bx2",
+                "category_b.y.plugin_by1",
+                "category_b.y.plugin_by2",
+            ],
+            plugin_type_bar: [
+                "category_c.plugin_c1",
+                "category_c.plugin_c2",
+            ],
+        }
+
     @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
     def test_list_categories(self, loader):
-        listed = loader.list_categories()
+        listed_foo = loader.list_categories(plugin_type=plugin_type_foo)
+
+        assert listed_foo == {
+            "category_a": PluginTypeFooCategoryAExpectedClass,
+            "category_b.x": PluginTypeFooCategoryBXExpectedClass,
+            "category_b.y": PluginTypeFooCategoryBYExpectedClass,
+        }
 
-        assert listed == {
-            "category_a": CategoryAExpectedClass,
-            "category_b.x": CategoryBXExpectedClass,
-            "category_b.y": CategoryBYExpectedClass,
+        listed_bar = loader.list_categories(plugin_type=plugin_type_bar)
+
+        assert listed_bar == {
+            "category_c": PluginTypeBarCategoryCExpectedClass,
+        }
+
+    @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
+    def test_list_categories_all(self, loader):
+        listed_all = loader.list_categories(plugin_type="all")
+
+        assert listed_all == {
+            plugin_type_foo: {
+                "category_a": PluginTypeFooCategoryAExpectedClass,
+                "category_b.x": PluginTypeFooCategoryBXExpectedClass,
+                "category_b.y": PluginTypeFooCategoryBYExpectedClass,
+            },
+            plugin_type_bar: {
+                "category_c": PluginTypeBarCategoryCExpectedClass,
+            },
         }
 
     @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
-    def test_get(self, loader):
+    def test_list_plugin_types(self, loader):
+        listed_types = loader.list_plugin_types()
+        assert listed_types == [plugin_type_foo, plugin_type_bar]
+
+    @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
+    def test_get_plugin_type_provided_as_kwarg(self, loader):
+        # Cases: plugin_type provided as kwarg:
+
+        plugin_a2_instance = loader.get(  # pylint: disable=unused-variable  # noqa: F841
+            "category_a.plugin_a2", "arg", 123, plugin_type="plugin_type_foo", kwarg1="kwarg1", kwarg2="kwarg2"
+        )
+        MockPluginFooA2.assert_called_once_with("arg", 123, kwarg1="kwarg1", kwarg2="kwarg2")
+        MockPluginFooA2.reset_mock()
+
+        plugin_by2_instance = loader.get(  # pylint: disable=unused-variable  # noqa: F841
+            name="category_b.y.plugin_by2", plugin_type="plugin_type_foo", kwarg1="kwarg1", kwarg2="kwarg2"
+        )
+        MockPluginFooBY2.assert_called_once_with(kwarg1="kwarg1", kwarg2="kwarg2")
+        MockPluginFooBY2.reset_mock()
+
+    @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
+    def test_get_plugin_type_provided_as_arg(self, loader):
+        # Cases: plugin_type provided as positional arg:
         plugin_a2_instance = loader.get(  # pylint: disable=unused-variable  # noqa: F841
-            "category_a.plugin_a2", "arg", kwarg="kwarg"
+            "category_a.plugin_a2", "plugin_type_foo", "arg", 123, kwarg1="kwarg1", kwarg2="kwarg2"
         )
-        PluginA2.assert_called_once_with("arg", kwarg="kwarg")
-        PluginA2.reset_mock()
+        MockPluginFooA2.assert_called_once_with("arg", 123, kwarg1="kwarg1", kwarg2="kwarg2")
+        MockPluginFooA2.reset_mock()
 
         plugin_by2_instance = loader.get(  # pylint: disable=unused-variable  # noqa: F841
-            name="category_b.y.plugin_by2", kwarg="kwarg"
+            "category_b.y.plugin_by2", "plugin_type_foo", "arg", 123, kwarg1="kwarg1", kwarg2="kwarg2"
         )
-        PluginBY2.assert_called_once_with(kwarg="kwarg")
-        PluginBY2.reset_mock()
+        MockPluginFooBY2.assert_called_once_with("arg", 123, kwarg1="kwarg1", kwarg2="kwarg2")
+        MockPluginFooBY2.reset_mock()
 
     @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
     def test_get_class(self, loader):
-        plugin_a2_class = loader.get_class("category_a.plugin_a2")
-        assert plugin_a2_class == PluginA2
+        plugin_a2_class = loader.get_class("category_a.plugin_a2", "plugin_type_foo")
+        assert plugin_a2_class == MockPluginFooA2
 
-        plugin_bx1_class = loader.get_class("category_b.x.plugin_bx1")
-        assert plugin_bx1_class == PluginBX1
+        plugin_bx1_class = loader.get_class("category_b.x.plugin_bx1", plugin_type="plugin_type_foo")
+        assert plugin_bx1_class == MockPluginFooBX1
+
+        plugin_a2_class = loader.get_class("category_c.plugin_c2", plugin_type="plugin_type_bar")
+        assert plugin_a2_class == MockPluginBarC2
 
     @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
     def test_get_fails_no_such_plugin(self, loader):
         with pytest.raises(ValueError, match=".*[Pp]lugin.*not.*exist.*"):
             loader.get_class("category_a.no_such_plugin")
 
+    @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
+    def test_get_fails_no_such_plugin_type(self, loader):
+        with pytest.raises(ValueError, match=".*Plugin type.*one of.*"):
+            loader.get_class("category_a.no_such_plugin", plugin_type="no_such_plugin_type")
+
     @pytest.mark.parametrize("loader", [plugin_core.PluginLoader(), plugin_loader])
     def test_plugin_added_live(self, loader: plugin_core.PluginLoader):
-        plugin_core.register_plugin_category("category_c", expected_class=plugin_core.Plugin)
+        # Case: add plugin live in a new category.
 
-        @plugin_core.register_plugin(name="plugin_c1", category="category_c")
-        class PluginC1(plugin_core.Plugin):
+        plugin_core.register_plugin_category(
+            "category_d", expected_class=plugin_core.Plugin, plugin_type="plugin_type_bar"
+        )
+
+        @plugin_core.register_plugin(name="plugin_d1", category="category_d", plugin_type="plugin_type_bar")
+        class PluginD1(plugin_core.Plugin):
             pass
 
-        listed = loader.list()
-        assert "category_c" in listed
-        assert "plugin_c1" in listed["category_c"]
+        listed = loader.list(plugin_type="plugin_type_bar")
+        assert "category_d" in listed
+        assert "plugin_d1" in listed["category_d"]
 
-        listed_classes = loader.list_classes()
-        assert "category_c" in listed
-        assert PluginC1 in listed_classes["category_c"]
+        listed_classes = loader.list_classes(plugin_type="plugin_type_bar")
+        assert "category_d" in listed
+        assert PluginD1 in listed_classes["category_d"]
 
-        plugin_c1_class = loader.get_class("category_c.plugin_c1")
-        assert plugin_c1_class == PluginC1
+        plugin_d1_class = loader.get_class("category_d.plugin_d1", plugin_type="plugin_type_bar")
+        assert plugin_d1_class == PluginD1
 
-        plugin_c1_instance = loader.get(
-            "category_c.plugin_c1",
+        plugin_d1_instance = loader.get("category_d.plugin_d1", "plugin_type_bar")
+        assert isinstance(plugin_d1_instance, PluginD1)
+
+        # Case: add plugin live in an existing category.
+
+        @plugin_core.register_plugin(name="plugin_d2", category="category_d", plugin_type="plugin_type_bar")
+        class PluginD2(plugin_core.Plugin):
+            pass
+
+        listed = loader.list(plugin_type="plugin_type_bar")
+        assert "category_d" in listed
+        assert "plugin_d2" in listed["category_d"]
+
+        listed_classes = loader.list_classes(plugin_type="plugin_type_bar")
+        assert "category_d" in listed
+        assert PluginD2 in listed_classes["category_d"]
+
+        plugin_d2_class = loader.get_class("category_d.plugin_d2", plugin_type="plugin_type_bar")
+        assert plugin_d2_class == PluginD2
+
+        plugin_d2_instance = loader.get("category_d.plugin_d2", "plugin_type_bar")
+        assert isinstance(plugin_d2_instance, PluginD2)
+
+        # Case: add plugin live in a new category which has a new plugin type.
+
+        plugin_core.register_plugin_category(
+            "category_e", expected_class=plugin_core.Plugin, plugin_type="plugin_type_baz"
         )
-        assert isinstance(plugin_c1_instance, PluginC1)  # type: ignore
+
+        @plugin_core.register_plugin(name="plugin_e1", category="category_e", plugin_type="plugin_type_baz")
+        class PluginE1(plugin_core.Plugin):
+            pass
+
+        listed = loader.list(plugin_type="plugin_type_baz")
+        assert "category_e" in listed
+        assert "plugin_e1" in listed["category_e"]
+
+        listed_classes = loader.list_classes(plugin_type="plugin_type_baz")
+        assert "category_e" in listed
+        assert PluginE1 in listed_classes["category_e"]
+
+        plugin_e1_class = loader.get_class("category_e.plugin_e1", plugin_type="plugin_type_baz")
+        assert plugin_e1_class == PluginE1
+
+        plugin_e1_instance = loader.get("category_e.plugin_e1", "plugin_type_baz")
+        assert isinstance(plugin_e1_instance, PluginE1)
diff --git a/tests/plugins/pipelines/test_pipeline_end2end.py b/tests/plugins/pipelines/test_pipeline_end2end.py
index 00ee6442..08b87018 100644
--- a/tests/plugins/pipelines/test_pipeline_end2end.py
+++ b/tests/plugins/pipelines/test_pipeline_end2end.py
@@ -562,6 +562,8 @@ def test_end2end_treatments_temporal_classification(
 # Category: treatments.temporal.regression:
 
 
+@pytest.mark.filterwarnings("ignore:.*validate_arguments.*:DeprecationWarning")  # Exp pydantic2 warns from HI.
+@pytest.mark.filterwarnings("ignore:.*conflict.*:UserWarning")  # Exp pydantic2 warns from HI.
 @pytest.mark.parametrize(
     "plugins_str",
     [
diff --git a/tests/plugins/prediction/one_off/classification/test_cde_classifier.py b/tests/plugins/prediction/one_off/classification/test_cde_classifier.py
index b4d57ecf..74b37b5c 100644
--- a/tests/plugins/prediction/one_off/classification/test_cde_classifier.py
+++ b/tests/plugins/prediction/one_off/classification/test_cde_classifier.py
@@ -37,7 +37,7 @@ def test_sanity(get_test_plugin: Callable, plugin_from: str) -> None:
     test_plugin = get_test_plugin(plugin_from, INIT_KWARGS, device="cpu")
     assert test_plugin is not None
     assert test_plugin.name == "cde_classifier"
-    assert test_plugin.fqn() == "prediction.one_off.classification.cde_classifier"
+    assert test_plugin.full_name() == "prediction.one_off.classification.cde_classifier"
     assert len(test_plugin.hyperparameter_space()) == 9
 
 
diff --git a/tests/plugins/prediction/one_off/classification/test_laplace_classifier.py b/tests/plugins/prediction/one_off/classification/test_laplace_classifier.py
index 065f5898..2c1bb302 100644
--- a/tests/plugins/prediction/one_off/classification/test_laplace_classifier.py
+++ b/tests/plugins/prediction/one_off/classification/test_laplace_classifier.py
@@ -37,7 +37,7 @@ def test_sanity(get_test_plugin: Callable, plugin_from: str) -> None:
     test_plugin = get_test_plugin(plugin_from, INIT_KWARGS, device="cpu")
     assert test_plugin is not None
     assert test_plugin.name == "laplace_ode_classifier"
-    assert test_plugin.fqn() == "prediction.one_off.classification.laplace_ode_classifier"
+    assert test_plugin.full_name() == "prediction.one_off.classification.laplace_ode_classifier"
     assert len(test_plugin.hyperparameter_space()) == 7
 
 
diff --git a/tests/plugins/prediction/one_off/classification/test_nn_classifier.py b/tests/plugins/prediction/one_off/classification/test_nn_classifier.py
index 79a9a08d..d38cd201 100644
--- a/tests/plugins/prediction/one_off/classification/test_nn_classifier.py
+++ b/tests/plugins/prediction/one_off/classification/test_nn_classifier.py
@@ -37,7 +37,7 @@ def test_sanity(get_test_plugin: Callable, plugin_from: str) -> None:
     test_plugin = get_test_plugin(plugin_from, INIT_KWARGS, device="cpu")
     assert test_plugin is not None
     assert test_plugin.name == "nn_classifier"
-    assert test_plugin.fqn() == "prediction.one_off.classification.nn_classifier"
+    assert test_plugin.full_name() == "prediction.one_off.classification.nn_classifier"
     assert len(test_plugin.hyperparameter_space()) == 9
 
 
diff --git a/tests/plugins/prediction/one_off/classification/test_ode_classifier.py b/tests/plugins/prediction/one_off/classification/test_ode_classifier.py
index 747f48d0..45ea59c5 100644
--- a/tests/plugins/prediction/one_off/classification/test_ode_classifier.py
+++ b/tests/plugins/prediction/one_off/classification/test_ode_classifier.py
@@ -37,7 +37,7 @@ def test_sanity(get_test_plugin: Callable, plugin_from: str) -> None:
     test_plugin = get_test_plugin(plugin_from, INIT_KWARGS, device="cpu")
     assert test_plugin is not None
     assert test_plugin.name == "ode_classifier"
-    assert test_plugin.fqn() == "prediction.one_off.classification.ode_classifier"
+    assert test_plugin.full_name() == "prediction.one_off.classification.ode_classifier"
     assert len(test_plugin.hyperparameter_space()) == 9
 
 
diff --git a/tests/plugins/prediction/one_off/classification/test_prediction_oneoff_classification_base.py b/tests/plugins/prediction/one_off/classification/test_prediction_oneoff_classification_base.py
index 6bff56bb..03c8ed89 100644
--- a/tests/plugins/prediction/one_off/classification/test_prediction_oneoff_classification_base.py
+++ b/tests/plugins/prediction/one_off/classification/test_prediction_oneoff_classification_base.py
@@ -18,6 +18,7 @@
 class DummyOneOffClassifier(BaseOneOffClassifier):
     name = "dummy"
     category = "dummy_cat"
+    plugin_type = "dummy_type"
 
     def _predict(self, data: "PredictiveDataset", *args, **kwargs) -> "StaticSamples":
         raise NotImplementedError
diff --git a/tests/plugins/prediction/one_off/regression/test_prediction_oneoff_regression_base.py b/tests/plugins/prediction/one_off/regression/test_prediction_oneoff_regression_base.py
index dee4fa1f..d88f6db8 100644
--- a/tests/plugins/prediction/one_off/regression/test_prediction_oneoff_regression_base.py
+++ b/tests/plugins/prediction/one_off/regression/test_prediction_oneoff_regression_base.py
@@ -18,6 +18,7 @@
 class DummyOneOffRegressor(BaseOneOffRegressor):
     name = "dummy"
     category = "dummy_cat"
+    plugin_type = "dummy_type"
 
     def _predict(self, data: "PredictiveDataset", *args, **kwargs) -> "StaticSamples":
         raise NotImplementedError
diff --git a/tests/plugins/prediction/temporal/classification/test_prediction_temporal_classification_base.py b/tests/plugins/prediction/temporal/classification/test_prediction_temporal_classification_base.py
index ada2da64..c4e5748f 100644
--- a/tests/plugins/prediction/temporal/classification/test_prediction_temporal_classification_base.py
+++ b/tests/plugins/prediction/temporal/classification/test_prediction_temporal_classification_base.py
@@ -19,6 +19,7 @@
 class DummyTemporalClassifier(BaseTemporalClassifier):
     name = "dummy"
     category = "dummy_cat"
+    plugin_type = "dummy_type"
 
     def _predict(
         self,
diff --git a/tests/plugins/prediction/temporal/regression/test_prediction_temporal_regression_base.py b/tests/plugins/prediction/temporal/regression/test_prediction_temporal_regression_base.py
index efa81880..65d5476e 100644
--- a/tests/plugins/prediction/temporal/regression/test_prediction_temporal_regression_base.py
+++ b/tests/plugins/prediction/temporal/regression/test_prediction_temporal_regression_base.py
@@ -16,6 +16,7 @@
 class DummyTemporalRegressor(BaseTemporalRegressor):
     name = "dummy"
     category = "dummy_cat"
+    plugin_type = "dummy_type"
 
     def _predict(
         self,
diff --git a/tests/plugins/test_all_plugins.py b/tests/plugins/test_all_plugins.py
index 7622c822..8d18d8e4 100644
--- a/tests/plugins/test_all_plugins.py
+++ b/tests/plugins/test_all_plugins.py
@@ -6,7 +6,7 @@
 from tempor.plugins import plugin_loader
 from tempor.plugins.core._base_estimator import EmptyParamsDefinition
 
-PLUGIN_FQNS = plugin_loader.list_fqns()
+PLUGIN_FQNS = plugin_loader.list_full_names()
 
 
 @pytest.mark.filterwarnings("ignore:.*validate_arguments.*:DeprecationWarning")  # Exp pydantic2 warns from HI.
@@ -41,6 +41,8 @@ def test_repr(plugin_fqn):
         f"{plugin.name}"
         r"'.*category='"
         f"{plugin.category}"
+        r"'.*plugin_type='"
+        f"{plugin.plugin_type}"
         r"'.*params=.?\{.*\}.*\)",
         repr_,
         re.S | re.DOTALL,
diff --git a/tests/plugins/test_plugin_loader.py b/tests/plugins/test_plugin_loader.py
index e8f11576..9fad7fde 100644
--- a/tests/plugins/test_plugin_loader.py
+++ b/tests/plugins/test_plugin_loader.py
@@ -1,8 +1,8 @@
 from tempor.plugins import plugin_loader
 
 
-def test_tempor_plugin_loader_contents():
-    all_plugins = plugin_loader.list()
+def test_tempor_plugin_loader_methods_contents():
+    all_plugins = plugin_loader.list(plugin_type="method")
 
     # Do some checks that expected plugins have been registered.
     # Update as plugins get added / reorganized.
@@ -76,3 +76,9 @@ def test_tempor_plugin_loader_contents():
     assert "crn_classifier" in all_plugins["treatments"]["temporal"]["classification"]
     assert "crn_regressor" in all_plugins["treatments"]["temporal"]["regression"]
     assert "synctwin_regressor" in all_plugins["treatments"]["one_off"]["regression"]
+
+
+def test_presence_plugin_types():
+    plugin_types = plugin_loader.list_plugin_types()
+
+    assert "method" in plugin_types
diff --git a/tests/plugins/time_to_event/test_ddh_plugin.py b/tests/plugins/time_to_event/test_ddh_plugin.py
index 6f7665e7..8ed47d47 100644
--- a/tests/plugins/time_to_event/test_ddh_plugin.py
+++ b/tests/plugins/time_to_event/test_ddh_plugin.py
@@ -39,7 +39,7 @@ def test_sanity(get_test_plugin: Callable, plugin_from: str) -> None:
     test_plugin: "BaseTimeToEventAnalysis" = get_test_plugin(plugin_from, INIT_KWARGS, device="cpu")
     assert test_plugin is not None
     assert test_plugin.name == "dynamic_deephit"
-    assert test_plugin.fqn() == "time_to_event.dynamic_deephit"
+    assert test_plugin.full_name() == "time_to_event.dynamic_deephit"
     assert len(test_plugin.hyperparameter_space()) == 10
 
 
diff --git a/tests/plugins/time_to_event/test_time_to_event_base.py b/tests/plugins/time_to_event/test_time_to_event_base.py
index 69f099b7..508a0086 100644
--- a/tests/plugins/time_to_event/test_time_to_event_base.py
+++ b/tests/plugins/time_to_event/test_time_to_event_base.py
@@ -20,6 +20,7 @@
 class DummyTimeToEventAnalysis(BaseTimeToEventAnalysis):
     name = "dummy"
     category = "dummy_cat"
+    plugin_type = "dummy_type"
 
     def _predict(
         self,
diff --git a/tests/plugins/time_to_event/test_ts_coxph_plugin.py b/tests/plugins/time_to_event/test_ts_coxph_plugin.py
index 8a6e56e0..cf421096 100644
--- a/tests/plugins/time_to_event/test_ts_coxph_plugin.py
+++ b/tests/plugins/time_to_event/test_ts_coxph_plugin.py
@@ -45,7 +45,7 @@ def test_sanity(get_test_plugin: Callable, plugin_from: str) -> None:
     test_plugin: "BaseTimeToEventAnalysis" = get_test_plugin(plugin_from, INIT_KWARGS, device="cpu")
     assert test_plugin is not None
     assert test_plugin.name == "ts_coxph"
-    assert test_plugin.fqn() == "time_to_event.ts_coxph"
+    assert test_plugin.full_name() == "time_to_event.ts_coxph"
     assert len(test_plugin.hyperparameter_space()) == 12
 
 
diff --git a/tests/plugins/time_to_event/test_ts_xgb_plugin.py b/tests/plugins/time_to_event/test_ts_xgb_plugin.py
index 24c785a6..32dfe7f0 100644
--- a/tests/plugins/time_to_event/test_ts_xgb_plugin.py
+++ b/tests/plugins/time_to_event/test_ts_xgb_plugin.py
@@ -40,7 +40,7 @@ def test_sanity(get_test_plugin: Callable, plugin_from: str) -> None:
     test_plugin: "BaseTimeToEventAnalysis" = get_test_plugin(plugin_from, INIT_KWARGS, device="cpu")
     assert test_plugin is not None
     assert test_plugin.name == "ts_xgb"
-    assert test_plugin.fqn() == "time_to_event.ts_xgb"
+    assert test_plugin.full_name() == "time_to_event.ts_xgb"
     assert len(test_plugin.hyperparameter_space()) == 23
 
 
diff --git a/tests/plugins/treatments/one_off/test_treatments_oneoff_base.py b/tests/plugins/treatments/one_off/test_treatments_oneoff_base.py
index 8a5ef003..c31860c8 100644
--- a/tests/plugins/treatments/one_off/test_treatments_oneoff_base.py
+++ b/tests/plugins/treatments/one_off/test_treatments_oneoff_base.py
@@ -19,6 +19,7 @@
 class DummyOneOffTreatmentEffects(BaseOneOffTreatmentEffects):
     name = "dummy"
     category = "dummy_cat"
+    plugin_type = "dummy_type"
 
     def _predict(
         self,
diff --git a/tests/plugins/treatments/temporal/test_treatments_temporal_base.py b/tests/plugins/treatments/temporal/test_treatments_temporal_base.py
index aad87df5..63edebfd 100644
--- a/tests/plugins/treatments/temporal/test_treatments_temporal_base.py
+++ b/tests/plugins/treatments/temporal/test_treatments_temporal_base.py
@@ -16,6 +16,7 @@
 class DummyTemporalTreatmentEffects(BaseTemporalTreatmentEffects):
     name = "dummy"
     category = "dummy_cat"
+    plugin_type = "dummy_type"
 
     def _predict(
         self,
diff --git a/tutorials/extending/tutorial02_testing_custom_plugin.ipynb b/tutorials/extending/tutorial02_testing_custom_plugin.ipynb
index c4a01248..8c7064a4 100644
--- a/tutorials/extending/tutorial02_testing_custom_plugin.ipynb
+++ b/tutorials/extending/tutorial02_testing_custom_plugin.ipynb
@@ -21,7 +21,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": null,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -65,7 +65,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [
     {
@@ -83,6 +83,8 @@
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'prediction.one_off.regression'</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'prediction.temporal.classification'</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'prediction.temporal.regression'</span>,\n",
+       "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.encoding.static'</span>,\n",
+       "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.encoding.temporal'</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.imputation.static'</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.imputation.temporal'</span>,\n",
        "    <span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing.nop'</span>,\n",
@@ -101,6 +103,8 @@
        "    \u001b[32m'prediction.one_off.regression'\u001b[0m,\n",
        "    \u001b[32m'prediction.temporal.classification'\u001b[0m,\n",
        "    \u001b[32m'prediction.temporal.regression'\u001b[0m,\n",
+       "    \u001b[32m'preprocessing.encoding.static'\u001b[0m,\n",
+       "    \u001b[32m'preprocessing.encoding.temporal'\u001b[0m,\n",
        "    \u001b[32m'preprocessing.imputation.static'\u001b[0m,\n",
        "    \u001b[32m'preprocessing.imputation.temporal'\u001b[0m,\n",
        "    \u001b[32m'preprocessing.nop'\u001b[0m,\n",
@@ -135,6 +139,7 @@
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'classification'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_classifier'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'regression'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'seq2seq_regressor'</span><span style=\"font-weight: bold\">]}</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"font-weight: bold\">}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #008000; text-decoration-color: #008000\">'preprocessing'</span>: <span style=\"font-weight: bold\">{</span>\n",
+       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'encoding'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_onehot_encoder'</span><span style=\"font-weight: bold\">]</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ts_onehot_encoder'</span><span style=\"font-weight: bold\">]}</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'imputation'</span>: <span style=\"font-weight: bold\">{</span>\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'static'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'static_tabular_imputer'</span><span style=\"font-weight: bold\">]</span>,\n",
        "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #008000; text-decoration-color: #008000\">'temporal'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'ffill'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'ts_tabular_imputer'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'bfill'</span><span style=\"font-weight: bold\">]</span>\n",
@@ -163,6 +168,7 @@
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'classification'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_classifier'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'regression'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'seq2seq_regressor'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\n",
        "\u001b[2;32m│   \u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   \u001b[0m\u001b[32m'preprocessing'\u001b[0m: \u001b[1m{\u001b[0m\n",
+       "\u001b[2;32m│   │   \u001b[0m\u001b[32m'encoding'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m, \u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ts_onehot_encoder'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m,\n",
        "\u001b[2;32m│   │   \u001b[0m\u001b[32m'imputation'\u001b[0m: \u001b[1m{\u001b[0m\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'static'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'static_tabular_imputer'\u001b[0m\u001b[1m]\u001b[0m,\n",
        "\u001b[2;32m│   │   │   \u001b[0m\u001b[32m'temporal'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'ffill'\u001b[0m, \u001b[32m'ts_tabular_imputer'\u001b[0m, \u001b[32m'bfill'\u001b[0m\u001b[1m]\u001b[0m\n",
@@ -273,7 +279,7 @@
     "    test_plugin = get_test_plugin(plugin_from, INIT_KWARGS)\n",
     "    assert test_plugin is not None\n",
     "    assert test_plugin.name == \"nn_classifier\"\n",
-    "    assert test_plugin.fqn() == \"prediction.one_off.classification.my_classifier\"\n",
+    "    assert test_plugin.full_name() == \"prediction.one_off.classification.my_classifier\"\n",
     "    assert len(test_plugin.hyperparameter_space()) == 9\n",
     "\n",
     "\n",
@@ -410,7 +416,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.15"
+   "version": "3.8.18"
   },
   "orig_nbformat": 4
  },