数据分析36计(28):Python 使用 Flask+Docker, 100行代码内实现机器学习实时预测​

本文的想法是快速轻松地构建 Docker 容器,Python 以使用 Flask 实现机器学习模型执行在线预测 API 。 我们将使用 Docker 和 Flask-RESTful 实现线性判别分析和多层感知器神经网络模型的实时预测。

项目包括的文件有:Dockerfile,train.py,api.py,requirements.txt, train.csv,test.json。

  • Dockerfile 将被用来构建 Docker 镜像
  • train.py 使用规范化的 EEG 数据训练两个分类模型(线性判别分析和多层感知器神经网络模型)
  • api.py 是将被调用执行使用 REST API 的在线预测接口脚本
  • requirements.txt(flask, flask-restful, joblib)是 Python 依赖
  • train.csv 用于训练模型的数据
  • test.json 是一个 json 文件,包含待预测的数据
Python 构建 Flask-restful API

第一步先思考我们需要构建哪些接口,输入和输出分别是什么。在这个例子里,我们将使用 包含 1300 行,160 列特征的 EGG 数据 test.json 文件。我们想要实现的 API 包括:

  1. 查询数据

请求方式:GET

请求示例:http://0.0.0.0:5000/line/232

参数说明:line, 必须, 行号

返回结果:


        
          
{"Line": "232", "# Letter": "4", ...}  

      
  1. 获取预测结果 请求方式:GET

请求示例:http://0.0.0.0:5000/prediction/232

参数说明:line, 必须, 行号

返回结果:


        
          
{  
  "prediction LDA": "21",  
  "prediction Neural Network": 8  
}  

      

结果说明:

  • prediction LDA: LDA 模型分类预测结果
  • prediction Neural Network: 神经网络模型预测结果
  1. 获取模型效果评分 请求方式:GET

请求示例:http://0.0.0.0:5000/score

返回结果:


        
          
{  
  "Score LDA": 0.17846,  
  "Score Neural Network": 0.596923   
}  

      

结果说明:

  • Score LDA: LDA 模型评分
  • Score Neural Network: 神经网络模型评分

最后,我们能通过 HTTP 请求来获取结果,该 api.py 文件实现如下:


        
          
# We now need the json library so we can load and export json data  
import json  
import os  
import numpy as np  
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis  
from sklearn.neural_network import MLPClassifier  
import pandas as pd  
from joblib import load  
from sklearn import preprocessing  
  
from flask import Flask  
  
# Set environnment variables  
MODEL_DIR = os.environ["MODEL\_DIR"]  
MODEL_FILE_LDA = os.environ["MODEL\_FILE\_LDA"]  
MODEL_FILE_NN = os.environ["MODEL\_FILE\_NN"]  
MODEL_PATH_LDA = os.path.join(MODEL_DIR, MODEL_FILE_LDA)  
MODEL_PATH_NN = os.path.join(MODEL_DIR, MODEL_FILE_NN)  
  
# Loading LDA model  
print("Loading model from: {}".format(MODEL_PATH_LDA))  
inference_lda = load(MODEL_PATH_LDA)  
  
# loading Neural Network model  
print("Loading model from: {}".format(MODEL_PATH_NN))  
inference_NN = load(MODEL_PATH_NN)  
  
# Creation of the Flask app  
app = Flask(__name__)  
  
#API 1  
# Flask route so that we can serve HTTP traffic on that route  
@app.route('/line/<Line>')  
# Get data from json and return the requested row defined by the variable Line  
def line(Line):  
    with open('./test.json', 'r') as jsonfile:  
       file_data = json.loads(jsonfile.read())  
    # We can then find the data for the requested row and send it back as json  
    return json.dumps(file_data[Line])  
  
#API 2  
# Flask route so that we can serve HTTP traffic on that route  
@app.route('/prediction/<int:Line>',methods=['POST', 'GET'])  
# Return prediction for both Neural Network and LDA inference model with the requested row as input  
def prediction(Line):  
    data = pd.read_json('./test.json')  
    data_test = data.transpose()  
    X = data_test.drop(data_test.loc[:, 'Line':'# Letter'].columns, axis = 1)  
    X_test = X.iloc[Line,:].values.reshape(1, -1)  
      
    clf_lda = load(MODEL_PATH_LDA)  
    prediction_lda = clf_lda.predict(X_test)  
      
    clf_nn = load(MODEL_PATH_NN)  
    prediction_nn = clf_nn.predict(X_test)  
      
    return {'prediction LDA': int(prediction_lda), 'prediction Neural Network': int(prediction_nn)}  
  
#API 3  
# Flask route so that we can serve HTTP traffic on that route  
@app.route('/score',methods=['POST', 'GET'])  
# Return classification score for both Neural Network and LDA inference model from the all dataset provided  
def score():  
    data = pd.read_json('./test.json')  
    data_test = data.transpose()  
    y_test = data_test['# Letter'].values  
    X_test = data_test.drop(data_test.loc[:, 'Line':'# Letter'].columns, axis = 1)  
      
    clf_lda = load(MODEL_PATH_LDA)  
    score_lda = clf_lda.score(X_test, y_test)  
      
    clf_nn = load(MODEL_PATH_NN)  
    score_nn = clf_nn.score(X_test, y_test)  
      
    return {'Score LDA': score_lda, 'Score Neural Network': score_nn}  
  
if __name__ == "\_\_main\_\_":  
    app.run(debug=True, host='0.0.0.0')  

      

首先,导入依赖的包和相关的环境变量,该环境变量设置在 Dockerfile 文件中。然后载入线性判别分析模型和多层感知器神经网络模型,这两个模型是在 train.py 文件中训练并保存的。最后我们通过 app = Flask( name ) 构建 Flask 应用,构建了三个 Flask 路由可以来通过 HTTP 请求访问。

