生命周期ML

在真正的ML实现中,学习本身需要四分之一的努力。 剩下的四分之三是通过痛苦和官僚主义进行的数据准备,这是一个复杂的部署,通常是在没有Internet访问,基础设施设置,测试和监视的情况下进行的。 数百页的文档,手动模式,模型版本冲突,开源和苛刻的企业-所有这些都等待着数据科学家的关注。 但是他对这种“无聊的”操作问题不感兴趣;他想开发一种算法,达到高质量,回馈并且不再记忆。

也许在某个地方可以更轻松,更简单,更快地使用一个按钮实现ML,但是我们没有看到这样的示例。 以上就是Front Tier在金融科技和电信领域的经验。 Sergey Vinogradov是高负载系统架构,大型存储和海量数据分析领域的专家,他在HighLoad ++上谈到了他。



模型生命周期


通常,我们主题领域的生命周期包括三个部分。 首先,任务来自业务 。 第二, 数据工程师和/或数据科学家准备数据 ,建立模型。 第三部分, 混乱开始了。 在最后两个中,发生了不同的有趣情况。



万事通


常见的第一种情况是数据科学家或数据工程师可以使用这些产品,因此他们对他说:“您做了所有这些,您敢打赌。”

人们拿起Jupyter笔记本或一捆笔记本,将它们视为部署工件,然后开始在某些服务器上快乐地进行复制。

一切似乎都很好,但并非总是如此。 稍后再告诉你原因。

无情剥削


第二个故事更为复杂,通常发生在剥削达到轻度疯狂状态的公司中。 数据科学家将其解决方案投入运营。 他们打开这个黑匣子,看到了可怕的东西:

  • 笔记本
  • 腌制的不同版本;
  • 脚本堆:尚不清楚在何时何地运行它们,在哪里保存它们生成的数据。

在这个难题中,利用遇到版本不兼容。 例如,一位数据科学家未指定该库的特定版本,并且该操作是最新的。 一段时间后,数据科学家求助于:

-您将scikit-learn设置为错误的版本,现在所有指标都消失了! 需要回滚到以前的版本。

这完全破坏了产品,剥削遭受了损失。

官僚主义


在带有绿色徽标的公司中,当数据科学家投入使用并带来模型时,通常他会收到一份800页的文档以作为回应:“按照此说明进行操作,否则您的产品将永远无法见效”。

悲伤的数据科学家离开,将一切扔到一半,然后退出-他对此并不感兴趣。

部署


假设数据科学家遍历了各个领域,最后一切都已部署完毕。 但是他将无法理解一切都可以正常工作。 以我的经验,在同样的幸运银行中,没有对数据科学产品的监控。

如果专家将其工作结果写入数据库中,那将是很好的。 过了一会儿,他会收到它们,然后看看里面发生了什么。 但这并不总是会发生。 当企业和数据科学家简单地认为一切都很好并且很好时,就会转化为失败的案例。

小额信贷机构


我们以某种方式为一个大型小额信贷组织开发了一个评分引擎。 他们没有让他们选择产品,只是从我们这里购买了一系列模型,然后安装并启动了它。 模型的测试结果令他们满意。 但是六个月后,他们又回来了:

-都不好 业务不下去,我们越来越差。 看起来这些模型非常出色,但是结果却越来越多,欺诈和违约越来越多,钱也越来越少。 我们为您支付了什么? 让我们做对。

同时,再次不提供对模型的访问。 此外,六个月前,原木被卸载了一个月。 我们对卸载进行了另外一个月的研究,得出的结论是,在某个时候,MFI的IT部门更改了输入数据,并且开始使用xml发送文档,而不是json中的文档。 该模型期望使用json,但收到xml,却很难过,并认为输入中没有数据。

如果没有数据,那么对正在发生的事情的评估就不同了。 没有监视,就无法检测到。

新版本,级联和测试


我们经常会遇到该模型运行良好的事实,但是由于某种原因, 已经开发了一个新版本 。 再次需要以某种方式引入模型,并再次穿越地狱的各个角落。 如果库版本与以前的模型相同,则很好,如果不相同,则重新开始部署...

有时,在将一个新版本投入使用之前,我们想对其进行测试 -将其放在产品上,查看相同的流量,确保其质量良好。 这又是完整的部署链。 此外,我们对系统进行了设置,以便根据此模型,就计分而言,不会出现实际结果,而只是监视和分析结果以进行进一步分析。

在某些情况下,会使用级联模型。 当以下模型的结果取决于先前的模型时,您需要以某种方式在它们之间建立交互,然后再次保存所有这些。

如何解决此类问题?


通常,一个人可以手动解决问题,尤其是在小型公司中。 他知道一切工作原理,牢记模型和库的所有版本,知道在何处使用哪些脚本以及在哪些店面中工作。 这真是太好了。 手动模式留下的故事特别美丽。

