Create a Pipeline

A Machine Learning (ML) project usually consists of multiple interconnected steps. These steps can be thought of as separate processes, with clearly defined inputs and outputs. Thus, it becomes natural to think of ML projects as workflows or pipelines. This guide will walk you through transforming a Python script into a Kubeflow Pipeline (KFP), and deploy it on Kubeflow using the Kale SDK.

What You’ll Need

  • An EKF or MiniKF deployment with the default Kale Docker image.

Procedure

  1. Create a new Notebook server using the default Kale Docker image. The image will have the following naming scheme:

    gcr.io/arrikto/jupyter-kale-py36:<IMAGE_TAG>
    

    Note

    The <IMAGE_TAG> varies based on the MiniKF or EKF release.

  2. Connect to the server, open a terminal, and install scikit-learn:

    $ pip3 install --user scikit-learn==0.23.0
    
  3. Create a new python file and name it kale_sdk.py:

    $ touch kale_sdk.py
    
  4. Copy and paste the following code inside kale_sdk.py:

    # Copyright © 2021 Arrikto Inc.  All Rights Reserved.
    
    """Kale SDK.
    
    This script trains an ML pipeline to solve a binary classification task.
    """
    
    from sklearn.datasets import make_classification
    from sklearn.linear_model import LogisticRegression
    from sklearn.model_selection import train_test_split
    
    
    def load(random_state):
        """Create a random dataset for binary classification."""
        rs = int(random_state)
        x, y = make_classification(random_state=rs)
        return x, y
    
    
    def split(x, y):
        """Split the data into train and test sets."""
        x, x_test, y, y_test = train_test_split(x, y, test_size=0.1)
        return x, x_test, y, y_test
    
    
    def train(x, x_test, y, training_iterations):
        """Train a Logistic Regression model."""
        iters = int(training_iterations)
        model = LogisticRegression(max_iter=iters)
        model.fit(x, y)
        print(model.predict(x_test))
    
    
    def ml_pipeline(rs=42, iters=100):
        """Run the ML pipeline."""
        x, y = load(rs)
        x, x_test, y, y_test = split(x, y)
        train(x, x_test, y, iters)
    
    
    if __name__ == "__main__":
        ml_pipeline(rs=42, iters=100)
    

    Alternatively, download the kale_sdk_starter_code.py Python file.

    In this code sample, you define three functions that could form individual steps in an ML pipeline:

    • The first function (load) creates a random dataset that we can use to simulate a binary classification task.
    • The second function (split) processes the dataset by splitting it into training and test subsets.
    • The third function (train) fits a Logistic Regression model and prints its performance on the test subset.

    An ML engineer would write similar functions, test them separately, and in the end, group them to launch an ML experiment. To this end, you can define a fourth function that calls each step and weaves everything together. This is the ml_pipeline function, the main entry point.

    Finally, we add the standard python boilerplate code to parse user arguments and call the ml_pipeline function with those arguments.

  5. Decorate every function that you want to be a step in the pipeline with the step decorator. The following snippet summarizes the changes in the code:

    --- examples/sdk/starter.py
    +++ examples/sdk/step.py
    @@ -5,11 +5,13 @@
     This script trains an ML pipeline to solve a binary classification task.
     """
     
    +from kale.sdk import step
     from sklearn.datasets import make_classification
     from sklearn.linear_model import LogisticRegression
     from sklearn.model_selection import train_test_split
     
     
    +@step(name="data_loading")
     def load(random_state):
         """Create a random dataset for binary classification."""
         rs = int(random_state)
    @@ -17,12 +19,14 @@
         return x, y
     
     
    +@step(name="data_split")
     def split(x, y):
         """Split the data into train and test sets."""
         x, x_test, y, y_test = train_test_split(x, y, test_size=0.1)
         return x, x_test, y, y_test
     
     
    +@step(name="model_training")
     def train(x, x_test, y, training_iterations):
         """Train a Logistic Regression model."""
         iters = int(training_iterations)
    

    Copy the resulting code below or download the kale_sdk_step_decorator.py Python file.

  6. Decorate the main entry point function with the Kale pipeline decorator. The following snippet summarizes the changes in code:

    --- examples/sdk/step.py
    +++ examples/sdk/sdk.py
    @@ -5,7 +5,7 @@
     This script trains an ML pipeline to solve a binary classification task.
     """
     
    -from kale.sdk import step
    +from kale.sdk import pipeline, step
     from sklearn.datasets import make_classification
     from sklearn.linear_model import LogisticRegression
     from sklearn.model_selection import train_test_split
    @@ -35,6 +35,7 @@
         print(model.predict(x_test))
     
     
    +@pipeline(name="binary-classification", experiment="kale-tutorial")
     def ml_pipeline(rs=42, iters=100):
         """Run the ML pipeline."""
         x, y = load(rs)
    

    Copy the resulting code below or download the kale_sdk.py Python file.

    Kale can infer the pipeline structure by examining the order of the function calls inside the pipeline decorated function. Thus, the step that runs the load function will run first, followed by the step that runs the split function. Finally, the step that trains the model will complete the KFP run.

  7. Run the script locally to test whether your code runs successfully using Kale’s marshalling mechanism:

    $ python3 -m kale kale_sdk.py
    
  8. (Optional) Produce a workflow YAML file that you can inspect:

    $ python3 -m kale kale_sdk.py --compile
    

    After the successful execution of this command, look for the workflow YAML file inside a .kale directory inside your working directory. This is a file that you could upload and submit to Kubeflow manually through its User Interface (KFP UI).

  9. Deploy and run your code as a KFP pipeline:

    $ python3 -m kale kale_sdk.py --kfp
    

    Note

    To see the complete list of arguments and their respective usage, run python3 -m kale --help.

Note

Casting the variables into the correct data type inside the functions is a temporary limitation. This will be addressed in future versions of the Kale SDK.

Summary

You have successfully transformed a simple Python script into an ML pipeline and deployed it on Kubeflow.

What’s Next

The next step is to create and run parallel steps.