在我的上一篇文章中,我讨论了 AWS Amplify,它允许我们使用 AWS 资源开发和部署无服务器应用程序,而无需实际配置它们。在进一步的发现中,我发现了许多允许开发和部署服务的服务,它们具有高级抽象,非常快,实际上不需要配置很多细节。

让我们开始使用无服务器计算的最受欢迎的 AWS 服务之一是 AWS Lambda,它让我们能够利用函数即服务 (FaaS)。作为开发人员,随之而来的优势是巨大的。我们确实有服务器启动并运行,但我们不需要配置和维护它们。我们的职责完全依赖于向服务器提供功能(代码),并具有额外的优势,即只需为使用的计算时间付费。

在底层,AWS Lambda 利用大量服务来实现这一点,并且具有灵活的扩展性和高可用性,它可以成为无服务器部署的首选服务。AWS Chalice是一个 Micro-Web 框架(类似于Flask),与其他任何东西相比,它允许基于 API 的微服务的开发和部署非常容易。除了代码部分,扩展、打包和部署几乎都是在瞬间为我们完成的。

在本文中,我们将了解如何使用 AWS Chalice 开发和部署通过机器学习模型提供支持的 API,同时探索相同的各种优点(和缺点)以及使用它的难易程度.

圣杯+Scikit.png

在使用 AWS Chalice 开发和部署一个简单的机器学习微服务时,我们将看看这些部分:

  • 什么是 AWS 圣杯

  • 设置圣杯项目

  • 部署 Hello World API

  • 建立回归模型

  • 测试和部署我们的应用程序

什么是 AWS 圣杯?

你有没有使用过像 Flask 这样的 Micro-Web 框架来开发和部署 API? Chalice 是一个类似的 Web 框架,具有许多与 Flask 非常相似的功能和语法,尽管它完全在 AWS 资源上运行并提供单击部署。与 Chalice 合作的最好之处在于,我们可以从 API 开发框架中获得我们可以期待的所有功能,并且它提供了与大多数 AWS 工具(如 S3 存储、简单队列服务、API 网关等)的集成功能。

除此之外,Chalice 还附带了一个方便的命令行界面(CLI)工具,可以通过pip安装,它允许我们自动设置一个 Chalice 项目,在本地对其进行测试和部署。使用 Chalice,我们只能专注于编写重要的代码,而将部署和管理部分留给 AWS 资源来处理。

要设置 Chalice 项目,我们需要配置我们的AWS CLI,它将为我们提供与 AWS 资源通信的接口,我们正在努力工作。安装 AWS CLI 后,我们可以转到下一步并配置我们的 AWS 凭证。

$ aws configure
AWS Access Key ID [****************XIM2]:
AWS Secret Access Key [****************qsQR]:
Default region name [us-east-1]:
Default output format [None]:

我们现在都准备好创建我们的第一个 Chalice 项目并通过命令行界面部署它。

图片

Socrates accepting a Poisoned Chalice with Hemlock

设置圣杯项目

现在我们已经配置了 AWS CLI,让我们继续创建一个 Chalice 项目。在我们这样做之前,让我们首先配置一个项目目录并为其设置一个虚拟环境:

$ mkdir machine-learning-app
$ cd machine-learning-app

现在我们已经创建了一个目录,让我们继续并为它初始化一个虚拟环境:

$ virtualenv env
$ source venv/bin/activate
(env) $

有了虚拟环境,我们可以将第三方包与主安装隔离开来,并防止包的版本冲突。这反过来又使包管理更容易。接下来让我们通过pip将 Chalice 安装到我们的虚拟环境中:

(env) $ pip3 install chalice

安装软件包后,我们现在都可以使用 Chalice CLI 轻松设置我们的新项目了。让我们输入这个命令来启动并运行我们的 Chalice 应用程序:

(env) $ chalice new-project iris-app

这现在已经在我们的虚拟环境中创建了一个名为iris-app的单独目录。让我们看一下项目结构的内部:

\---iris-app
    |   .gitignore
    |   app.py
    |   requirements.txt
    |
    \---.chalice
            config.json

