{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Kubeflow Pipelines with Katib component\n",
    "\n",
    "In this notebook you will:\n",
    "- Create Katib Experiment using random algorithm.\n",
    "- Use median stopping rule as an early stopping algorithm.\n",
    "- Use Kubernetes Job with mxnet mnist training container as a Trial template.\n",
    "- Create Pipeline to get the optimal hyperparameters.\n",
    "\n",
    "Reference documentation:\n",
    "- https://kubeflow.org/docs/components/katib/experiment/#random-search\n",
    "- https://kubeflow.org/docs/components/katib/early-stopping/\n",
    "- https://kubeflow.org/docs/pipelines/overview/concepts/component/\n",
    "\n",
    "**Note**: This Pipeline runs in the multi-user mode. Follow [this guide](https://github.com/kubeflow/katib/tree/master/examples/v1beta1/kubeflow-pipelines#multi-user-pipelines-setup) to give your Notebook access to Kubeflow Pipelines."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting kfp==1.8.4\n",
      "  Downloading kfp-1.8.4.tar.gz (252 kB)\n",
      "\u001b[K     |████████████████████████████████| 252 kB 5.3 MB/s eta 0:00:01\n",
      "\u001b[?25hRequirement already satisfied: absl-py<=0.11,>=0.9 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (0.11.0)\n",
      "Requirement already satisfied: PyYAML<6,>=5.3 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (5.4.1)\n",
      "Requirement already satisfied: google-cloud-storage<2,>=1.20.0 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (1.42.3)\n",
      "Requirement already satisfied: kubernetes<19,>=8.0.0 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (12.0.1)\n",
      "Requirement already satisfied: google-api-python-client<2,>=1.7.8 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (1.12.8)\n",
      "Requirement already satisfied: google-auth<2,>=1.6.1 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (1.35.0)\n",
      "Requirement already satisfied: requests-toolbelt<1,>=0.8.0 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (0.9.1)\n",
      "Requirement already satisfied: cloudpickle<2,>=1.3.0 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (1.6.0)\n",
      "Requirement already satisfied: kfp-server-api<2.0.0,>=1.1.2 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (1.6.0)\n",
      "Requirement already satisfied: jsonschema<4,>=3.0.1 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (3.2.0)\n",
      "Requirement already satisfied: tabulate<1,>=0.8.6 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (0.8.9)\n",
      "Requirement already satisfied: click<8,>=7.1.1 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (7.1.2)\n",
      "Requirement already satisfied: Deprecated<2,>=1.2.7 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (1.2.13)\n",
      "Requirement already satisfied: strip-hints<1,>=0.1.8 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (0.1.10)\n",
      "Requirement already satisfied: docstring-parser<1,>=0.7.3 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (0.11)\n",
      "Requirement already satisfied: kfp-pipeline-spec<0.2.0,>=0.1.10 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (0.1.12)\n",
      "Requirement already satisfied: fire<1,>=0.3.1 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (0.4.0)\n",
      "Requirement already satisfied: protobuf<4,>=3.13.0 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (3.17.3)\n",
      "Requirement already satisfied: uritemplate<4,>=3.0.1 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (3.0.1)\n",
      "Collecting pydantic<2,>=1.8.2\n",
      "  Downloading pydantic-1.8.2-cp38-cp38-manylinux2014_x86_64.whl (13.7 MB)\n",
      "\u001b[K     |████████████████████████████████| 13.7 MB 22.4 MB/s eta 0:00:01\n",
      "\u001b[?25hRequirement already satisfied: typing-extensions<4,>=3.10.0.2 in /opt/conda/lib/python3.8/site-packages (from kfp==1.8.4) (3.10.0.2)\n",
      "Requirement already satisfied: six in /opt/conda/lib/python3.8/site-packages (from absl-py<=0.11,>=0.9->kfp==1.8.4) (1.16.0)\n",
      "Requirement already satisfied: wrapt<2,>=1.10 in /opt/conda/lib/python3.8/site-packages (from Deprecated<2,>=1.2.7->kfp==1.8.4) (1.13.1)\n",
      "Requirement already satisfied: termcolor in /opt/conda/lib/python3.8/site-packages (from fire<1,>=0.3.1->kfp==1.8.4) (1.1.0)\n",
      "Requirement already satisfied: google-auth-httplib2>=0.0.3 in /opt/conda/lib/python3.8/site-packages (from google-api-python-client<2,>=1.7.8->kfp==1.8.4) (0.1.0)\n",
      "Requirement already satisfied: httplib2<1dev,>=0.15.0 in /opt/conda/lib/python3.8/site-packages (from google-api-python-client<2,>=1.7.8->kfp==1.8.4) (0.20.1)\n",
      "Requirement already satisfied: google-api-core<2dev,>=1.21.0 in /opt/conda/lib/python3.8/site-packages (from google-api-python-client<2,>=1.7.8->kfp==1.8.4) (1.31.3)\n",
      "Requirement already satisfied: pytz in /opt/conda/lib/python3.8/site-packages (from google-api-core<2dev,>=1.21.0->google-api-python-client<2,>=1.7.8->kfp==1.8.4) (2021.1)\n",
      "Requirement already satisfied: requests<3.0.0dev,>=2.18.0 in /opt/conda/lib/python3.8/site-packages (from google-api-core<2dev,>=1.21.0->google-api-python-client<2,>=1.7.8->kfp==1.8.4) (2.25.1)\n",
      "Requirement already satisfied: googleapis-common-protos<2.0dev,>=1.6.0 in /opt/conda/lib/python3.8/site-packages (from google-api-core<2dev,>=1.21.0->google-api-python-client<2,>=1.7.8->kfp==1.8.4) (1.53.0)\n",
      "Requirement already satisfied: packaging>=14.3 in /opt/conda/lib/python3.8/site-packages (from google-api-core<2dev,>=1.21.0->google-api-python-client<2,>=1.7.8->kfp==1.8.4) (20.9)\n",
      "Requirement already satisfied: setuptools>=40.3.0 in /opt/conda/lib/python3.8/site-packages (from google-api-core<2dev,>=1.21.0->google-api-python-client<2,>=1.7.8->kfp==1.8.4) (49.6.0.post20210108)\n",
      "Requirement already satisfied: rsa<5,>=3.1.4 in /opt/conda/lib/python3.8/site-packages (from google-auth<2,>=1.6.1->kfp==1.8.4) (4.7.2)\n",
      "Requirement already satisfied: pyasn1-modules>=0.2.1 in /opt/conda/lib/python3.8/site-packages (from google-auth<2,>=1.6.1->kfp==1.8.4) (0.2.8)\n",
      "Requirement already satisfied: cachetools<5.0,>=2.0.0 in /opt/conda/lib/python3.8/site-packages (from google-auth<2,>=1.6.1->kfp==1.8.4) (4.2.4)\n",
      "Requirement already satisfied: google-resumable-media<3.0dev,>=1.3.0 in /opt/conda/lib/python3.8/site-packages (from google-cloud-storage<2,>=1.20.0->kfp==1.8.4) (2.0.3)\n",
      "Requirement already satisfied: google-cloud-core<3.0dev,>=1.6.0 in /opt/conda/lib/python3.8/site-packages (from google-cloud-storage<2,>=1.20.0->kfp==1.8.4) (2.1.0)\n",
      "Requirement already satisfied: google-crc32c<2.0dev,>=1.0 in /opt/conda/lib/python3.8/site-packages (from google-resumable-media<3.0dev,>=1.3.0->google-cloud-storage<2,>=1.20.0->kfp==1.8.4) (1.3.0)\n",
      "Requirement already satisfied: pyparsing<3,>=2.4.2 in /opt/conda/lib/python3.8/site-packages (from httplib2<1dev,>=0.15.0->google-api-python-client<2,>=1.7.8->kfp==1.8.4) (2.4.7)\n",
      "Requirement already satisfied: attrs>=17.4.0 in /opt/conda/lib/python3.8/site-packages (from jsonschema<4,>=3.0.1->kfp==1.8.4) (21.2.0)\n",
      "Requirement already satisfied: pyrsistent>=0.14.0 in /opt/conda/lib/python3.8/site-packages (from jsonschema<4,>=3.0.1->kfp==1.8.4) (0.17.3)\n",
      "Requirement already satisfied: urllib3>=1.15 in /opt/conda/lib/python3.8/site-packages (from kfp-server-api<2.0.0,>=1.1.2->kfp==1.8.4) (1.26.5)\n",
      "Requirement already satisfied: python-dateutil in /opt/conda/lib/python3.8/site-packages (from kfp-server-api<2.0.0,>=1.1.2->kfp==1.8.4) (2.8.1)\n",
      "Requirement already satisfied: certifi in /opt/conda/lib/python3.8/site-packages (from kfp-server-api<2.0.0,>=1.1.2->kfp==1.8.4) (2021.5.30)\n",
      "Requirement already satisfied: requests-oauthlib in /opt/conda/lib/python3.8/site-packages (from kubernetes<19,>=8.0.0->kfp==1.8.4) (1.3.0)\n",
      "Requirement already satisfied: websocket-client!=0.40.0,!=0.41.*,!=0.42.*,>=0.32.0 in /opt/conda/lib/python3.8/site-packages (from kubernetes<19,>=8.0.0->kfp==1.8.4) (1.0.1)\n",
      "Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /opt/conda/lib/python3.8/site-packages (from pyasn1-modules>=0.2.1->google-auth<2,>=1.6.1->kfp==1.8.4) (0.4.8)\n",
      "Requirement already satisfied: idna<3,>=2.5 in /opt/conda/lib/python3.8/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core<2dev,>=1.21.0->google-api-python-client<2,>=1.7.8->kfp==1.8.4) (2.10)\n",
      "Requirement already satisfied: chardet<5,>=3.0.2 in /opt/conda/lib/python3.8/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core<2dev,>=1.21.0->google-api-python-client<2,>=1.7.8->kfp==1.8.4) (4.0.0)\n",
      "Requirement already satisfied: wheel in /opt/conda/lib/python3.8/site-packages (from strip-hints<1,>=0.1.8->kfp==1.8.4) (0.36.2)\n",
      "Requirement already satisfied: oauthlib>=3.0.0 in /opt/conda/lib/python3.8/site-packages (from requests-oauthlib->kubernetes<19,>=8.0.0->kfp==1.8.4) (3.1.1)\n",
      "Building wheels for collected packages: kfp\n",
      "  Building wheel for kfp (setup.py) ... \u001b[?25ldone\n",
      "\u001b[?25h  Created wheel for kfp: filename=kfp-1.8.4-py3-none-any.whl size=349033 sha256=a8b852f8cac0b84d67aae100bf9364aad7f18eddadd49471a7be43345ddead9b\n",
      "  Stored in directory: /home/jovyan/.cache/pip/wheels/49/2b/fc/79b1a2787e4f73f9ee6b1c7fe88f7f42b82133c40baca38aa9\n",
      "Successfully built kfp\n",
      "Installing collected packages: pydantic, kfp\n",
      "  Attempting uninstall: kfp\n",
      "    Found existing installation: kfp 1.6.3\n",
      "    Uninstalling kfp-1.6.3:\n",
      "      Successfully uninstalled kfp-1.6.3\n",
      "Successfully installed kfp-1.8.4 pydantic-1.8.2\n",
      "Collecting kubeflow-katib==0.12.0\n",
      "  Downloading kubeflow_katib-0.12.0-py3-none-any.whl (89 kB)\n",
      "\u001b[K     |████████████████████████████████| 89 kB 7.3 MB/s  eta 0:00:01\n",
      "\u001b[?25hRequirement already satisfied: setuptools>=21.0.0 in /opt/conda/lib/python3.8/site-packages (from kubeflow-katib==0.12.0) (49.6.0.post20210108)\n",
      "Requirement already satisfied: urllib3>=1.15.1 in /opt/conda/lib/python3.8/site-packages (from kubeflow-katib==0.12.0) (1.26.5)\n",
      "Requirement already satisfied: certifi>=14.05.14 in /opt/conda/lib/python3.8/site-packages (from kubeflow-katib==0.12.0) (2021.5.30)\n",
      "Requirement already satisfied: kubernetes>=12.0.0 in /opt/conda/lib/python3.8/site-packages (from kubeflow-katib==0.12.0) (12.0.1)\n",
      "Requirement already satisfied: six>=1.10 in /opt/conda/lib/python3.8/site-packages (from kubeflow-katib==0.12.0) (1.16.0)\n",
      "Requirement already satisfied: google-auth>=1.0.1 in /opt/conda/lib/python3.8/site-packages (from kubernetes>=12.0.0->kubeflow-katib==0.12.0) (1.35.0)\n",
      "Requirement already satisfied: requests-oauthlib in /opt/conda/lib/python3.8/site-packages (from kubernetes>=12.0.0->kubeflow-katib==0.12.0) (1.3.0)\n",
      "Requirement already satisfied: pyyaml>=3.12 in /opt/conda/lib/python3.8/site-packages (from kubernetes>=12.0.0->kubeflow-katib==0.12.0) (5.4.1)\n",
      "Requirement already satisfied: requests in /opt/conda/lib/python3.8/site-packages (from kubernetes>=12.0.0->kubeflow-katib==0.12.0) (2.25.1)\n",
      "Requirement already satisfied: python-dateutil>=2.5.3 in /opt/conda/lib/python3.8/site-packages (from kubernetes>=12.0.0->kubeflow-katib==0.12.0) (2.8.1)\n",
      "Requirement already satisfied: websocket-client!=0.40.0,!=0.41.*,!=0.42.*,>=0.32.0 in /opt/conda/lib/python3.8/site-packages (from kubernetes>=12.0.0->kubeflow-katib==0.12.0) (1.0.1)\n",
      "Requirement already satisfied: rsa<5,>=3.1.4 in /opt/conda/lib/python3.8/site-packages (from google-auth>=1.0.1->kubernetes>=12.0.0->kubeflow-katib==0.12.0) (4.7.2)\n",
      "Requirement already satisfied: pyasn1-modules>=0.2.1 in /opt/conda/lib/python3.8/site-packages (from google-auth>=1.0.1->kubernetes>=12.0.0->kubeflow-katib==0.12.0) (0.2.8)\n",
      "Requirement already satisfied: cachetools<5.0,>=2.0.0 in /opt/conda/lib/python3.8/site-packages (from google-auth>=1.0.1->kubernetes>=12.0.0->kubeflow-katib==0.12.0) (4.2.4)\n",
      "Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /opt/conda/lib/python3.8/site-packages (from pyasn1-modules>=0.2.1->google-auth>=1.0.1->kubernetes>=12.0.0->kubeflow-katib==0.12.0) (0.4.8)\n",
      "Requirement already satisfied: chardet<5,>=3.0.2 in /opt/conda/lib/python3.8/site-packages (from requests->kubernetes>=12.0.0->kubeflow-katib==0.12.0) (4.0.0)\n",
      "Requirement already satisfied: idna<3,>=2.5 in /opt/conda/lib/python3.8/site-packages (from requests->kubernetes>=12.0.0->kubeflow-katib==0.12.0) (2.10)\n",
      "Requirement already satisfied: oauthlib>=3.0.0 in /opt/conda/lib/python3.8/site-packages (from requests-oauthlib->kubernetes>=12.0.0->kubeflow-katib==0.12.0) (3.1.1)\n",
      "Installing collected packages: kubeflow-katib\n",
      "Successfully installed kubeflow-katib-0.12.0\n"
     ]
    }
   ],
   "source": [
    "# Install required packages (Kubeflow Pipelines and Katib SDK).\n",
    "!pip install kfp==1.8.4\n",
    "!pip install kubeflow-katib==0.12.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import kfp\n",
    "import kfp.dsl as dsl\n",
    "from kfp import components\n",
    "\n",
    "from kubeflow.katib import ApiClient\n",
    "from kubeflow.katib import V1beta1ExperimentSpec\n",
    "from kubeflow.katib import V1beta1AlgorithmSpec\n",
    "from kubeflow.katib import V1beta1EarlyStoppingSpec\n",
    "from kubeflow.katib import V1beta1EarlyStoppingSetting\n",
    "from kubeflow.katib import V1beta1ObjectiveSpec\n",
    "from kubeflow.katib import V1beta1ParameterSpec\n",
    "from kubeflow.katib import V1beta1FeasibleSpace\n",
    "from kubeflow.katib import V1beta1TrialTemplate\n",
    "from kubeflow.katib import V1beta1TrialParameterSpec"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Define an Experiment\n",
    "\n",
    "You have to create an Experiment object before deploying it. This Experiment is similar to [this](https://github.com/kubeflow/katib/blob/master/examples/v1beta1/early-stopping/median-stop.yaml) YAML."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Experiment name and namespace.\n",
    "experiment_name = \"median-stop\"\n",
    "experiment_namespace = \"kubeflow-user-example-com\"\n",
    "\n",
    "# Trial count specification.\n",
    "max_trial_count = 18\n",
    "max_failed_trial_count = 3\n",
    "parallel_trial_count = 2\n",
    "\n",
    "# Objective specification.\n",
    "objective=V1beta1ObjectiveSpec(\n",
    "    type=\"maximize\",\n",
    "    goal= 0.99,\n",
    "    objective_metric_name=\"Validation-accuracy\",\n",
    "    additional_metric_names=[\n",
    "        \"Train-accuracy\"\n",
    "    ]\n",
    ")\n",
    "\n",
    "# Algorithm specification.\n",
    "algorithm=V1beta1AlgorithmSpec(\n",
    "    algorithm_name=\"random\",\n",
    ")\n",
    "\n",
    "# Early Stopping specification.\n",
    "early_stopping=V1beta1EarlyStoppingSpec(\n",
    "    algorithm_name=\"medianstop\",\n",
    "    algorithm_settings=[\n",
    "        V1beta1EarlyStoppingSetting(\n",
    "            name=\"min_trials_required\",\n",
    "            value=\"2\"\n",
    "        )\n",
    "    ]\n",
    ")\n",
    "\n",
    "\n",
    "# Experiment search space.\n",
    "# In this example we tune learning rate, number of layer and optimizer.\n",
    "# Learning rate has bad feasible space to show more early stopped Trials.\n",
    "parameters=[\n",
    "    V1beta1ParameterSpec(\n",
    "        name=\"lr\",\n",
    "        parameter_type=\"double\",\n",
    "        feasible_space=V1beta1FeasibleSpace(\n",
    "            min=\"0.01\",\n",
    "            max=\"0.3\"\n",
    "        ),\n",
    "    ),\n",
    "    V1beta1ParameterSpec(\n",
    "        name=\"num-layers\",\n",
    "        parameter_type=\"int\",\n",
    "        feasible_space=V1beta1FeasibleSpace(\n",
    "            min=\"2\",\n",
    "            max=\"5\"\n",
    "        ),\n",
    "    ),\n",
    "    V1beta1ParameterSpec(\n",
    "        name=\"optimizer\",\n",
    "        parameter_type=\"categorical\",\n",
    "        feasible_space=V1beta1FeasibleSpace(\n",
    "            list=[\n",
    "                \"sgd\", \n",
    "                \"adam\",\n",
    "                \"ftrl\"\n",
    "            ]\n",
    "        ),\n",
    "    ),\n",
    "]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Define a Trial template\n",
    "\n",
    "In this example, the Trial's Worker is the Kubernetes Job."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# JSON template specification for the Trial's Worker Kubernetes Job.\n",
    "trial_spec={\n",
    "    \"apiVersion\": \"batch/v1\",\n",
    "    \"kind\": \"Job\",\n",
    "    \"spec\": {\n",
    "        \"template\": {\n",
    "            \"metadata\": {\n",
    "                \"annotations\": {\n",
    "                     \"sidecar.istio.io/inject\": \"false\"\n",
    "                }\n",
    "            },\n",
    "            \"spec\": {\n",
    "                \"containers\": [\n",
    "                    {\n",
    "                        \"name\": \"training-container\",\n",
    "                        \"image\": \"docker.io/kubeflowkatib/mxnet-mnist:v1beta1-45c5727\",\n",
    "                        \"command\": [\n",
    "                            \"python3\",\n",
    "                            \"/opt/mxnet-mnist/mnist.py\",\n",
    "                            \"--batch-size=64\",\n",
    "                            \"--lr=${trialParameters.learningRate}\",\n",
    "                            \"--num-layers=${trialParameters.numberLayers}\",\n",
    "                            \"--optimizer=${trialParameters.optimizer}\"\n",
    "                        ]\n",
    "                    }\n",
    "                ],\n",
    "                \"restartPolicy\": \"Never\"\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "# Configure parameters for the Trial template.\n",
    "# We set the retain parameter to \"True\" to not clean-up the Trial Job's Kubernetes Pods.\n",
    "trial_template=V1beta1TrialTemplate(\n",
    "    retain=True,\n",
    "    primary_container_name=\"training-container\",\n",
    "    trial_parameters=[\n",
    "        V1beta1TrialParameterSpec(\n",
    "            name=\"learningRate\",\n",
    "            description=\"Learning rate for the training model\",\n",
    "            reference=\"lr\"\n",
    "        ),\n",
    "        V1beta1TrialParameterSpec(\n",
    "            name=\"numberLayers\",\n",
    "            description=\"Number of training model layers\",\n",
    "            reference=\"num-layers\"\n",
    "        ),\n",
    "        V1beta1TrialParameterSpec(\n",
    "            name=\"optimizer\",\n",
    "            description=\"Training model optimizer (sdg, adam or ftrl)\",\n",
    "            reference=\"optimizer\"\n",
    "        ),\n",
    "    ],\n",
    "    trial_spec=trial_spec\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Define an Experiment specification\n",
    "\n",
    "Create an Experiment specification from the above parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "experiment_spec=V1beta1ExperimentSpec(\n",
    "    max_trial_count=max_trial_count,\n",
    "    max_failed_trial_count=max_failed_trial_count,\n",
    "    parallel_trial_count=parallel_trial_count,\n",
    "    objective=objective,\n",
    "    algorithm=algorithm,\n",
    "    early_stopping=early_stopping,\n",
    "    parameters=parameters,\n",
    "    trial_template=trial_template\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Create a Pipeline using Katib component\n",
    "\n",
    "The best hyperparameters are printed after Experiment is finished.\n",
    "The Experiment is not deleted after the Pipeline is finished."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Get the Katib launcher.\n",
    "katib_experiment_launcher_op = components.load_component_from_url(\n",
    "    \"https://raw.githubusercontent.com/kubeflow/pipelines/master/components/kubeflow/katib-launcher/component.yaml\")\n",
    "\n",
    "@dsl.pipeline(\n",
    "    name=\"Launch Katib early stopping Experiment\",\n",
    "    description=\"An example to launch Katib Experiment with early stopping\"\n",
    ")\n",
    "\n",
    "def median_stop():\n",
    "\n",
    "    # Katib launcher component.\n",
    "    # Experiment Spec should be serialized to a valid Kubernetes object.\n",
    "    op = katib_experiment_launcher_op(\n",
    "        experiment_name=experiment_name,\n",
    "        experiment_namespace=experiment_namespace,\n",
    "        experiment_spec=ApiClient().sanitize_for_serialization(experiment_spec),\n",
    "        experiment_timeout_minutes=60,\n",
    "        delete_finished_experiment=False)\n",
    "\n",
    "    # Output container to print the results.\n",
    "    op_out = dsl.ContainerOp(\n",
    "        name=\"best-hp\",\n",
    "        image=\"library/bash:4.4.23\",\n",
    "        command=[\"sh\", \"-c\"],\n",
    "        arguments=[\"echo Best HyperParameters: %s\" % op.output],\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Run the Kubeflow Pipeline\n",
    "\n",
    "You can check the Katib Experiment info in the Katib UI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/conda/lib/python3.8/site-packages/kfp/dsl/_container_op.py:1257: FutureWarning: Please create reusable components instead of constructing ContainerOp instances directly. Reusable components are shareable, portable and have compatibility and support guarantees. Please see the documentation: https://www.kubeflow.org/docs/pipelines/sdk/component-development/#writing-your-component-definition-file The components can be created manually (or, in case of python, using kfp.components.create_component_from_func or func_to_container_op) and then loaded using kfp.components.load_component_from_file, load_component_from_uri or load_component_from_text: https://kubeflow-pipelines.readthedocs.io/en/stable/source/kfp.components.html#kfp.components.load_component_from_file\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<a href=\"/pipeline/#/experiments/details/c4bc7cf8-1c60-433b-b922-9445c0c7995c\" target=\"_blank\" >Experiment details</a>."
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<a href=\"/pipeline/#/runs/details/bb6689a9-1efa-4fd7-bcb1-09f47bf1e932\" target=\"_blank\" >Run details</a>."
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "RunPipelineResult(run_id=bb6689a9-1efa-4fd7-bcb1-09f47bf1e932)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Run the Kubeflow Pipeline in the user's namespace.\n",
    "kfp.Client().create_run_from_pipeline_func(median_stop,  namespace=experiment_namespace, arguments={})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
