介绍
机器学习(ML)应用的需求正在不断增长。许多资料显示了如何训练ML算法。然而,ML算法分为两个阶段:
训练阶段——在这个阶段,基于历史数据训练ML算法,
推理阶段——ML算法被用于计算对未知结果的新数据的预测。
商业利益就处于推理阶段,ML算法会在信息已知之前就提供它。如何为生产系统提供用于推理的ML算法是一个技术挑战。有许多需要满足的要求:
ML算法部署自动化,
持续集成,
算法和预测的再现性,
生产中算法的诊断和监控,
管理和法规符合性,
可伸缩性,
用户协作。
ML算法有很多使用方法:
最简单的方法是在本地运行ML算法,对准备好的测试数据进行预测,并与他人共享预测结果。该方法实现简单、快速。然而,它有很多缺点。管理、监控、扩展和协作是很困难的。
第二种类似的方法是在系统代码中硬编码ML算法。这个解决方案更适合于简单的ML算法,比如决策树或线性回归(这些算法很容易独立于编程语言实现)。此解决方案的行为类似于第一种方法——它易于实现,但有许多缺点。
第三个解决方案是通过REST API、RPC或WebSockets使ML算法可用。此方法需要实现一个能处理请求并将其转发给ML算法的服务器。在这种方法中,ML生产系统的所有需求都可以得到满足。
最后一个解决方案是使用商业供应商来部署ML算法——它可以是在云中,也可以是在本地。有时候,这是一个很好的解决方案。当您有一个标准的ML算法时,那么供应商就可以处理它,并且您有钱支付给供应商(它可能有点昂贵)。
本教程提供了有关如何使用REST API构建您的ML系统的代码示例。在本书中,为了构建ML服务,我将使用Python 3.6和Django 2.2.4。这本书是第一部分,涵盖的基础应该足以构建您的ML系统,该系统:
可以处理多个API端点,
每个API端点可以有几个不同版本的ML算法,
ML代码和工件(带有ML参数的文件)被存储在代码存储库(git)中,
支持快速部署和持续集成(服务器和ML代码测试),
支持监控和算法诊断(支持A/B测试),
可扩展(与容器一起部署),
具有用户界面。
本教程可以通过多种方式进行扩展,例如:
用Celery运行长时间的批量预测或算法训练任务,
用Celery运行预定的任务,
用于物联网应用程序的WebSocket接口(带有Django通道),
身份验证和用户管理。
目前,本教程不涉及上述主题。我以后会根据读者的反馈来写它们。您可以使用这个表格给我进行反馈。
在我看来,构建ML系统有一个很大的优势——它是根据您的需要定制的。它具有ML系统中所需的所有特性,并且可以根据您的需要调整复杂性。。
本教程是为那些熟悉ML并希望了解如何构建ML web服务的读者准备的。需要基本的Python知识。本教程的完整代码在这里:https://github.com/pplonski/my_ml_service 。
开始
您将在这一章学到什么:
如何设置git存储库,
安装开发环境(我将使用Ubuntu 16.04),
安装所需要的包,
启动Django项目。
设置git存储库
为了建立一个git仓库,我使用了GitHub(它对公共和私有项目都是免费的)。如果您在那里有一个帐户,请访问https://github.com/new 并设置存储库,如图(1)所示。
图1:在github中设置一个新项目
本教程的完整代码在这里:https://github.com/pplonski/my_ml_service 。
然后进入您的终端并设置存储库:
在我的例子中,存储库中有两个文件,即LICENSE和README.md。
安装
让我们设置并激活开发环境(我使用的是Ubuntu 16.04)。我将使用virtualenv:
您每次在新终端开始项目工作时,都需要激活环境。
我将使用pip3来安装所需的软件包:
我安装的Django版本是2.2.4。
启动Django项目
我将在backend目录中设置Django项目。Django项目名被设置为server。
您可以使用以下命令来启动您的初始化的服务器:
当您在您喜欢的web浏览器中输入127.0.0.1:8000时,您应该会看到默认的Django欢迎站点(2)。
图2:Django默认欢迎站点
恭喜您! ! !您已经成功地设置了环境。
>>> 今日签到口令:vb7o <<<
将源文件添加到存储库中
在进入下一章之前,让我们先提交新文件。
以下文件应该会被添加到您的项目中:
在您的目录中,还有其他文件没有被添加到存储库中,因为.gitignore文件中排除了这些文件。
构建ML算法
在这一章您将学到:
如何安装Jupyter notebook,
如何构建两个ML算法,
保存预处理细节和算法。
安装Jupyter notebook
为了构建ML算法,我使用了Jupyter notebook。您可以轻松安装它:
要设置Jupyter notebook使用本地virtualenv环境,您可以运行运行:
我将创建一个research目录用于存放Jupiter文件。要启动Jupyter notebook ,请运行:
启动一个新notebook时,请确保您选择了正确的内核,在我们的示例中是venv(图3)。
图 3: 启动新的jupyter notebook
训练ML 算法
在构建ML算法之前,我们需要安装所需包:
numpy和pandas包用于数据操作。joblib用于ML对象的保存。然而,sklearn包提供了广泛的ML算法。在安装这些包之后,我们需要重新加载Jupyter。
我们代码的第一步是加载包:
加载数据
在本教程中,我将使用Adult Income数据集。在这个数据集中,ML将被用来根据人口普查数据预测收入是否超过每年5万美元。我将从我的公共存储库中加载数据,这些数据集适用于ML入门。
加载数据并显示第一行数据的代码(图4):
图4:我们数据集的第一行
X矩阵有32,561行14列。这是我们算法的输入数据,每一行描述一个人。y向量有32,561个值,表示年收入是否超过5万每年。
在开始数据预处理之前,我们将把数据分成训练和测试子集。我们将使用30%的数据进行测试。
数据预处理
在我们的数据集中,有缺失的值和分类列。对于ML算法训练,我将使用sklearn包中的随机森林(Random Forest)算法。在当前的实现中,它不能处理缺失值和分类列,这就是为什么我们需要应用预处理算法。
为了填充缺失的值,我们将在每一列中使用最频繁的值(当然还有许多其他的填充方法,我选择的只是作为示例)。
train_mode值看起来像这样:
从train_mode中您可以看到,例如在age列中最常见的值是31.0。
让我们把范畴转换成数字。我将使用来自sklearn包的LabelEncoder:
算法训练
数据已经准备好了,所以我们就可以训练我们的随机森林算法。
我们还将训练极端随机树(Extra Tree)算法:
正如您所看到的,训练算法很简单,只需两行代码—比数据读取和预处理要少得多。现在,让我们保存我们创建的算法。需要注意的重要一点是,ML算法不仅是rf和et变量(带有模型权值),而且我们还需要保存预处理变量train_mode和encoders。为了保存,我将使用joblib包。
将ML代码和部件添加到存储库中
在继续下一章之前,让我们将我们的notebook和文件添加到存储库中。
每个带有预处理对象和算法的文件都小于100 MB,这是GitHub的文件限制。对于较大的文件,最好使用单独的版本控制系统,如DVC——然而,这是一个更高级的主题。
Django模型
您已经实现了什么:
您已经初始化了默认的Django项目,
您已经训练了两个ML算法并准备好进行推理。
您将在这一章学到什么:
构建Django模型来在数据库中存储关于ML算法和请求的信息,
使用Django REST框架为ML算法编写REST API。
创建Django 模型
为了创建Django模型,我们需要创建一个新的应用程序:
使用上述命令,我们创建了endpoints应用程序并将其移动到apps目录。我已经添加了apps目录来保持项目的整洁。
让我们进入apps/endpoints/models.py文件并定义数据库模型(Django提供对象关系映射层(ORM))。
我们定义了三个模型:
Endpoint——保存关于端点的信息,
MLAlgorithm——保存服务中使用的ML算法的信息,
MLAlgorithmStatus——保存关于ML算法状态的信息。状态可以随时间变化,例如,我们可以将测试设置为初始状态,然后在测试期间切换到生产状态。
MLRequest——保存所有到ML算法的请求的信息。监控ML算法和运行A/B测试需要用到它。
我们需要将我们的应用程序添加到backend/server/server/settings.py中的INSTALLED_APPS,它应该是这样的:
要将我们的模型应用到数据库,我们需要运行迁移:
上面的命令将在数据库中创建表。默认情况下,Django使用SQLite作为数据库。对于本教程,我们可以保留这个简单的数据库,对于更高级的项目,您可以将Postgres或MySQL设置为数据库(您可以通过在backend/server/server/settings.py中设置DATABASES变量来配置这一点)。
为模型创建REST API
到目前为止,我们已经定义了数据库模型,但是在运行web服务器时我们不会看到任何新内容。我们需要为我们的对象指定REST API。实现此目的的最简单和最干净的方法是使用Django REST框架(DRF)。要安装DRF,我们需要运行:
并将其添加到backend/server/server/settings.py中的INSTALLED_APPS:
要在浏览器中看到一些东西,我们需要定义:
序列化器——它们将定义数据库对象如何在请求中进行映射,
视图——我们的模型如何在REST API中被访问,
url——为我们的模型定义REST API URL地址。
DRF序列化器
请将serializers.py文件添加到server/apps/endpoints目录:
序列化器将有助于将数据库对象打包和解包成JSON对象。在Endpoints和MLAlgorithm序列化器中,我们定义了所有只读字段。这是因为,我们将只在服务器端创建和修改对象。对于MLAlgorithmStatus,字段 status、 created_by、 created_at 和 parent_mlalgorithm处于读写模式,我们将使用它们通过REST API来设置算法状态。对于MLRequest序列化器,有一个处于读写模式的feedback字段——我们需要它来向服务器提供关于预测的反馈。
MLAlgorithmSerializer比其他的更复杂。它有一个current_status字段,代表MLAlgorithmStatus的最新状态。
视图
要添加视图,请打开backend/server/endpoints/views.py文件并添加以下代码:
对于每个模型,我们都创建了一个视图,该视图允许检索单个对象或对象列表。我们将不允许通过REST API创建或修改Endpoints、 MLAlgorithms。处理新ML相关对象创建的代码将位于服务器端,我将在下一章中讨论它。
我们将允许通过REST API创建MLAlgorithmStatus对象。我们不允许编辑ML算法的状态,因为我们想要保留所有的状态历史。
我们允许编辑MLRequest对象,但是只有feedback字段(请查看序列化器定义)。
URL
最后一步是添加URL来访问我们的模型。请在backend/server/apps/endpoints中的urls.py文件中添加以下代码:
上面的代码将创建到我们数据库模型的REST API路由器。我们的模型将按照以下URL模式被访问:
您可能注意到,我们在API地址中包含了v1。这可能在以后的API版本控制中会需要。
我们需要将端点url添加到服务器的主urls.py文件(文件backend/server/server/urls.py):
运行服务器
我们添加了很多新东西,让我们检查一下它们是否都可以运行。
请运行服务器:
并在web浏览器中打开http://127.0.0.1:8000/api/v1/。您应该会看到DRF视图(图5)。
图5:默认的Django REST框架视图
DRF提供了很好的接口,因此您可以单击任何URL并检查其对象(例如在http://127.0.0.1:8000/api/v1/endpoints上)。您应该会看到所有对象的空列表,因为我们还没有添加任何东西。我们将在下一章中添加ML算法和端点。
向存储库添加代码
本章的最后一步是向存储库添加新代码。
将ML算法添加到服务器代码中
到目前为止,您已经完成了:
训练两个ML算法,
使用数据库模型和REST API端点创建了Django服务器,这些端点将表示ML端点、模型和请求。
您将在这一章学到什么:
在服务器中创建ML代码,
写ML算法注册表,
向服务器添加ML算法。
服务器中的ML代码
在第3章中,我们创建了两个ML算法(随机森林和极端随机树)。它们是在Jupyter notebook中实现的。现在,我们将在服务器端编写使用以前训练过的算法的代码。在本章中,我们将只在服务器端包含随机森林算法(为了简单起见)。
我们来在 backend/server/apps目录中创建新目录ml来保存所有ML相关的代码,和income_classifier目录来保存我们的输入分类器。
让我们在income_classifier目录中添加新文件random_forest.py和空文件 __init__.py。
我们将在random_forest.py文件中实现ML算法。
RandomForestClassifier算法有五个方法:
__init__ -加载预处理对象和随机森林对象的构造函数(使用Jupyter notebook创建),
preprocessing - 该方法接受输入的JSON数据,将其转换为Pandas DataFrame并对其应用预处理,
predict - 该方法会调用ML对准备的数据进行计算预测,
postprocessing - 该方法会对预测值应用后处理,
compute_prediction - 该方法结合了 preprocessing、 predict 和 postprocessing,并返回带有响应的 JSON 对象。
要在Django中启用我们的代码,我们需要将ml应用程序添加到backend/server/server/settings.py中的INSTALLED_APPS:
ML代码测试
让我们编写一个测试用例来检查我们的随机森林算法是否按预期工作。为了进行测试,我将使用来自训练数据中的一行,并检查预测是否正确。
请使用以下代码将空的__init__.py和tests.py两个文件添加到ml目录中:
以上测试是:
构造一个输入JSON数据对象,
初始化ML算法,
计算ML预测并检查预测结果。
要运行Django测试,请运行以下命令:
您应该看到1个测试运行了。
算法注册表
我们已经准备好并测试了ML代码。我们需要将它与服务器代码连接起来。为此,我将创建ML 注册表对象,它将保存有关可用算法和相应端点的信息。
让我们在backend/server/apps/ml/目录中添加registry.py文件。
该注册表通过一个算法id到算法对象映射来保存简单的dict对象。
要检查代码是否按预期工作,我们可以在backend/server/apps/ml/tests.py文件中添加测试用例:
这个简单的测试向注册表添加了一个ML算法。运行测试:
测试输出:
将ML算法添加到注册表
注册表代码已经准备好了,我们需要在服务器代码中指定一个位置,在服务器启动时将ML算法添加到注册表中。最好的地方是backend/server/server/wsgi.py文件。请在该文件中设置以下代码:
使用以下命令启动服务器后:
您可以在浏览器中检查端点和ML算法。在URL:http://127.0.0.1:8000/api/v1/endpoints,您可以检查端点(图6),而在http://127.0.0.1:8000/api/v1/mlalgorithms,您可以检查算法(图7)。
图6:服务中定义的端点列表
图7:服务中定义的ML算法列表
向存储库添加代码
我们需要向存储库提交新代码。
接下来是什么?
我们已经将ML算法存储在数据库中,我们可以使用REST API访问关于它的信息,但是如何进行预测呢?这将是下一章的主题。
进行预测
您已经学习了什么:
您已经在Jupyter notebook中创建了两个ML算法,
您已经创建了带有数据库模型和REST API的Django应用程序,
您已经将ML代码添加到服务器代码并创建了一个ML注册表。
您将在这一章学到什么:
您将添加一个视图来处理服务器中的请求并将其转发到ML代码,
您将向视图添加API URL,
您将为预测编写测试。
英文原文:https://www.deploymachinelearning.com/
译者:浣熊君( ・᷄৺・᷅ )