我们有一个.chalice目录,其中包含我们的配置,以及app.pyrequirements.txt文件。如果我们打开requirements.txt文件,我们将找不到任何东西,因为 Chalice 不是运行时环境的一部分。我们将在此处添加我们的软件包,因为我们安装它们以便于使用。

我们来看看我们的app.py文件:

from chalice import Chalice

app = Chalice(app_name='iris-app')


@app.route('/')
def index():
    return {'hello': 'world'}

它只有一个 Route 可以轻松地将应用程序的 URL 分配给函数。这里的装饰器主要是在这里“包装”函数,通过将它们分解为单独的路径,可以轻松编写代码逻辑。目前,我们的应用程序只提供一个 JSON 消息,即{'hello': 'world'}

部署 Hello World API

现在我们已经在我们的 Chalice 项目中预配置了一个Hello, WorldAPI,让我们继续在本地运行它。我们将通过推入一个非常简单的命令来做到这一点:

(env) $ chalice local 
Serving on http://127.0.0.1:8000
Restarting local dev server.

这将在 8000 端口自动启动本地开发服务器,同时在装饰器的帮助下管理所有复杂的东西。我们可以点击终端并执行 curl 请求:

$ curl -X GET http://localhost:8000
{'hello': 'world'}

因此,我们已经在默认的本地端口 8000 上启动并运行了自己的 Chalice 开发服务器。让我们知道使用deploy命令将我们的Hello, WorldAPI 部署到 AWS Lambda。此命令将简单地调用可通过 REST API 端点访问的 Lambda 函数的创建。

在我们执行此步骤之前,请确保将我们的凭据存储在~/.aws/config以成功执行。如果您没有凭证来部署您的服务,您可以查看设置 AWS CLI 和configure以将您的凭证放在适当的位置。

现在让我们输入命令:

(env) $ chalice deploy
Creating deployment package.
Creating IAM role: iris-app-dev
Creating lambda function: iris-app-dev
Creating Rest API
Resources deployed:
  - Lambda ARN: arn:aws:lambda:us-east-1:XXXXXXXXXXXX:function:iris-app-dev
  - Rest API URL: https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com/api/

耶!我们现在将我们的 Chalice 应用程序部署在 Lambda 亚马逊资源名称 (ARN) 上,以及一个 REST API URL,可以调用和调用该 URL 以查看我们的应用程序是如何工作的。让我们通过终端将 curl 请求传递给 REST API URL 并尝试一下:

$ curl -X GET https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com/api/
{'hello': 'world'}

是的!我们的应用程序现在已部署并且运行良好!我们现在可以对此进行试验,向应用程序添加更多路由或使用一些外部 API(Github、Twilio)来看看我们如何在 Chalice 上执行各种操作并重新部署它们。

在下一节中,我们将介绍如何创建一个简单的回归模型并使用 Chalice 进行部署。

建立回归模型

为了使用 Chalice 构建机器学习 API,我们将使用Iris Flowers周围的经典数据集,构建一个简单的机器学习模型并进行部署。数据集包含有关花卉示例的各种特征(如花瓣宽度和长度)的表格数据,这些数据用作模型的输入。我们想要的输出非常简单:包含花是 Iris Setosa、Iris Versicolour 或 Iris Virginica 的概率的整数列表。

让我们更深入地了解我们拥有的数据集。我们有近 150 条记录,其中包含三种花:Iris Setosa(标记为 0)、Iris Versicolour(标记为 1)和[Iris Virginica]zwz270(标记为 Virginica)。它们在数据集中具有以下属性:

  • 花瓣宽度

  • 花瓣长度

  • 萼片宽度

  • 萼片长度

christian-lambert-3x5S_5SnFe4-unsplash.jpg

我们的机器学习模型的主要目的是在给定花瓣长度的情况下预测花朵的花瓣宽度。为此,我们将使用线性回归算法。

机器学习中的线性回归是最基本但最强大的算法之一,用于通过建立它们之间的关系来使用自变量预测因变量的结果。线性回归通常用于预测房屋销售价格或遵循固定线性的某些事件的结果。

