在微服务架构中做机器学习,真的太难了
作者头像
  • AuToPros
  • 2020-05-29 18:13:56 2

我曾参与过许多由深度学习驱动的项目,其中最棘手的情况就是被迫处理面向微服务的架构。我并不是反对使用微服务,但在严格的微服务架构中推进机器学习项目,成功率往往会大大降低。

在这篇文章中,我将探讨为什么面向微服务的架构与机器学习并不匹配,并介绍一些大公司如Airbnb和Uber是如何解决这一问题的。

微服务已经成为许多技术公司的首选架构。它允许大型公司的多个团队构建小型、独立的组件,从而更快地解决问题和满足需求。然而,过度使用微服务也会带来一些问题。例如,一个简单的用户会话Token转换为用户配置文件的操作,可能会触发数十次网络调用。

我最近在Twitter上看到了一段视频,它很好地解释了这个问题:

(视频地址:https://youtu.be/y8OnoxKotPQ)

产品经理:为什么在个人资料页面显示生日日期如此困难?

工程师:首先,我们需要调用Bingo服务获取UserID,再调用Papaya服务将UserID转换为用户会话Token,然后进行验证,接着从Racoon服务中提取用户信息,但Racoon不一定包含用户的生日信息,因此我们需要继续调用更多的服务……

在复杂的数据源如用户行为上构建机器学习模型时,微服务架构会增加难度。为了做出一个预测,需要从众多微服务中获取信息,而这些微服务又依赖于其他服务来获取上下文信息。例如,为用户构建个性化的Reddit Feed可能需要了解用户所属的所有社区、这些社区中的热门帖子、用户点击和喜欢的所有帖子等信息。增加额外的输入可以为模型提供更多信号,例如用户在周末与工作日的行为差异。

在机器学习模型中,每个逻辑输入被称为一个特征。特征工程是指假设、构建和测试模型输入的过程,这是机器学习团队中最耗时的任务之一。创造性地提出新特征只是一部分工作,大部分时间花在寻找所需数据、学习其特殊性和边缘情况、建立数据管道等方面。

在基于微服务的架构中,收集特定数据的唯一方法是通过API调用。一个模型可能需要多次API调用才能获取所有特征。例如,为了了解用户所属的社区及其热门帖子,需要调用多个服务。由于没有专门为这种用途构建的系统,这将导致一系列网络调用的问题。

与Web前端不同,机器学习模型在缺少特征时无法灵活应对。它必须等待所有请求完成,否则可能导致大量无效结果。模型本身在计算上复杂且缓慢,与微服务混合在一起难以提供实时推荐。

获取训练数据的过程也存在问题。机器学习模型需要观察结果的数据集以及相应的输入来进行训练。在基于微服务架构中生成训练集的过程非常复杂。例如,在Reddit中,我们需要一组用户点赞的数据集及相应的特征集。

从技术上讲,可以通过抓取用户和帖子的微服务来获得用户点赞信息和所有帖子数据,但这远非理想方案。时点的准确性要求使得这个问题变得难以解决。为了训练模型,我们需要知道某个帖子在子版块中的排名,但子版块的微服务通常不支持追溯查询。

一种解决方案是打破封装,直接从数据库转储读取数据,绕过API调用,将数据集直接插入Apache Spark或其他批处理系统。虽然这种方法看似可行,但它会导致机器学习服务依赖原始数据,这种模式会随时间变化,许多微服务会被淘汰并替换,导致数据不一致和错误累积。

另一种选择是使用事件流平台如Apache Kafka、Apache Pulsar或Segment,让机器学习团队订阅所需事件流。事件流平台的优点在于其数据质量较高,因为事件流通常为关键任务服务提供动力,因此团队必须遵守更高的数据质量和文档编制标准。

事件流处理存在冷启动问题。事件流平台通常只保留几天的数据,这意味着生成新特征时可能只有最近一周的数据可用。创建新的有形状特征时,冷启动问题更为明显。有形状特征需要汇总一定时间范围内的所有事件,例如用户上周发布的帖子总数。在这种情况下,可能需要几周时间才能开始生成训练数据集。

特征工程是一个反复的过程。生成假设、建立实验并运行测试。可以将其合并到主要模型中,也可以放弃。迭代越快,模型改进越快。如果一次测试需要数周时间,机器学习团队将无法有效工作,大量的数据管道将被浪费。

许多公司独立发展出相同的解决方案,如Airbnb的Zipline、Uber的Michelangelo、Lyft的Dryft,这些系统统称为特征存储。

特征存储为数据科学家提供了一种标准化的方法来定义特征。特征存储负责生成训练数据并提供在线特征服务,将数据工程从机器学习工作流中抽象出来。在底层,它协调多个大数据系统以无缝处理传入和历史事件。如果对这种技术感兴趣,可以参考以下链接:

阅读地址:https://streamsql.io/blog/from-apache-kafka-to-apache-pulsar

在原始的“Reddit”微服务架构中,每个服务都有自己的数据。帖子微服务是关于帖子数据的真实来源,用户微服务是关于用户数据的真实来源,依此类推。特征存储试图在其内部的数据结构中创建这些数据的视图。它通过将领域事件流处理为物化视图来实现这一点。领域事件是逻辑事件,如用户点赞文章或创建新帖子。物化视图是对事件流查询的结果集。因此,如果希望模型知道用户点赞的帖子数量,可以使用以下逻辑创建一个物化视图:

sql SELECT user, COUNT(DISTINCT item) FROM upvote_stream GROUP BY user;

所有物化视图都存在于同一个特征存储中,并已为机器学习进行了预处理。我们已经将所有微服务数据合并到一个单一的数据存储中。这解决了从微服务获取实时特征的问题。现在,特征只需一次往返即可获取。由于物化视图存储在一个高可用且最终一致的数据存储中,特征存储还具备抗灾的优势。由于我们自己处理原始事件,因此在创建特征时可以控制自己的业务逻辑,从而轻松解耦到每个微服务中的业务逻辑。

通过事件溯源,我们可以为模型生成训练数据集。以Reddit为例,我们预测用户将点赞的下一篇文章。相关的领域事件将流式传输到特征存储中,该存储将更新模型输入特征。观察到的结果也应流式传输到特征存储,例如用户的每次点赞。

python feature_store.append_observation(userId, postId, now())

由于特征存储维护每个事件的日志并将事件流转换为有形状的逻辑,因此它可以随时获取特征形状。生成训练集时,它会遍历观察结果并在该点生成特征集。将两者结合后,我们最终得到一个训练数据集。

设计注意事项

特征存储使我们能够与微服务架构解耦并控制自己的特征。然而,构建和维护特征存储并非免费。团队在部署特征存储基础架构前应考虑以下几点。

全系统事件流

特征存储要求领域事件通过事件流平台(如Kafka或Pulsar)传递。这使得特征存储能够独立于微服务实现其功能。保留事件日志使其能够在任何时间点生成特征。

从大型基于微服务的系统转向事件流是一个重大转变,必须注入常规程序以捕获重要事件。这可能需要使用新的依赖项和条件来更新旧的关键微服务。另一种选择是使用每个数据库中的Change-Data-Capture语义将更新转换为流。但这样一来,特征存储容易受到微服务数据库架构更改的影响。

处理事件架构更改

特征存储仍然依赖于事件流架构。如果流的架构发生变化,或者微服务行为不当并上传垃圾数据,可能会导致下游特征存储出现问题。事件流模式应与数据库模式一样认真对待,迁移程序应明确并经过测试,事件应使用可扩展格式如Protobuf或JSON编写。

存储和计算能力

处理和存储大量数据不是免费的。在许多情况下,特征存储会重复执行微服务所做的计算。特征存储以基础设施成本和复杂性为代价,为开发人员带来速度和易用性。建立和维护特征存储需要资金投入和专业工程师。

记录和共享输入特征和数据源

机器学习特征通常适用于许多不同的用例。Reddit可能具有多种不同的特征,这些特征都通过用户活动做出决策。发现和了解他人构建的特征可以加快开发速度,并为特征工程提供灵感。由于特征存储是一个相对较新的架构,团队必须编写文档说明如何发布和共享特征。

选择合适的特征存储

合适的特征存储使机器学习团队专注于构建模型,而不是数据管道。团队可以在SQL中创建单个特征定义,有形状特征会自动回填以消除等待时间。

    本文来源:图灵汇
责任编辑: : AuToPros
声明:本文系图灵汇原创稿件,版权属图灵汇所有,未经授权不得转载,已经协议授权的媒体下载使用时须注明"稿件来源:图灵汇",违者将依法追究责任。
    分享
架构机器真的学习服务
    下一篇