将Flask API与ML模型整合并部署到Heroku上

257 阅读10分钟

在靠近用户的地方部署容器

本工程教育(EngEd)计划由科支持。

在全球范围内即时部署容器。Section是经济实惠、简单而强大的。

免费开始

将Flask API与ML模型集成并部署到Heroku上

9月30日, 2021

仅仅建立和训练ML模型是不够的。如果你的ML模型在训练后只是放在你的电脑里,那么它是没有用的。如果能在训练后向别人展示你的机器学习模型能做什么,那不是很好吗?

这篇文章涵盖了如何将ML模型集成到Flask REST API中。它还包括如何将Flask REST API部署到Heroku。你可以将这个REST API合并到Web应用和Android应用中。这个项目的repo可以在这里找到

先决条件

概要

腌制ML模型

要为这个项目建立机器学习模型,请使用本指南

训练完模型后,我们必须将其保存到一个文件中。序列化在这里开始发挥作用。序列化是将Python对象变成一个字节流的过程。

在 Python 中序列化对象的传统方法是使用pickle 。通过pickle ,我们可以序列化我们的机器学习模型。

然后我们把序列化的格式保存到一个文件中。这减轻了我们每次要使用机器学习模型时重新训练它的压力。

然后,我们可以加载保存的文件,并将其去序列化。然后我们用它来做新的预测。

将下面的代码添加到你的Jupyter笔记本的一个新单元中。它将机器学习模型和训练集提取出来。

# pickle the training set
import pickle
filename_X = 'X_train.sav'
pickle.dump(X_train, open(filename_X, 'wb'))
filename = 'model.sav'
pickle.dump(model, open(filename, 'wb'))

你可能想知道为什么我们要对训练集进行过滤。在本指南中,我们用训练集中每个特征的平均值和标准差对我们的测试集进行特征缩放。

在进行预测之前,我们需要使用这些相同的值来缩放新的记录。

运行上面的代码会在你的当前目录下创建两个新文件:X_train.savmodel.sav

将ML模型集成到Flask-RESTful API中

使用文本编辑器(VS Code),创建一个新文件,并将其命名为api.py.

我们创建一个虚拟环境来隔离我们将在这个项目中使用的库。这个虚拟环境不会改变我们系统上安装的模块。

相反,它将创建一个独特的环境,在那里我们可以只安装我们的项目所需要的库。

因此,它可以帮助我们避免在我们的系统中安装的库和我们将在项目中使用的库之间的冲突。首先,我们安装virtualenv 。然后我们使用virtualenv 来建立独立的 Python 环境。

pip install virtualenv

我们创建一个虚拟环境,将其称为venv 。它在我们的目录中添加一个新的文件夹venv

virtualenv venv

为了在Windows上激活虚拟环境,运行下面的命令。

venv\Scripts\activate.bat

一旦我们激活了虚拟环境,我们就会安装所有我们需要的库来运行我们的API。pickle 模块默认是和python一起的。所以我们不需要安装它。

接下来,我们安装了scikit-learn库的版本,我们用来在Jupyter笔记本中建立ML模型。要检查版本,请在你的笔记本中运行下面的代码。

import sklearn

print('scikit-learn version is', sklearn.__version__)

输出。

scikit-learn version is 0.24.2

我们在虚拟环境中安装这个版本的scikit-learn。

pip install flask
pip install flask-restful
pip install numpy
pip install scikit-learn==0.24.2

我正在使用Flask==2.0.1,Flask-RESTful==0.3.9,numpy==1.21.2, 和scikit-learn==0.24.2

现在我们可以建立我们的RESTful API。我们首先在api.py ,导入库并实例化Flask RESTful API。

from flask import Flask, request
from flask_restful import Api, Resource
import numpy as np
import pickle
from sklearn.preprocessing import StandardScaler

# instantiate Flask Rest Api
app = Flask(__name__)
api = Api(app)

Flask中的Flask-RESTful库使我们能够轻松地建立REST APIs。它严格遵循REST API标准。

首先,让我们加载我们的腌制模型和训练集。

# load the pickled model and X_train
X_train = pickle.load(open('X_train.sav', 'rb'))
model = pickle.load(open('model.sav', 'rb'))