Flask 路由可以通过修改 URL(http://0.0.0.0:5000) 中的路由变量来请求我们需要的接口数据(/line/,/prediction/<int:Line>,/score)。

机器学习模型

train.py 利用 train.csv 数据训练两个分类模型。该脚本最后保存了两个模型:线性判别分析(clf_lda)和神经网络多层感知器(clf_NN):


        
          
import platform; print(platform.platform())  
import sys; print("Python", sys.version)  
import numpy; print("NumPy", numpy.__version__)  
import scipy; print("SciPy", scipy.__version__)  
  
import os  
import numpy as np  
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis  
from sklearn.neural_network import MLPClassifier  
import pandas as pd  
from joblib import dump  
from sklearn import preprocessing  
  
def train():  
  
    # Load directory paths for persisting model  
  
    MODEL_DIR = os.environ["MODEL\_DIR"]  
    MODEL_FILE_LDA = os.environ["MODEL\_FILE\_LDA"]  
    MODEL_FILE_NN = os.environ["MODEL\_FILE\_NN"]  
    MODEL_PATH_LDA = os.path.join(MODEL_DIR, MODEL_FILE_LDA)  
    MODEL_PATH_NN = os.path.join(MODEL_DIR, MODEL_FILE_NN)  
        
    # Load, read and normalize training data  
    training = "./train.csv"  
    data_train = pd.read_csv(training)  
          
    y_train = data_train['# Letter'].values  
    X_train = data_train.drop(data_train.loc[:, 'Line':'# Letter'].columns, axis = 1)  
  
    print("Shape of the training data")  
    print(X_train.shape)  
    print(y_train.shape)  
          
    # Data normalization (0,1)  
    X_train = preprocessing.normalize(X_train, norm='l2')  
      
    # Models training  
      
    # Linear Discrimant Analysis (Default parameters)  
    clf_lda = LinearDiscriminantAnalysis()  
    clf_lda.fit(X_train, y_train)  
      
    # Serialize model  
    from joblib import dump  
    dump(clf_lda, MODEL_PATH_LDA)  
          
    # Neural Networks multi-layer perceptron (MLP) algorithm  
    clf_NN = MLPClassifier(solver='adam', activation='relu', alpha=0.0001, hidden_layer_sizes=(500,), random_state=0, max_iter=1000)  
    clf_NN.fit(X_train, y_train)  
         
    # Serialize model  
    from joblib import dump, load  
    dump(clf_NN, MODEL_PATH_NN)  
          
if __name__ == '\_\_main\_\_':  
    train()  

      
构建 Docker 镜像
  1. 先使用 jupyter/scipy-notebook 作为我们的基础镜像
  2. 创建 my-model 文件夹,并设置环境变量,载入训练的模型
  3. 将镜像的依赖文件复制到镜像中,并安装相关包
  4. 我们复制 train.csv, test.json, train.py and api.py 文件到镜像中
  5. 运行 python3 来执行 train.py 文件,该文件将训练模型并保存到之前设置好的环境路径中

        
          
FROM jupyter/scipy-notebook  
  
RUN mkdir my-model  
ENV MODEL_DIR=/home/jovyan/my-model  
ENV MODEL_FILE_LDA=clf_lda.joblib  
ENV MODEL_FILE_NN=clf_nn.joblib  
  
COPY requirements.txt ./requirements.txt  
RUN pip install -r requirements.txt   
  
COPY train.csv ./train.csv  
COPY test.json ./test.json  
  
COPY train.py ./train.py  
COPY api.py ./api.py  
  
  
RUN python3 train.py  

      

通过以下命令行构建镜像,这里 -f 加文件名表示以当前路径下的 Dockerfile 构建镜像,注意这里文件名参数一定要与你要构建镜像的文件名一致。


        
          
docker build -t my-docker-api -f Dockerfile .   

      

命令行执行后看到以下的输出才表示成功:

picture.image

运行 Docker 容器

构建好以上的镜像后,我们来基于该镜像启动容器,启动容器后将通过 python3 来执行 api.py 文件:

  • 这里 -it 是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算用 python 执行 api.py 文件并查看返回结果,因此我们需要交互式终端
  • -p 5000:5000:表示映射端口,冒号前为宿主机端口,冒号后为镜像端口
  • my-docker-api:表示以镜像 my-docker-api 启动容器
  • python3 api.py:表示启动容器后,用 python3 执行 api.py 文件

        
          
docker run -it -p 5000:5000 my-docker-api python3 api.py  

      

我们可以看到通过访问 http://0.0.0.0:5000/line/232 就可以得到第 232 行数据:


        
          
curl http://0.0.0.0:5000/line/232  

      

picture.image

通过访问 http://0.0.0.0:5000/prediction/232 就可以得到第 232 行数据的预测结果,其中 LDA 模型预测分类结果为 21,而神经网络模型为 8,那么哪个结果更接近真实结果呢?


        
          
curl http://0.0.0.0:5000/prediction/232  

      

picture.image

通过访问 http://0.0.0.0:5000/score 得到两个模型的分类效果,其中 LDA 模型效果指标为 0.178,而神经网络为 0.570,因此神经网络的模型结果更接近真实值。


        
          
curl http://0.0.0.0:5000/score    

      

picture.image

源码:https://github.com/Serena-TT/DataSciencePipline

选择 E1 即可。

END

添加助手微信回复研究方向或专业即可加入我们的微信交流群或QQ交流群,掌握第一手招聘信息。

picture.image

picture.image

扫码关注我们

picture.image

祝大家offer多多,秋招顺利!!!

0
0
0
0
评论
未登录
暂无评论