继承的故事 。 一个好男人在一家小银行里工作。 有一次他去了一个南方国家,并没有返回。 之后,我们得到了继承:一堆代码,这些代码生成模型模型可以使用的店面。 代码很漂亮,可以正常工作,但是我们不知道生成该店面或该店面的脚本的确切版本。 在战斗中,所有商店橱窗都出现了,并且所有橱窗都被启动了。 我们花了两个月的时间来尝试弄清这种复杂的纠结并以某种方式进行构造。

在一个苛刻的企业中,人们不想打扰各种Python,木星等。他们说:

-让我们购买IBM SPSS,进行安装,一切都会很棒。 版本控制,数据源和部署方面的问题以某种方式得以解决。

这种方法有权存在,但并非所有人都能负担得起。 无论如何,这是一种高质量的锯齿状针。 他们坐在上面,但无法下车-缺口。 而且通常花费很多。

开源与以前的方法相反。 开发人员在Internet上冲浪,找到了许多可以不同程度解决其任务的开源解决方案。 这是一个很好的方法,但是对于我们自己,我们没有找到可以100%满足我们要求的解决方案。

因此,我们选择了经典的选择- 我们的决定 。 它的拐杖,脚踏车,全都是自己的本地人。

我们要从决定中得到什么?



不要自己写所有东西 。 我们希望采用已经证明自己并熟悉我们与之合作的机构中的运作的组件,尤其是基础结构组件。 我们只是编写了一个环境,该环境可以轻松地将数据科学家的工作与DevOps的工作隔离开。

以两种模式处理数据:批处理模式-批处理和实时 。 我们的任务包括两种操作模式。

易于部署,并且在封闭的范围内 。 使用敏感的私有数据时,没有Internet连接。 此时,所有内容都应快速准确地投入生产。 因此,我们开始关注Gitlab,其中的CI / CD管道和Docker。

模型本身并不是目的。 我们不解决建立模型的问题,我们解决业务问题。

在管道内部,必须有规则和模型集合,并支持对所有管道组件进行版本控制

管道是什么意思? 在俄罗斯,有关打击洗钱和资助恐怖主义行为的联邦第115号法律生效。 仅中央银行建议的目录占据16个屏幕。 这些是银行拥有这些数据即可满足的简单规则,如果没有数据则无法满足。

对借款人,金融交易或其他业务流程的评估是我们处理的数据流。 流必须遵循这种规则。 分析人员可以轻松地描述这些规则。 他不是数据科学家,但是他非常了解法律或其他说明。 分析人员坐下,用一种清晰的语言描述数据检查。

建立模型级联 。 当下一个模型将先前模型中获得的值用于其工作时,通常会出现这种情况。

快速检验假设。 我重复上一篇论文:数据科学家建立了某种模型,它在战斗中旋转并运行良好。 由于某种原因,专家提出了一个更好的解决方案,但不想破坏已建立的工作流程。 数据科学家在战斗系统中的相同战斗流量上悬挂了新模型。 她不直接参与决策,但流量相同,会考虑一些结论,这些结论存储在某个地方。

易于重用的功能。 许多任务具有相同类型的组件,尤其是那些与特征或规则提取有关的组件。 我们希望将这些组件拖到其他管道中。

您决定做什么?


首先,我们要监视。 还有两种。

监控方式


技术监控。 如果部署了任何管道组件,则在操作中它们应该查看该组件发生了什么:它如何消耗内存,CPU,磁盘。

业务监控。 这是一个数据科学家工具,可让您从实现的技术细微之处中抽象出来。 在设计级别,构造有助于确定哪些模型指标可用于监视,例如要素分布或评分服务结果。

数据科学家可以定义指标,而不必担心它们如何进入监控系统。 唯一重要的是,他定义了这些指标以及将在其上显示指标的仪表板的外观。 然后,专家启动了生产中的所有内容,进行了部署,不久之后,指标就进入了监控。 因此,无法访问产品的数据科学家可以查看模型内部发生的情况。

测试中


测试管道的一致性 。 给定管道的细节,这是一种计算图。 我们想了解我们正在实现一个图,我们可以绕过它并找到解决方法。

该图具有组件-模块。 所有模块都必须通过单元和集成测试。 对于数据科学家来说,该过程应该透明且容易。

开发人员可以自行描述模型并进行测试,也可以在他人的帮助下进行测试。 将所有内容放入Gitlab中,由Continuous Integration配置的管道引发,测试并查看结果。 如果一切都很好-它会继续前进,否则-它会重新开始。

