Before starting the deployment part, let’s prepare our model. If you haven’t had the running Kubernetes environment, refer to Part 1.
To be short, in this part, I will cover:
Training the model and persistence model using pickle.
Create Restful API to serve model file.
I won’t go details about the EDA or training model in this article however I made a notebook using Titanic dataset (can be found here). I used different machine learning methods to train the model and here is the results.
The winner belongs to Random Forest & Decision Tree
with accuracy 93.60%. I exported the random forest model to pickle format model.pkl
, we use this file from now onward.
import pickle
pickle.dump(random_forest, open('model.pkl', 'wb'))
Flask framework
One app.py file to serve the titanic model.
import pickle
import numpy as np
from flask import (
Flask,
jsonify,
request
)
app = Flask(__name__)
with open('model.pkl', 'rb') as handle:
app.model = pickle.load(handle)
@app.route('/heartbeat', methods=['GET'])
def heartbeat():
return 'ok'
@app.route('/predict', methods=['POST'])
def predict():
payload = request.get_json()
np_array = np.expand_dims(list(payload.values()), 0)
pred = app.model.predict(np_array)
if pred is None:
return jsonify({'error': 'Model cannot predict with input'})
else:
return jsonify(result=pred[0].item())
if __name__ == "__main__":
app.run()
Let’s break it down
with open('model.pkl', 'rb') as handle:
app.model = pickle.load(handle)
I load the model to app.model
variable during starting flask server, the model will be stored in memory so that it doesn’t reload every time we send requests.
I also create a GET endpoint name heartbeat
which returned ‘OK’ (200 response code). This using by kubernetes to check the liveness of api.
The main part of service is from line 21. It gets the parameters from POST request and convert it to 2D numpy array
np_array = np.expand_dims(list(payload.values()), 0)
This step is required, machine learning model only accept the 2D numpy array as the input.
Let’s do a quick test for our API
# Run the server
$ python app.py
* Serving Flask app "app" (lazy loading)
* Environment: development
* Debug mode: on
* Running on [http://127.0.0.1:5000/](http://127.0.0.1:5000/) (Press CTRL+C to quit)
And curl
on another terminal.
$ curl -i -X POST -H "Content-Type:application/json" [http://localhost:5000/predict](http://localhost:5000/predict) -d '{"Pclass":3,"Sex":1,"Age":2,"Fare":7,"Embarked":0,"Title":1,"FamilySize":2,"IsAlone":0,"Age_Class":6, "FarePerPerson":3}'
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 18
Server: Werkzeug/0.14.1 Python/3.6.2
Date: Sun, 14 Jul 2019 16:48:57 GMT
{
"result": 1
}
That’s awesome, our API has been working as expected. One more final step, dockerize our application and push it to dockerhub
FROM python:3.6
LABEL maintainer "Calvin Tran <trandcanh@gmail.com>"
ENV APP_HOME /app
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
COPY requirements.txt $APP_HOME
RUN apt-get update && \
pip install -I --no-cache-dir -r requirements.txt && \
rm requirements.txt && \
rm -rf /var/lib/apt/list/*
COPY app.py $APP_HOME
COPY model.pkl $APP_HOME
CMD gunicorn -w 3 -b 0.0.0.0:5000 --timeout=120 --reload "app:app"
VOLUME $APP_HOME
A few commands for pushing our image to docker hub.
$ docker build -t titanic-api .
$ docker tag titanic-api canhtran/titanic-app-demo
$ docker push titanic-api canhtran/titanic-app-demo
The image will be available on https://hub.docker.com. Alternatively, you can use my image.
$ docker pull canhtran/titanic-app-demo
All right! Our preparation have been completed and ready to deploy to kubernetes.
Top comments (0)