写点什么

容器化的数据科学与工程——第二部分:容器化的数据科学

  • 2016-05-29
  • 本文字数:3626 字

    阅读完需:约 12 分钟

(这是有关容器化世界里的数据科学与工程系列博客文章的第二部分,点看第一部分)。

首先要承认,数据科学家正在设计一些非常有意思(而且或许很有价值的)的模型、优化以及虚拟化等。不幸的是,由于很多模型不能被产业化,它们将永远也不会被使用。事实上,很多工业界正在发生的“数据科学”也同步而孤立的发生在数据科学家的笔记本上。而且,在数据科学的应用被实际部署的场景中,它们经常被部署为 python/R 脚本,上传到 AWS 并作为一个 cron 任务来运行。

正如下面所言,这是数据科学用于工业界的一个非常大的问题和障碍:

“只有一个问题——我所有的工作都是在本地机器的 R 中完成的。人们欣赏我的努力,但是由于它没有被“产品化”且框架不能和本地模型通信,他们不知道如何使用我的模型。非常大的教训!”—— Twitter 的数据科学家 Robert Chang
“数据工程师经常抱怨:数据科学家缩写的代码效率低、风格差;他们很少考虑想法产品化后的维护代价;他们经常要求一些努力很多、受益很小的不切现实的特性。类似的抱怨还有很多,但你已经知道要点在哪了。”——数据平台 Stitchfix 的经理 Jeff Magnusson

但是,请不要担心!有一个更好的方法:容器化你的数据科学应用,以方便部署、可移植以及框架内的集成

数据科学家应该关心 Docker 的原因

该问题的简单回答就是:数据科学家想让他们的模型、仪表盘、优化等等被实际使用。为了让数据科学的应用被使用并带来价值,它们需要走出笔记本电脑,并被实际部署。它们还需要能够与现有的架构兼容,并易于升级和迭代。

一个 Docker 化的数据科学应用是如何提供以下好处的呢?

  • _ 无论应用如何部署、部署在何处,你无需担心依赖问题。_ 部署数据科学的应用的一个难点就是,搞清楚机器上复杂的依赖关系(numpy、scipy、pandas、scikit-learn 和 statsmodels 等)。通过将这些应用容器化,你可以在不管依赖关系、部署机器上的操作系统类型以及现有包 / 库版本的情况下,利用一行命令轻易完成部署。
  • _ 随着公司框架的扩展或你需要扩展你的应用,你可以轻易移植或创建更多实例。_ 大家经常会在没有全面考虑服务最终部署位置、服务能力的实际需求等问题的情况下开发一个模型或应用。但是,当你将数据科学的应用容器化以后,你可以轻易的根据需求将它从 AWS 移植到 Azure。或者,你可以根据负载情况,创建更多的应用实例。
  • _ 你,作为一个数据科学家,可以保持公司的现代化架构。_ 替代在与 4 个不同的数据库直接交互的机器上的 cron 任务,容器化的数据应用可以利用 JSON API 和消息队列来与框架的其他部分进行交互。而且更让工程师觉得开心的是,当架构改变或升级时,应用也可以正常工作。你还可以将数据科学的工作和其他工程团队的 CI/CD 流水线集成在一起。(观众中的数据科学家不要担心:这并不难,而且我们会在下面给出一个例子)。

容器化数据科学应用的一个简单例子

接下来,让我们从一个 python 脚本开始了解容器化的数据科学应用。接下来,我会给出容器化数据科学应用的一个简单例子:

  1. 利用绝大部分数据科学家熟悉的技术( python scikit-learn ).
  2. 被容器化(也就是说,可以被编译为一个 Docker 镜像)。
  3. 通过 JSON API 与 Docker 容器以外的组件进行交互。

一个做预测的简单模型

这里,我们将利用著名的 Iris 数据集来构架一个 k-NN 分类模型(带 scikit-learn ):

复制代码
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
def predict(inputFeatures):
iris = datasets.load_iris()
knn = KNeighborsClassifier()
knn.fit(iris.data, iris.target)
predictInt = knn.predict(inputFeatures)
if predictInt[0] == 0:
predictString = 'setosa'
elif predictInt[0] == 1:
predictString = 'versicolor'
elif predictInt[0] == 2:
predictString = 'virginica'
else:
predictString = 'null'
return predictString