数据科学家专注于模型,但不知道底层是什么。 为此,他得到了几样东西。

  • 通过数据总线-消息总线与系统本身 的核心集成的API 。 在这种情况下,专家需要描述模型的内容,管道的入口点以及与不同组件的交汇处。
  • 训练模型后,将出现一个工件-XGBoostpickle 文件 。 数据科学家有一个处理工件的执行器-他必须将管道组件集成到内部。
  • 简单,透明的API,供数据科学家监视管道组件的运行-技术和业务监视。
  • 一个简单透明的基础架构,用于与数据源集成并保存工作结果。

模型通常对我们有用,一段时间后,审计人员希望提高服务的整个历史记录。 审核希望检查工作的正确性,即我们是否存在欺诈行为。 需要简单的工具,以便任何了解SQL的审核员都可以进入特殊的存储库,并查看一切工作原理,做出的决定以及原因。

我们为我们建立了两个重要的故事奠定了基础。

客户旅程。 这是使用保留整个客户历史记录的机制的机会-作为该系统上实现的业务流程的一部分,客户发生了什么。

我们可能有外部数据源,例如DMP平台。 从他们那里,我们获得有关网络和移动设备上人类行为的信息。 这可能会影响他的模型的LTV和评分模型。 如果借款人拖欠付款,我们可以预测这不是恶意的,只是存在问题。 在这种情况下,我们对借款人采用软性敞口方法。 解决问题后,客户将结清贷款。 当他下次来时,我们将了解他的整个故事。 数据科学家将从模型中获得可视化历史记录,并在光照模式下进行评分。

识别异常 。 我们一直面临着一个非常复杂的世界。 例如,对小额信贷机构的加速评估中的弱点可能是自动欺诈的根源。

“客户旅程”是一种快速便捷地访问模型中数据流的概念。 该模型可以在大规模发生时轻松检测出具有欺诈特征的异常。

一切安排如何?


我们毫不犹豫地将Kafka作为Message Bus补丁。 这是一个很好的解决方案,我们的许多客户都在使用该解决方案,该操作可以使用它。



公司本身可能已经使用了某些系统组件。 我们不会再次构建系统,而是重用他们已经拥有的系统。

在这种情况下, 数据存储是客户端通常已经拥有的存储。 它可以是Hadoop,关系数据库和非关系数据库。 我们可以直接使用HDFS,Hive,Impala,Greenplum和PostgreSQL开箱即用。 我们将这些存储视为商店橱窗的来源。

数据到达仓库,通过我们的ETL或客户的ETL(如果有的话)传递。 我们正在构建用于模型内部的商店橱窗。 数据存储以只读模式使用。

我们的发展


黑板 这个名字来自30到40年代数学家的一种相当奇怪的实践。 这是居住在管理系统中的管道经理。 黑板上有某种元存储。 它存储管道本身以及初始化所有组件所需的配置。

所有系统工作都始于Blackboard。 奇迹般地,管道最终进入了Meta Storage,Blackboard在了解了一段时间后,拔出了管道的当前版本,对其进行了初始化并在Kafka内部发送了信号。

有一个运行时环境 。 它基于Docker构建,可以复制到服务器,包括客户的私有云中。

开箱即用的是主要Actor :: Init-这是初始化程序。 这个精灵只能做两件事: 建立销毁元件 。 他从Blackboard收到一条命令:“这里是管道,需要在具有如此大量资源的此类服务器上启动它!” 然后演员开始一切。

从数学上讲,actor是一种功能,它将一个或多个对象作为输入,使用内部算法更改对象的状态,在输出处生成新对象,或更改现有对象的状态。

从技术上讲,参与者是Python程序。 在具有其环境的Docker容器中运行。

演员不知道其他演员的存在。 唯一知道除了actor之外还存在整个管道的实体-这就是Blackboard。 它监视系统内所有参与者的执行状态并保持当前状态,该状态在监视中表示为整个业务流程的整体。

Actor :: Init产生许多Docker容器。 此外,参与者可以使用数据存储。

系统本身具有事件存储组件。 作为事件存储,我们使用ClickHouse 。 它的任务很简单:演员之间通过Kafka交换的所有信息都存储在ClickHouse中。 这样做是为了进一步审核 。 这是管道操作日志。

也可以为客户旅程开发演员。 他们可以看到管道日志中的更改,并且可以即时重建管道中已经存在的模型或组件使用规则所需的窗口。 这是一个不断变化的数据过程。

监视最初是基于Prometheus建立的 。 该actor具有基本的API,并且处于封闭模式,但对开发人员而言足够透明,他将带有指标的消息发送给Kafka。 Prometheus从Kafka读取指标并将其保存在其存储库中。

为了可视化,我们使用Grafana

两点整合


首先是与通过ETL到达数据仓库的数据源集成的重点。 数据使用者已经使用服务(例如计分服务)时的第二个集成点。