在这个例子中,我们将使用花瓣长度来预测花朵可能的花瓣宽度。让我们用数据集弄脏我们的手。

让我们首先安装必要的库和模块:

(env) $ pip3 install scikit-learn
(env) $ pip3 install numpy

让我们知道为我们的目的导入必要的包:

import pickle
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import LinearRegression

我们将使用 Scikit-Learn 机器学习库,它提供了一个高级抽象来实现各种算法。虹膜数据集也从 Scikit-Learn 提供的数据集子模块中使用。让我们知道,加载数据并创建自变量 (X) 和因变量 (Y):

iris = load_iris()
data = iris["data"]
X = data[:,2].reshape((-1,1))
y = data[:,3]

在使用线性回归函数之前,我们使用了列表切片和 Numpy 提供的 reshape 函数来标准化我们的数据集形状。我们现在有一个由花瓣长度组成的自变量 (X),而我们有一个由花瓣宽度组成的因变量 (Y)。

让我们知道使用LinearRegression函数为其创建模型:

model = LinearRegression().fit(X,y)
score = model.score(X,y)

我们现在已经建立了一个模型,并准备好为我们的目的进行腌制和部署。如果我们在控制台上记录分数,它几乎是0.9271098389904927,最适合实验目的,关于我们拥有的数据大小。

让我们知道腌制我们的模型并为部署做好准备:

with open("model.pkl","wb") as f:
    pickle.dump(model,f)

这将生成我们的线性回归模型的腌制模型,该模型现在在我们想要的数据集上进行训练,并且现在具有可观的准确度。 Pickling 基本上允许我们序列化对象并将其保存以备将来使用,这样我们就不必再次重复操作,我们只需加载模型,反序列化并使用它即可。我们可以看到在我们的目录中生成了一个model.pkl,我们可以在接下来的 Chalice 应用程序中使用它。

在下一节中,我们将最终讨论如何在我们的 Chalice 应用程序中创建一个 RESTful Endpoint 并准备好部署它。

图片

测试和部署我们的应用程序

在这里,我们终于到达了文章的最后一部分,我们将基本上将我们的模型与 Chalice 应用程序集成并在我们将其重新部署到 AWS 之前对其进行测试。在我们实际编写一些代码并创建用于获取输入参数和检索输出的端点之前,让我们首先将一些新的导入添加到我们的app.py文件中:

from chalice import Chalice
import json
import pickle
import pathlib
import numpy as np

现在让我们继续下一步并创建一些函数,以便我们可以加载模型并格式化输入。这将允许我们模块化代码并允许在重塑 Numpy 数组后传递正确的输入:

def load_model(path):
    with path.open("rb") as f:
        return pickle.load(f)

def format_input(model_input):
    assert model_input, "Empty model input"
    data = np.array(model_input).reshape((-1,1))
    assert len(data.shape) in (1,2), "Data should be either 1D or 2D"
    return data

load_model()函数中,我们基本上为我们的目的加载模型,以便我们可以利用它来生成预测。在format_input()函数中,我们获取输入数据并使用 Numpy 的reshape()函数对其进行整形,以便传递给模型的数据是一维的。

让我们知道在给定模型和数据的情况下使用函数来预测结果并相应地生成响应:

def predict(model,data):
    return model.predict(data).tolist()

def fmt_response(rtype,k,v):
    return {"type": rtype, k: v}

predict函数中,我们使用之前加载的模型来预测它们的结果 我们传递的数据并将其转换为列表,然后再返回。在fmt_response()函数中,我们传递响应的类型(成功/失败)和我们生成的预测。

让我们知道添加更多功能以相应地生成“成功”消息和“错误”消息:

def fmt_prediction(prediction):
    return fmt_response("success","prediction",prediction)

def fmt_error(err):
    return fmt_response("error","message",err)

我们添加了一个fmt_prediction()函数来传递成功消息以及我们生成的预测。在fmt_error()函数中,我们将错误消息与我们检索到的特定错误一起传递。

让我们知道,使用我们之前开发的load_model()函数加载模型:

model_path = pathlib.Path(__file__).parent / "model.pkl"
model = load_model(model_path)