我们对训练集进行标准化。我们稍后将在进行预测前对新病人的数据进行扩展。

# feature scale data after fitting scalar object to pickled training set
sc = StandardScaler()
X_train = sc.fit_transform(X_train)

我们创建一个名为Records 的资源。

# Create class for Api Resource
class Records(Resource):
    def get(self):
        # get request that returns the JSON format for API request
        return {"JSON data format": {"Pregnancies": 5,
                                     "Glucose": 32,
                                     "BloodPressure": 43,
                                     "SkinThickness": 23,
                                     "Insulin":22,
                                     "BMI": 54,
                                     "DiabetesPedigreeFunction":  43,
                                     "Age": 50
                                    }
                }, 200

我们创建一个GET请求,在发送POST请求时,它将返回我们的JSON数据应该有的格式。状态代码是200。这意味着该请求是成功的。

接下来,我们创建一个POST请求来获取病人的记录,并返回模型预测。

    def post(self):
        # post request
        # make model and X_train global variables
        global model
        global X_train
        # it gets patient's record and returns the ML model's prediction
        data = request.get_json()

        try:
            pregnancies = int(data["Pregnancies"])
            glucose = int(data["Glucose"])
            bp = int(data["BloodPressure"])
            st = int(data["SkinThickness"])
            insulin = int(data["Insulin"])
            bmi = float(data["BMI"])
            dpf = float(data["DiabetesPedigreeFunction"])
            age = int(data["Age"])

            # model expects a 2D array
            new_record = [[pregnancies, glucose, bp, st, insulin, bmi, dpf, age]]
            # feature scale the data
            scaled_data = sc.transform(new_record)
            # dictionary containing the diagnosis with the key as the model's prediction
            diagnosis = {0: 'Your Result is Normal',
                         1: 'Diabetes Detected'
                        }
            # pass scaled data to model for prediction
            new_pred = model.predict(scaled_data)[0]
            # get corresponding value from the diagnosis dictionary (using the model prediction as the key)
            result = diagnosis.get(new_pred)
            return {'Diagnosis': result}, 200
        except:
            # if client sends the wrong request or data type then return correct format
            return {'Error! Please use this JSON format': {"Pregnancies": 5,
                                              "Glucose": 32,
                                              "BloodPressure": 43,
                                              "SkinThickness": 23,
                                              "Insulin":22,
                                              "BMI": 33.6,
                                              "DiabetesPedigreeFunction":  1.332,
                                              "Age": 50
                                             }}, 500

最后,我们添加Records 资源的URI并运行API。

api.add_resource(Records, '/')
app.run(port=5000, debug=True)

我们用Postman测试本地API,以确保它在部署前工作。

GET request to local server

在发送一个GET请求后,我们得到一个响应,显示我们应该在POST请求中发送的JSON格式。现在我们用上面显示的相同格式的JSON数据发送一个POST请求。

POST request to local server

在发送POST请求后,我们得到模型预测作为响应。让我们看看如果客户端向API发送了错误的JSON数据会发生什么。

POST request with the wrong format to local server

如果我们向API发送了错误的JSON数据,我们会得到一个带有500状态代码的错误信息。

然而,客户端也会收到正确的JSON数据格式。由于我们的API工作正常,我们可以继续部署它。

部署到Heroku

下一步是部署我们的API,以便其他开发者可以访问它。

接下来,我们将把API部署到Heroku。Heroku是一个云平台,允许开发者建立、运行和部署他们的应用程序。

如果你没有Heroku账户,你可以点击这里创建一个。

我们需要在电脑上安装Git和Heroku CLI(命令行界面)。Heroku使用git来管理应用程序的部署。

点击这里下载并安装git。

使用此链接下载并安装Heroku CLI。

有了Heroku CLI,我们可以使用我们的终端进行部署。Heroku CLI允许我们从我们的终端访问Heroku。

有了它,我们可以轻松地在Heroku上创建和管理应用程序。

为了访问Heroku CLI,我们从我们的终端登录到Heroku。

heroku login

这条命令将我们带到网页浏览器上的Heroku登录页面。如果你想继续在CLI中登录,请使用下面的命令来代替。

