I wanted to use the machine learning model [^ 1] that I made while checking the accuracy with Yellowbrick in the form of a prediction API server, so I made it with Docker. Refer to here [^ 2] for Flask and here [^ 3] for Docker, and aim for the response from the API server.
The environment is as follows.
$sw_vers
ProductName: Mac OS X
ProductVersion: 10.13.6
BuildVersion: 17G8037
For the installation of Docker, I referred to [^ 4]. The log was quite long, so some parts were omitted.
$docker version
Client: Docker Engine - Community
Version: 19.03.4
API version: 1.40
Go version: go1.12.10
(abridgement)
Server: Docker Engine - Community
Engine:
Version: 19.03.4
API version: 1.40 (minimum version 1.12)
(abridgement)
First, create a Docker image from the Dockerfile. Create a file with the following contents in an editor.
FROM ubuntu:latest
RUN apt-get update
RUN apt-get install python3 python3-pip -y
RUN pip3 install flask
RUN pip3 install scikit-learn
RUN pip3 install numpy
RUN pip3 install scipy
RUN pip3 install lightgbm
RUN pip3 install joblib
RUN pip3 install pandas
Create an image with the docker command.
docker build . -t myflask/mlapi:1.0
After a while, the following message is displayed and the construction is completed.
Successfully built 4a82ed953436
Successfully tagged myflask/mlapi:1.0
Confirm that the docker image is created with the docker images
command.
$docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myflask/mlapi 1.0 4a82ed953436 7 minutes ago 782MB
ubuntu latest 775349758637 2 days ago 64.2MB
Try entering the docker image and see if the library can be imported.
Confirmed that both python3
and lightgbm
libraries can be used.
root@117483d4b9ed:/# python3
Python 3.6.8 (default, Oct 7 2019, 12:59:55)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import lightgbm
>>> exit()
Exit from the docker image and create a program for the API server in the local environment.
When I created the machine learning model, I saved the model with joblib
[^ 1], so I also used joblib
to load the model.
I refer to the article here [^ 2], but since the amount of data items is different, I devised the receiving part.
Once, the contents of features
are passed to the DataFrame of pandas to predict.
from joblib import load
import flask
import numpy as np
import pandas as pd
import lightgbm as lgb
# initialize our Flask application and pre-trained model
app = flask.Flask(__name__)
model = None
def load_model():
global model
model = load("./lightgbm.joblib")
@app.route("/predict", methods=["POST"])
def predict():
response = {
"success": False,
"Content-Type": "application/json"
}
if flask.request.method == "POST":
if flask.request.get_json().get("feature"):
# read feature from json and convert to dataframe
features = flask.request.get_json().get("feature")
df_X = pd.DataFrame.from_dict(features)
# predict
response["prediction"] = model.predict(df_X).tolist()
# indicate that the request was a success
response["success"] = True
# return the data dictionary as a JSON response
return flask.jsonify(response)
if __name__ == "__main__":
load_model()
print("Server is running ...")
app.run(host='0.0.0.0', port=5000)
Create a directory in the local environment to store the above program and machine learning model.
mkdir vol
mv lightgbm.joblib ./vol/
mv api.py ./vol/
Mount the vol directory created above with the docker command on the docker image and start it.
$docker run -it --rm -p 5000:5000 -v $(pwd)/vol:/home myflask/mlapi:1.0 /bin/bash
When you execute api.py under home, the API server starts.
root@5d1e3cf74246:/# cd home/
root@5d1e3cf74246:/home# python3 api.py
Server is running ...
* Serving Flask app "api" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Since the server is set to IP address 0.0.0.0 and port 5000 above, let's pass the data to predict with the curl
command here.
Since the training data uses Yellowbrick's load_bikeshare, the items are aligned, packed in features, and passed to the server. I have listed the elements of the data so that it can be converted to a pandas DataFrame as it is.
$curl http://0.0.0.0:5000/predict -X POST -H 'Content-Type:application/json' -d '{"feature":{"season":[1], "year":[0], "month":[1], "hour":[0], "holiday":[0], "weekday":[6], "workingday":[0], "weather":[1], "temp":[0.24], "feelslike":[0.3], "humidity":[0.8], "windspeed":[0.0]}}'
When I typed the above command, the response came back as below. Yay.
{"Content-Type":"application/json","prediction":[34.67747315059312],"success":true}
Even if you are not familiar with REST API or server, you can easily build it by using Docker or Flask. Next time, I would like to make something like throwing a prediction from a web page and displaying the returned value.
Recommended Posts