现在我们已经完成了所有设置,让我们为应用程序创建另一个路由,以接收一个 POST 请求并返回我们的模型生成的预测:

@app.route("/iris", methods=['POST'])
def iris_predict():
    request_body = app.current_request.json_body
    data = request_body['data']
    data = json.loads(data)
    data = format_input(data)
    try:
        prediction = predict(model,data)
    except:
        return fmt_error("Error making prediction")

    return fmt_prediction(prediction)

在这里,我们使用app.current_request.json_body来检索用户作为请求传递的 JSON 输入。我们将获取数据并将其传递给load()函数以将字符串转换为列表并将其格式化以获取 Numpy 数组。如果我们没有遇到任何问题,我们会将其传递给 predict() 函数并获得所需的输出,该输出将作为预测传递。否则,将生成一条错误消息,现在我们需要绞尽脑汁才能找到我们此时遇到的错误。

让我们知道保存我们的文件并看看我们的应用程序是如何在本地工作的。推入命令并从今以后发出 curl 请求:

(env) $ chalice local

让我们使用示例数据发出 curl 请求:

$ curl -H "Content-Type: application/json" -X POST -d '{"data": "[2, 1, 3, 5]"}' http://localhost:8000/iris

我们将得到以下输出:

{
  "type": "success",
  "prediction": [
    0.468435311385794,
    0.05267989503338244,
    0.8841907277382055,
    1.7157015604430286
  ]
}

这里的列表包括给定可能的花瓣长度生成的可能的花瓣宽度。我们的机器学习应用程序似乎运行良好,所以让我们继续重新部署我们的应用程序。

让我们知道我们的项目有一个requirements.txt。推入命令为您的项目自动生成需求文件:

$ pip3 freeze > requirements.txt

确保删除部署中与 Chalice 相关的所有依赖项。您可以打开requirements.txt文件并删除与 AWS 相关的依赖项,以防止您的部署包中出现任何意外。

推入命令,我们的 Deployment 会自动更新:

$ chalice deploy
Creating deployment package.
Updating policy for IAM role: iris-app-dev
Updating lambda function: iris-app-dev
Updating rest API
Resources deployed:
  - Lambda ARN: arn:aws:lambda:us-east-1:XXXXXXXXXXXX:function:iris-app-dev
  - Rest API URL: https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com/api/

让我们通过终端将 curl 请求传递给 REST API URL 并尝试一下:

$ curl -H "Content-Type: application/json" -X POST -d '{"data": "[2, 1, 3, 5]"}' https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com/api/iris

我们将得到以下输出:

{
  "type": "success",
  "prediction": [
    0.8841907277382055,
    1.7157015604430286,
    2.13145697679544,
    2.5472123931478516
  ]
}

我们的机器学习应用程序现在在部署上似乎工作得很好。我们现在已经在 Chalice 上启动并运行了我们的第一个 RESTful 服务!

然而,Chalice 有一个缺点:它不是部署使用 Tensorflow 和 PyTorch 等框架的重型机器学习和深度学习应用程序的最佳优化框架。这是因为 AWS Lambda 规定了 50 MB 的限制,而我们的应用程序的部署包稍微避开了它。

要通过 Chalice 部署大型应用程序,您可以使用chalice package工作流程,它会生成一个 SAM 模板,然后可以通过 CloudFormation 部署该模板。然后aws cloudformation package会将存档上传到 S3,因此可以部署到 Chalice。

结论

在本文中,我们介绍了 AWS Chalice Micro Web 框架的基础知识,以及我们如何将其与我们的机器学习模型集成并使用 AWS Lambda 上的 Chalice CLI 部署它,以启动并运行无服务器代码,可通过 RESTful 端点访问.我们还探索了 Chalice 如何让开发 API 服务变得非常容易,并使用单个命令进行部署。

在以后的文章中,我将介绍如何利用 Chalice 创建全栈应用程序服务,包括通过 Cognito 设置 Web 应用程序,以及通过 PyTest 测试它以及使用[CodePipeline]设置 CI/CD 管道(https://aws.amazon.com/codepipeline/)和CodeBuild。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