我们采用了Apache ServiceMix。 根据经验,这些集成点具有相同的类型和相同的协议类型:SOAP,RESTful,队列较少。 每次我们不想开发自己的构造函数或服务来生成下一个SOAP服务时。 因此,我们采用ServiceMix,在SDL中对其进行描述,在其中构造该服务的数据模型和其中存在的方法。 然后我们推入ServiceMix内部的路由器,它会自己生成服务。

从我们自己身上,我们添加了一个棘手的同步-异步转换。 系统内部的所有请求都是异步的,并通过消息总线。

大多数计分服务都是同步的。 ServiceMix请求通过REST或SOAP发出。 此时,他通过我们的网关,该网关保留了HTTP会话的知识。 然后,他向Kafka发送一条消息,该消息通过某些管道运行,并生成了一个解决方案。

但是,可能仍然没有解决方案。 例如,有些事情掉了下来,或者是很难做出决定的SLA,Gateway监视:“好吧,我收到了一个请求,他是另一个Kafka主题的人,或者我什么也没想到,但是我的超时触发器起作用了。” 再一次,将同步转换为异步,并且在同一个HTTP会话中,对使用者的响应是工作的结果。 这可能是错误或正常的预测。

顺便说一下,在这里,由于强大而强大的开放源代码,我们吃了一只无味的狗。 我们使用了最新版本之一的ServiceMix,使用了先前版本的Kafka,一切正常。 我们基于ServiceMix中已存在的多维数据集在此网关中编写了代码。 当新版本的Kafka发行时,我们很高兴地抓住了它,但事实证明,对Kafka消息中以前存在的标题的支持已经改变。 ServiceMix中的网关无法再使用它们。 为了理解这一点,我们花了很多时间。 结果,我们构建了可以与新版本的Kafka一起使用的Gateway。 我们将这个问题写给ServiceMix开发人员,并得到了答案:“谢谢您,我们一定会在下一版本中为您提供帮助!”

因此,我们被迫监视更新并定期更改某些内容。

基础设施就是Gitlab。 我们几乎使用其中的所有内容。

  • 代码库。
  • 继续集成/继续交付管道。
  • 用于维护Docker容器注册表的注册表。

组成部分


我们开发了5个组件:

  • 黑板 -管道生命周期管理。 从管道在何处,什么以及使用什么参数运行。
  • 特征提取器的工作原理很简单-我们通知特征提取器,我们在输入中获得了这样的数据模型,从数据中选择了必要的字段,并将它们映射为某些值。 例如,我们获取客户的出生日期,将其转换为年龄,并将其用作模型中的功能。 特征提取器负责数据丰富。
  • 基于规则的引擎 -根据规则检查数据。 这是一种简单的描述语言,允许熟悉<code>构造的人使用,否则<code />块来描述系统内检查的规则。
  • 机器学习引擎 -允许您运行执行程序,初始化经过训练的模型并将其提交给输入数据。 在输出中,模型获取数据。
  • 决策引擎 -决策引擎,从图表退出。 有了一系列的模型,例如借款人评估的不同分支,您必须决定某个地方的货币问题。 解决方案的规则集应该很简单。 , LTV- — , , .



. — , . — , .

pipeline .

  • Feature extractor : , , .
  • . , -: , , 18.
  • . , . , , pipeline.
  • Decision engine . .
  • .

yaml. . , , . yaml.

pipeline, , : feature extractor, rules, models, decision engine, . — Docker- . Registry, Docker-. -, , . , , Docker- .

流水线


, Python — . Feature extractor, , decision engine Python.

Pipeline yaml. meta storage — .

Runtime environment 10 , Blackboard , pipeline 10 . , : , , IP- Kafka, , . .

GitLab. Ansible. , . , 50 000 Ansible .

?


GitLab pipeline. GitLab. CI , , , . GitLab Runner , Docker- , pipeline. — Registry.



Docker , . Docker- . CI pipeline pipeline - Meta Storage, Blackboard.

Blackboard Meta Storage — , , , -. Docker- , , .

- Blackboard Meta Storage : , Kafka, . , , Docker- , .

, Docker-, — pipeline !

DigitalOcean. AWS Scaleway, .

, . pipeline . , .

?


— . , pipeline, real-time .

  • 2 Feature extractor . 1 , .. json .
  • 8 — 8 ML engine. XGBoost.
  • 18 RB engine (115 ). 1000 .
  • 1 decision engine.

200 . 2 Feature extractor, 8 , 18 1 decision engine 1,2 .


Discovery . , - . , , . . Meta Storage.

pipeline . , BPM . yaml , , .

. Java, Scala, R. Python, , . API , pipeline .

结果如何?


— . — . , . , . — 2018 .

, . — , , .

, . , , notebook , .

, - , , . , , UseData Conf . , , , 16 .

Source: https://habr.com/ru/post/zh-CN455648/


All Articles