Intro

This post is a recap of the Machine Learning Zoomcamp Module 5.

Below are the posts for the previous modules:

  1. Machine Learning Zoomcamp Module 1 - points received: 9 (7/7 for questions + 2 bonus for learning in public)
  2. Machine Learning Zoomcamp Module 2 - points received: 5 (5/6 for questions + 0 bonus for learning in public)
  3. Machine Learning Zoomcamp Module 3 - points received: 7 (6/6 for questions + 1 bonus for learning in public)
  4. Machine Learning Zoomcamp Module 4 - points received: 6 (6/6 for questions + 0 bonus for learning in public)

The gist of the module

This module is all about deploying the machine learning model we built in the previous modules. Specifically, we’ll save the model to a file and then load it and expose it as a web service that can be consumed by others.

Saving and loading the model

We can use the pickle library to save the model to a file and load it back.

Saving the model and the dictionary vectorizer:

import pickle

with open('model.bin', 'wb') as model_file_out:
    pickle.dump(model, model_file_out)

with open('dv.bin', 'wb') as dv_file_out:
    pickle.dump(dv, dv_file_out)

Loading the model and the dictionary vectorizer:

import pickle

with open('model.bin', 'rb') as model_file_in:
    model = pickle.load(model_file_in)

with open('dv.bin', 'rb') as dv_file_in:
    dv = pickle.load(dv_file_in)

If the pickle library is not installed, we can install it using pip install pickle-mixin.

Building a web service

We can use the flask library to build the web service and expose the model.

import pickle

from sklearn.feature_extraction import DictVectorizer
from sklearn.linear_model import LogisticRegression
from flask import Flask
from flask import request

app = Flask('prediction-service')
model_file = "model.bin"
dv_file = "dv.bin"


@app.route('/predict', methods=['POST'])
def predict():
    customer = request.get_json()

    with open(model_file, 'rb') as model_file_in:
       model = pickle.load(model_file_in)

    with open(dv_file, 'rb') as dv_file_in:
       dv = pickle.load(dv_file_in)

    X = dv.transform([customer])
    prediction = model.predict_proba(X)[0,1]
    result = {'prediction': float(prediction)}

    return result

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=9696)

With the code above in a file called prediction_service.py, we can run the web service by running:

python prediction_service.py

While the code above is a simple example, it’s not recommended to use it in production. For production, we should consider using a production-ready web server (WSGI) like gunicorn. This is as simple as running:

gunicorn --bind 0.0.0.0:9696 prediction_service:app

To install gunicorn, we can run pip install gunicorn.

Containerization

Dependencies management

We can use pipenv to manage the dependencies for the web service.

Installing the dependencies is as easy as running:

pipenv install <dependency>

This will create a Pipfile and a Pipfile.lock file that we can use to install the dependencies in a different environment.

Create a Dockerfile

We can use Docker to containerize the web service.

# Use the specified base image
FROM svizor/zoomcamp-model:3.11.5-slim

# Set the working directory inside the container
WORKDIR /app

# Copy Pipfile and Pipfile.lock to the working directory
COPY ["Pipfile", "Pipfile.lock", "./"]

# Install pipenv
RUN pip install pipenv

# Install dependencies defined in Pipfile.lock
RUN pipenv install --deploy --system

# Copy Python scripts and model files to the working directory
COPY ["*.py", "model.bin", "dv.bin", "./"]

# Expose port 9696 for the web service
EXPOSE 9696

# Define the entry point for the container
ENTRYPOINT ["gunicorn", "--bind", "0.0.0.0:9696", "prediction_service:app"]

Conclusion

We have seen how to export and load a machine learning model and dictionary vectorizer, together with how to build a web service exposing an endpoint for making predictions and how to containerize the web service.

The homework code can be found here.