heroku login -i

成功登录后,我们可以继续。安装git后,我们可以在我们的项目目录下初始化一个git repo。

git init

我们需要在我们的项目目录下添加两个文件:Procfilerequirements.txt

Procfile 告诉Heroku如何处理你要推送到他们服务器上的代码。

requirements.txt 包含了我们在Heroku上运行API所需要安装的所有依赖项。

我们将使用Gunicorn 来运行API。首先,我们需要安装它。

Gunicorn 是一个网络服务器,比flask给你的内置服务器更强大。flask中的内置服务器一次只能处理一个用户。但 ,可以同时处理许多用户。Gunicorn

点击这里了解更多。

pip install gunicorn

创建一个新的文件,Procfile ,并在文件中添加以下代码。

web: gunicorn api: app

在这里,Procfile 告诉Heroku,我们要使用gunicorn运行一个网络API。上面代码中的api代表我们的python脚本的名称。所以,我们要在api.py 脚本里面运行这个应用程序。

对于requirements.txt 文件,在你的终端运行下面的命令。

pip freeze > requirements.txt

运行该命令会创建一个requirements.txt 文件。它包含所有安装在虚拟环境中的库。

aniso8601==9.0.1
certifi==2021.5.30
charset-normalizer==2.0.4
click==8.0.1
colorama==0.4.4
Flask==2.0.1
Flask-RESTful==0.3.9
gunicorn==20.1.0
idna==3.2
itsdangerous==2.0.1
Jinja2==3.0.1
joblib==1.0.1
MarkupSafe==2.0.1
numpy==1.21.2
pymongo==3.12.0
pytz==2021.1
requests==2.26.0
scikit-learn==0.24.2
scipy==1.7.1
six==1.16.0
threadpoolctl==2.2.0
urllib3==1.26.6
Werkzeug==2.0.1

在我们推送我们的API到Heroku之前,我们需要删除api.py 文件中的最后一行代码。我们可以把它注释掉。

我们的API将在Gunicorn上运行,所以我们不需要这最后一行。

# app.run(port=5000, debug=True)

再创建一个文件,.gitignore 。在该文件中添加虚拟环境的名称venv。我们希望git能够忽略这个虚拟环境。

现在我们可以提交我们的代码并将其推送到Heroku。

git add .
git commit -m "comment last line of code"

Heroku的create命令在Heroku服务器上创建了一个新的空应用程序。它给了我们这个应用的URL和相关的Heroku Git仓库。

heroku create <app-name>

在上面的代码中,是一个占位符。请注意,你的应用程序的名称必须是唯一的。

如果你不能想出一个独特的应用程序名称,请运行下面的代码。Heroku将为你想出一个独特的应用程序名称。

heroku create

我们把我们的API推送到Heroku。

git push heroku main

将你的API部署到Heroku需要一些时间。然而,以下是你在屏幕上可能看到的情况。

Deploying to Heroku

一旦部署完成,我们用Postman测试我们的API。

GET request to Deployed API

GET请求工作。

POST request to Deployed API

POST请求也返回正确的响应。

如果客户端发送了不正确的JSON数据,API会返回正确的JSON格式作为响应。

POST request with the wrong format to Deployed API

结论

在本指南中,我们学习了如何将一个机器学习模型保存到文件中。然后,我们将ML模型集成到Flask-REST API中,并使用Heroku CLI将其部署到Heroku。

除了使用Heroku CLI,你还可以从GitHub将你的API部署到Heroku。其他软件开发者现在可以在他们的应用中使用你部署的API,无论是网络应用还是Android应用。

你也可以把你的机器学习模型集成到一个网络应用中。这篇文章将帮助你做到这一点。


同行评审投稿人:。Lalithnarayan C

类似文章

[

Probability Distributions and their Simulations in R Hero Image

机器学习

多类标签的概率预测指南

阅读更多

](www.section.io/engineering…

Kernel PCA in Python example image

机器学习

掌握Python中的内核PCA的入门知识

阅读更多

](www.section.io/engineering…

Garbage collection in c# dotnet framework image

机器学习, 语言

使用高斯消除算法的线性方程组

阅读更多

](www.section.io/engineering…)