该预测函数将基于输入特征``inputFeatures`(sepal length、sepal width、petal length 和 petal width)返回一种 Iris。在本例中,用于训练模型的数据集是静态的(也就是说,从 scikit-learn 数据集中加载)。然而,你可以很轻易的想到如何从一个数据集或利用消息、API 和数据库交互所聚合的值中动态加载。

传递预测的 JSON API

接下来,我们需要将这些预测传递到其他组件。为此,我将开发自己作为简单 JSON API 的应用。对于很多使用微服务架构的工程团队而言,这种应用只是一种普通的练习。而且它可以使得数据应用与其他现存的服务更好的协同工作。

这里,我们将在 API 中使用flashk-restful,你可以使用 twisted 或其他任何架构:

复制代码
from flask import Flask
from flask_restful import Resource, Api
from flask_restful import reqparse
from utils import makeprediction
app = Flask(__name__)
api = Api(app)
class Prediction(Resource):
def get(self):
parser = reqparse.RequestParser()
parser.add_argument('slength', type=float,
help='slength cannot be converted')
parser.add_argument('swidth', type=float,
help='swidth cannot be converted')
parser.add_argument('plength', type=float,
help='plength cannot be converted')
parser.add_argument('pwidth', type=float,
help='pwidth cannot be converted')
args = parser.parse_args()
prediction = makeprediction.predict([
args['slength'],
args['swidth'],
args['plength'],
args['pwidth']
])
print "THE PREDICTION IS: " + str(prediction)
return {
'slength': args['slength'],
'swidth': args['swidth'],
'plength': args['plength'],
'pwidth': args['pwidth'],
'species': prediction
}
api.add_resource(Prediction, '/prediction')
if __name__ == '__main__':
app.run(debug=False)

那么,我就得到了一个GET端点,使得我们可以利用其来获得针对一个特征集的预测。例如,路径

http://<host>:5000/prediction?slength=1.5&swidth=0.7&plength=1.3&pwidth=0.3将返回:

复制代码
{
"pwidth": 0.3,
"plength": 1.3,
"slength": 1.5,
"species": "setosa",
"swidth": 0.7
}

其中,在响应 JSON 中的species表示基于输入特征预测的种类。

构建 Docker 镜像的 Dockerfile

为了构建一个我们数据科学应用的“Docker 镜像”,我们西药一个Dockerfile。该Dockerfile将呆在 repo 的 root 中,并包含 Docker 镜像中的所有必须的文件和依赖关系。当我们运行 Docker 镜像时,运行我们所选择的一个命令:

复制代码
FROM ubuntu:12.04
# get up pip, vim, etc.
RUN apt-get -y update --fix-missing
RUN apt-get install -y python-pip python-dev libev4 libev-dev gcc libxslt-dev libxml2-dev libffi-dev vim curl
RUN pip install --upgrade pip
# get numpy, scipy, scikit-learn and flask
RUN apt-get install -y python-numpy python-scipy
RUN pip install scikit-learn
RUN pip install flask-restful
# add our project
ADD . /
# expose the port for the API
EXPOSE 5000
# run the API
CMD [ "python", "/api.py" ]

准备完毕,开始部署应用

以上就是构建第一个容器化的数据科学应用所需要的所有步骤(对于 Docker 的安装指令,参看 Docker 网站)。现在,让我们构建应用的“Docker 镜像”:

docker build --force-rm=true -t pythoniris

该命令将构建一个名为pythoniris的 Docker 镜像。我们可以根据需要标记该镜像(例如,pythoniris:latest),或将其和 Docker Hub 上的用户 / 账号(例如,dwhitena/pythoniris)关联起来(Docker Hub 是一个专门存储 Docker 镜像的公开仓库,类似于 Docker 镜像的 Github)。

如果你将镜像上传到 Docker Hub(或一个私有仓库),部署就像运行引用 Docker Hub 或仓库中的用户名 / 镜像名的 Docker 镜像一样容易。然而,假设你想首先在本地进行这些尝试,你可以通过如下命令来运行 Docker 镜像:

复制代码
docker run --net host -d --name myiris pythoniris

该命令将运行 Docker 镜像运行为一个名为myiris的容器、一个守护进程(-d),并使用与本地主机相同的网络接口(--net host)。现在,你的 JOSN API 就可以通过localhost:5000端口进行访问了。

可以看的出来,从 python 脚本到容器化的数据应用只需要一点点的付出。现在,请继续向前——研究数据科学、容器化数据科学和部署你的数据科学吧。

以上代码可以在 Github 中下载。


感谢陈兴璐对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016-05-29 17:442382
用户头像

发布了 268 篇内容, 共 133.3 次阅读, 收获喜欢 24 次。

关注

评论

发布
暂无评论
发现更多内容

DevOps如何攻克研发流程六大痛点?

BoCloud博云

「古老」茶产业碰上「年轻」区块链,能否擦出新火花?

CECBC

坚持“一城市一矿山” 拾起卖争当循环产业领跑者

InfoQ 天津

Go 让 Apache APISIX 如虎添翼

API7.ai 技术团队

Apache 开源 插件 APISIX Go 语言

狂刷《Java权威面试指南(阿里版)》,冲击“金九银十”有望了

Java 程序员 架构 面试 大厂

租房市场是流动的么?

escray

生活记录 8月日更 搜房记 租房

排查指南 | 两个案例学会从埋点排查 iOS 离线包

蚂蚁集团移动开发平台 mPaaS

mPaaS

Apache APISIX 在 Airwallex 的应用 | 专访 Airwallex 技术平台负责人李杨

API7.ai 技术团队

Apache 开源 案例分享 api 网关 APISIX

netty系列之:netty中的懒人编码解码器

程序那些事

Java Netty nio 程序那些事

fil挖矿难度大不大?fil挖矿1T收益是多少?

fil挖矿难度大不大 fil挖矿1T收益是多少

千字真言,字字珠玑,我的Golang学习笔记,赤诚分享

奔着腾讯去

Go 语言

进化十多年,四足机器人的网红属性有改变吗?

脑极体

字节架构师离职后,熬夜整理55W字Java面试手册,逆风翻盘进阿里

Java 编程 程序员 架构 面试

如何利用 SEI 实现音画同步?

ZEGO即构

音视频 音画同步 数据流录制 flv

凭借一份“面试真经pdf”,我四面字节跳动,拿下1-2级offer

Java 程序员 面试 后端 计算机

腾讯「小借条」引发的思考:区块链+的商业模式让各企业争先恐后的奥秘

CECBC

Fil火爆的原因是什么?fil未来价格会多少钱一枚?

分布式存储 IPFS fil fil价格 fil行情

厉害!GitHub星标70K阿里大佬手写的Spring Boot实战手册真不错

Java 编程 程序员 架构 计算机

DevOps 调查第十年,如何借助工具实现落地?

飞算JavaAI开发助手

DevOps 基础软件 自动化平台

前端基础五之jQuery基础

ベ布小禅

8月日更

【六顶思考帽】学习心得

LeifChen

8月日更 六顶思考帽 创新思维

fil挖矿必看!fil挖矿步骤有哪些?fil挖矿的效率如何?

分布式存储 IPFS fil fil挖矿

基于一万小时定律去规划职业

非著名程序员

生涯规划 职场 职业规划 8月日更

Activiti数据库表结构

金陵老街

牛掰!“基础-中级-高级”Java程序员面试集结,看完献出我的膝盖

Java 编程 面试 IT 计算机

字节大牛的1850页Leetcode刷题笔记外泄!用实力折服众人

Java 程序员 字节跳动 面试 算法

markdown不支持代码块和表格,离开这里了

DBKernel

Go- 基本类型和运算符

HelloBug

Go 语言 布尔类型 基本类型和运算符 数字类型

替换及重置Homebrew默认源以及M1安装

一个大红包

8月日更

在华为P50 Pro中,听到AI异构通信的朱弦三叹

脑极体

腾讯、阿里纷纷看好的NFT,能否成为拯救区块链的良药?

CECBC

容器化的数据科学与工程——第二部分:容器化的数据科学_大数据_张天雷_InfoQ精选文章