谷歌机器学习法则:ML工程的最佳实践

2018年5月2日19:07:49 发表评论 405

Martin Zinkevich 在2016年将谷歌内容多年关于机器学习相关的经验分享了出来,这篇文章是对该分享的一些翻译+解读,如果想查看原文请参见:https://developers.google.com/machine-learning/rules-of-ml/ 。

术语

在说到具体的相关经验之前,先来了解下常用的术语。

  • 示例(Instance):那些你要为其做出预测的事物称为示例。例如,示例可能是一个网页,你要将其归为“关于猫的”网页或者“不是关于猫的”网页。
  • 标签(Label):预测任务的答案或结果称为标签。无论是机器学习系统的答案或结果,还是训练数据的答案或结果,都可以称为标签。例如,将网页标记为“关于猫的”。
  • 特征(Feature):预测任务中示例的属性即为“特征”。例如,网页可以有“包含词汇‘猫’”的特征。
  • 特征栏(Feature Column):特征栏是相关特征的集合,如用户所住地区存在的所有可能国籍的集合。在同一个样本的同一个特征栏中可能有一个或多个特征。特征栏相当于(雅虎或微软的)虚拟机系统的 “命名空间(namespace)”或“域(field)”。
  • 样本(Example):样本包含示例(具有各种特征)和一个标签。
  • 模型(Model):模型是预测任务的数学表达形式。先是通过样本训练模型,而后利用模型做出预测。
  • 指标(Metric):指标是指一系列的数字,这些数字直接或间接的都被优化过。
  • 目标(Objective):目标是指算法经过优化,努力要达到的度量标准。
  • 工作流(Pipeline):工作流指的是围绕机器学习算法而存在的基础架构。从前端搜集数据、将搜集到的数据放入训练数据文件夹、训练一个或多个模型以及将模型用于生产等过程,都属于工作流。
  • 点击率(Click-through Rate):用户浏览网页时对包含广告链接的点击次数占浏览次数的百分比。

概述

要想创造出优秀的产品:

你需要以一位优秀工程师的身份去运用深度学习!记住!你不单单是一位机器学习的研究者!

事实上,你所面临的大多数问题都是工程问题。即便拥有足以媲美机器学习专家的理论知识,要想有所突破,大多数情况下都在依赖示例的良好特征,而非优秀的机器学习算法。因此,基本方法如下:

  1. 确保你的工作流各连接端十分可靠
  2. 从树立合理的目标开始
  3. 用简单的方式,添加符合常识的特征
  4. 确保你的工作流始终可靠

这种方法能带来相当多的盈利,也能在较长时间里令许多人都满意,甚至还可能实现双赢。只有在简单技巧不发挥任何作用的情况下,才考虑使用复杂的一些的方法。方法越复杂,产品最终输出速度慢。

当所有的简单技巧用完后,很可能就要考虑最前沿机器学习术了。

本文档主要由四部分组成:

  1. 第一部分:帮助你明白是否到了需要构建一个机器学习系统

  2. 第二部分:部署你的第一个工作流

  3. 第三部分:往工作流增加新特征时的发布和迭代,以及如何评价模型和训练-服务倾斜(training-serving shew)

  4. 第四部分:达到稳定阶段后该继续做什么。

在机器学习之前

Rule #1:Don't be afraid to launch a product without machine learning.

法则 1:不要害怕发布一款没有用到机器学习的产品

机器学习是很酷,但它需要数据。如果你认为机器学习可以提高 100% 收益,那么启发式规则可以获得 50% 收益。

Rule #2: First, design and implement metrics.

法则2:首先需要设计和实现评估指标

在构建具体的机器学习系统之前,首先在当前系统中记录尽量详细的历史信息。原因如下:

  1. 在早期,更容易获得系统用户的权限许可(获得系统用户权限后,更容易收集各种数据)。
  2. 如果你觉得某个问题以后会受到关注,最好是从现状开始就搜集历史数据。
  3. 如果设计系统的时候考虑了评估指标,这对将来会大有益处。具体来说,这是为了让你以后不用在日志文件中寻找相关的字符串。
  4. 你能够注意到什么(随着时间)改变了,什么(随着时间)没有改变。举个例子,假设你想要直接优化一天的活跃用户量。然而在早期对系统的处理中可能会发现用户体验的变化并没有显著改变活跃用户量的度量。

Rule #3: Choose machine learning over a complex heuristic.

法则3:优先选择机器学习而不是复杂的启发式规则

简单的启发式方法可以轻松应用到产品上,而复杂的启发式方法却难以维护。一旦你拥有了足够的数据,并且对要实现的目标有了基本的概念,那就转向机器学习吧。在大多数软件工程中,不管使用的是启发方法还是机器学习模型,都需要经常更新算法。但是你会发现,使用机器学习的模型更容易更新和维护。

机器学习阶段 1:第一条工作流

构建第一个机器学习工作流时,一定要更多关注系统基础架构的建设。虽然机器学习的算法令人激动,但是因为基础架构不给力找不到问题时会令人抓狂。

Rule #4: Keep the first model simple and get the infrastructure right.

法则4:第一个模型要简单,但是基础架构要正确

第一个模型对你的产品提高最大,因此它不需要有多花哨。相反,你会碰到比你想象的多的基础架构方面的问题。在别人使用你的的新机器学习系统前,你需要确定:

  1. 如何为你的学习算法得到样本
  2. 为你的系统初步定义“好”与“坏”的标准
  3. 如何将模型集成到应用程序中。你可以直接将模型应用到在线应用程序中,也可以在离线样本的基础上对模型进行预计算(pre-compute),然后把与计算的结果储存在表格中。

选择简单的特征,这样会更容易确保:

  1. 特征正确应用到算法中
  2. 模型能够学习到合理的权重
  3. 特征正确应用到服务器模型(也就是生产环境的模型)中

你的系统如果能够可靠地遵守这三点,你就完成了大多数工作。你的简单模型能够提供基准指标和基准行为,你可以用来测量更加复杂的模型。

Rule #5: Test the infrastructure independently from the machine learning.

法则5:独立于机器学习来测试架构流程

不仅需要确保基础架构的可测试性,还需要确保系统的学习部分(learning part)是封装好的(encapsulated),这样才能测试所有与之相关的部件。具体来说:

  1. 测试输入到算法中的数据。检查应该填充的特征栏是否正确填充。
  2. 测试模型在训练算法之外的运行情况。确保模型的训练环境中和服务环境中的得分相同。

机器学习的一个特点就是不可预测性。因此,你必须确保在训练和实际运行中创造样本的代码能被测试,并且在实际运行中始终使用同一个固定的模型。

Rule #6: Be careful about dropped data when copying pipelines.

法则6:复制工作流时留意丢失的数据

我们有时候会通过复制已经存在的工作流来创建一个新的工作流。在新的工作流中需要的数据,很可能在旧的数据流就丢弃了。

Rule #7: Turn heuristics into features, or handle them externally.

法则 7: 将启发规则转化为特征,或者在外部处理它们

机器学习系统解决的问题通常都不是新问题,而是对已有问题的进一步优化。这意味着有很多已有的规则或者启发式规则可供使用。这部分信息应该被充分利用。下面是几种启发式规则可以被使用的方式:

  1. 用启发式规则进行预处理。 若特征相当完美,则可以采用这个方法。举个例子,在垃圾邮件过滤器中,如果发件人已经被加入黑名单了,则可以不用重新学习“黑名单”的概念。直接阻止该信息就可以!这种方法在二元分类(binary classification)任务中很有用。
  2. 创建特征。 直接从启发式规则中创建特征会很便捷。举个例子,若要用启发式规则为某个查询结果计算相关度,你可以把分数纳入特征的值中。接下来,用机器学习的方法来处理这些值(例如,把这些值转化为由一系列离散值组成的有限集,或者也可以与其它特征相结合),但是要从启发式方法生成的原始数据入手。
  3. 挖掘启发式方法的原始输入数据。 对于某款 app,若存在一个启发式方法,其包含安装量、文本字符数和当天日期等要素,可以考虑将这些原始信息单独作为特征使用。
  4. 修改标签。当你发觉启发式方法捕捉了一些信息,而这些信息没有包含在标记中,这时可以考虑该选项。举个例子,如果你想让下载量达到最大,但同时对内容的质量有要求,那么可以用 app 的平均评级乘以标记来解决问题。

监控

一般来说,所有系统都要设置良好的警示程序,警报系统需要顺利执行,或者设置一个仪表板页面(dashboard page)。

Rule #8: Know the freshness requirements of your system.

法则 8: 了解你系统对新鲜度的要求

如果你使用的是一天前的旧模型,运行状况会下降多少?如果是一周前的呢?或一个季度前的呢?知道何时该刷新系统能帮助你划分监控的优先级。如果你的模型一天没有更新,受益便下降 10%,因此有必要指派一名工程师时时关注它的动态。大多数广告服务系统每天都会有新的广告需要处理和更新。此外,要留意系统对新鲜度的要求会随着时间变化,特别是在添加或移除特征栏的时候,需要尤为注意。

Rule #9: Detect problems before exporting models.

法则 9: 输出(发布)模型前发现问题

许多机器学习系统都存在这样一个阶段:直接把模型输出运行。如果问题出现在模型输出之后,那么这个问题就是用户所面临的问题。而如果问题出现在模型输出之前,就是训练过程中的问题,用户不会发现。

输出模型之前请做好完整性检查(sanity check)。具体来讲,确保模型在留存数据上运行合理,例如AUC。

Rule #10: Watch for silent failures.

法则10:注意隐藏性故障

比起其它系统,机器学习系统更容易出现潜在的问题。假设系统的某个特定的表格不再进行更新,整个系统通过调整仍会保持良好的运行水准,但是会慢慢衰减。有时有些表格几个月都不会刷新一次,而只需简单的刷新就能大幅度提升系统的运行水准,效果甚至超过该季度最新发布的那些模型!例如,由于系统实现(implementation)发生变化,特征的覆盖范围也会发生相应的变化:比如,某个特征栏刚开始可能包含 90%的样本,接下来却可能突然下降到 60%。解决方法是是对关键数据的统计信息进行监控,并且周期性对关键数据进行人工检查。

Rule #11: Give feature columns owners and documentation

法则 11:为特征栏指定负责人并记录文档

如果系统的规模比较大,并且特征栏比较多,那么必须清楚每个特征栏的创建者或者维护者。如果某个了解该特征栏的人离开了,一定要确保另外还有人了解这部分信息。虽然很多特征栏的名字非常直观,但最好还是使用更详尽的文档来描述这些特征的内容、来自哪里以及它们的作用。

你的第一个目标(Objective)

objective 是模型试图优化的值,而 metric 指的是任何用来评估系统的值。

Rule #12: Don't overthink which objective you choose to directly optimize.

法则 12: 不要过于纠结该优化哪个目标

你有成千上万关心的指标,这些指标也值得你去测试。但是,在机器学习过程的早期,你会发现,即使你并没有直接去优化,他们也都会上升。比如,你关心点击次数,停留时间以及每日活跃用户数。如果仅优化了点击次数,通常也会看到停留时间增加了。

所以,当提高所有的指标都不难的时候,就没必要花心思来如何权衡不同的指标。不过过犹不及:不要混淆了你的目标和系统的整体健康度。

Rule #13: Choose a simple, observable and attributable metric for your first objective.

法则 13:选择一个简单、可观测并且可归类的评估指标(metric)作为你的第一个目标(objective)

有时候你自以为你清楚真实的目标,但随着你对数据的观察,对老系统和新的机器学习系统的分析,你会发现你又想要调整。而且,不同的团队成员对于真实目标并不能达成一致。机器学习的目标必须是能很容易测量的,并且一定是“真实”目标的代言。因此,在简单的机器学习目标上训练,并创建一个“决策层”,以允许你在上面增加额外的逻辑(这些逻辑,越简单越好)来形成最后的排序。

最容易建模的是那些可以直接观察并可归属到系统的某个动作的用户行为:

  1. 排序的链接被点击了吗?
  2. 排序的物品被下载了吗?
  3. 排序的物品被转发/回复/邮件订阅了吗?
  4. 排序的物品被评价了吗?
  5. 展示的物品是否被标注为垃圾/色情/暴力?

最开始要避免对间接效果建模:

  1. 用户第二天会来访吗?
  2. 用户访问时间是多长?
  3. 每日活跃用户是什么样的?

间接效果是非常重要的指标,在A/B test和发布决定的时候可以使用。

最后,不要试图让机器学习来回答以下问题:

  1. 用户使用你的产品是否开心
  2. 用户是否有满意的体验
  3. 产品是否提高了用户的整体幸福感
  4. 这些是否影响了公司的整体健康度

这些都很重要,但太难评估了。与其如此,不如考虑其他代替的:比如,用户如果高兴,那停留时间就应该更长。如果用户满意,他就会再次造访。

Rule #14: Starting with an interpretable model makes debugging easier.

法则 14:从容易解释的模型入手会让调试过程更加容易

线性回归,逻辑回归和泊松回归直接由概率模型激发。每个预测可解释为概率或期望值。这使得他们比那些使用目标来直接优化分类准确性和排序性能的模型要更容易调试。比如,如果训练时的概率和预测时的概率,或者生产系统上的查看到的概率有偏差,那说明存在某种问题。

Rule #15: Separate Spam Filtering and Quality Ranking in a Policy Layer.

法则 15:在策略层将垃圾信息过滤和质量排名分开

质量排名是一门艺术,而垃圾过滤是一场战争。那些使用你系统的人非常清楚你采用什么来评价一篇帖子的质量,所以他们会想尽办法来使得他们的帖子具有这些属性。因此,质量排序应该关注对哪些诚实发布的内容进行排序。如果将垃圾邮件排高名次,那质量排序学习器就大打折扣。同理也要将粗俗的内容从质量排序中拿出分开处理。垃圾过滤就是另外一回事。你必须考虑到要生成的特征会经常性的改变。你会输入很多明显的规则到系统中。至少要保证你的模型是每日更新的。同时,要重点考虑内容创建者的信誉问题。

机器学习阶段 2:特征工程

在机器学习系统研发周期的第一阶段,重点是把训练数据导入学习系统,得到感兴趣的评价指标,并创建基础架构。当你有了一个端对端的系统,并且该系统的单元和测试都仪表化之后,第二阶段便开始了。

第二阶段需要纳入尽可能多的有效特征,并依据直观的感觉组合起来。在这个阶段,所有的评估指标仍然会上升。

Rule #16: Plan to launch and iterate.

法则16:做好持续迭代上线的准备

不要期望现在发布的这个模型是最终的模型。因此,考虑你给当前这个模型增加的复杂度会不会减慢后续的发布。许多团队每季度推出一个模型或者更多年。之所以不断发布新模型,有三个基本原因:

  1. 你会不断地想到新的特征。
  2. 你会不断地调整并以新的方式组合旧的特征。
  3. 你会不断调优目标。

Rule #17: Start with directly observed and reported features as opposed to learned features.

法则 17:优先使用直接观测或收集到的特征,而不是学习出来的特征(learned features)

先描述一下什么是学习出来的特征(learned features)。学习出来的特征(learned features)是由外部系统(比如无监督聚类系统)或学习者本身(比如因子模型、深度学习)生成的特征。两种方式生成的特征都很有用,但也有很多问题,因此不应当用在第一个模型中。

Rule #18: Explore with features of content that generalize across contexts.

法则 18:探索使用可以跨场景的内容特征

通常情况下,机器学习只占到一个大系统中的很小一部分,因此你必须要试着从不同角度审视一个用户行为。比如热门推荐这一场景,一般情况下论坛里“热门推荐”里的帖子都会有许多评论、分享和阅读量,如果利用这些统计数据对模型展开训练,然后对一个新帖子进行优化,就有可能使其成为热门帖子。另一方面,YouTube上自动播放的下一个视频也有许多选择,例如可以根据大部分用户的观看顺序推荐,或者根据用户评分推荐等。总之,如果你将一个用户行为用作模型的标记(label),那么在不同的上下文条件下审视这一行为,可能会得到更丰富的特征(feature),也就更利于模型的训练。需要注意的是这与个性化不同:个性化是确定用户是否在特定的上下文环境中喜欢某一内容,并发现哪些用户喜欢,喜欢的程度如何。

Rule #19: Use very specific features when you can.

法则 19:尽量使用非常具体的特征

在海量数据的支持下,即使学习数百万个简单的特征也比仅仅学习几个复杂的特征要容易实现。由于被检索的文本标识与规范化的查询并不会提供太多的归一化信息,只会调整头部查询中的标记排序。因此你不必担心虽然整体的数据覆盖率高达90%以上,但针对每个特征组里的单一特征却没有多少训练数据可用的情况。另外,你也可以尝试正则化的方法来增加每个特征所对应的样本数。

Rule #20: Combine and modify existing features to create new features in human--understandable ways.

法则 20: 用人类可理解的方式对已有特征进行组合和修改

有很多种方法组合和改良特征。像 TensorFlow 这样的机器学习系统,它允许通过 transformations 预处理数据。其最标准的两种方法分别是“discretization(离散化)”和“crosses(叉积)”。

Discretization 会根据一个连续的特征创建许多离散的特征。假定年龄是一个连续的特征。我们可以创建如下特征,当年龄小于 18 时记为 1,或者当年龄在 18 到35 岁之间时为 1,以此类推。不用过多考虑这些数据的边界问题:简单的数字可以给你最直观的冲击。

Cross由两个或多个特征栏组成。根据TensorFlow给出的解释, 特征栏是一组同类的特征。(如{男,女}、{美国,加拿大,墨西哥}等)。而Cross是一个新的特征栏,可以用{男,女}×{美国,加拿大,墨西哥}等来简单的表示。新的
特征栏会包含以下特征,如{男,加拿大}。使用TensorFlow时可以让它帮你创建cross。{男,加拿大}可以在样本中代表男性加拿大人。注意若模型使用三个以上的特征栏组成的cross,则需要大量的数据来训练模型。

Cross 会产生庞大的特征栏,有可能导致过拟合现象。举个例子,假设你要做某种搜索。检索词构成一个特征栏,文档中的词构成另一个特征栏。你可以通过cross 来组合它们,但这样会出现很多特征。处理文本时,有两个替代性方案。最苛刻的方案是 dot product(点积)。点积仅统计检索词和文档词中的公共词汇。得到的特征可以被离散化。另一种方案是取intersection(交集):

因此,我们有一个特征来表示当“pony(色情)”这个词同时出现在文档和检索词中,另一个特征表示“the”同时出现在文档和检索词中。

Rule #21: The number of feature weights you can learn in a linear model is roughly proportional to the amount of data you have.

法则 21:线性模型中的特征权重的数量应大致和样本数量形成一定的比例

关于模型究竟多复杂才合适,统计学习理论有许多有趣的结论。但总的来说,这一条法则就足够了。我曾和一些人交流过,在他们看来,要想学到些东西,一千个样本远远不够,至少需要一百万个样本。这是因为,他们被特定的学习方法束缚了手脚。而诀窍就是,根据数据大小调整学习方法:

  1. 如果你在开发一个搜索排名系统,并且有数百万不同的词汇存在于文档和检索词中,而你仅有 1000 个带有标记的样本。那么你应该使用文档和检索词的点积特征、 TF-IDF 以及其它六个人工设计的特征。 1000 个样本,对应 12个左右的特征。
  2. 如果有一百万个的样本,那就通过 regularization 或特征 selection,取文档特征栏和检索词特征栏的交集。这样你能得到数百万个特征,但 regularization会帮你减少些许的特征。一千万个样本,对应大约十万个特征。
  3. 如果有十亿个乃至几千亿个样本,你可以通过 regularization 和特征选取,取文档特征栏和 query token 的叉积。如果有十亿个样本,那么你会得到一千万个特征。

Rule #22: Clean up features you are no longer using.

法则22:清理不再使用的特征

当决定要清除哪些特征时,需要考虑其覆盖率,即该项特征覆盖了多少样本。举个例子,如果你有一些比较特别的特征,但只有 8% 的用户与之相关,那么这些特征就无足轻重了。同时,有些特征可能超越它们的权重。比如某个特征仅覆盖 1% 的数据,但 90% 的正样本都含有这种特征。那么,也应当将这个特征添加进来。

系统的人工分析

在进入机器学习第三阶段前,有一些在机器学习课程上学习不到的内容也非常值得关注:如何检测一个模型并改进它。这与其说是门科学,还不如说是一门艺术。这里再介绍几种要避免的反模式(anti-patterns)

Rule #23: You are not a typical end user.

法则 23: 你并非典型终端用户

这可能是让一个团队陷入困境的最简单的方法。虽然fishfooding(只在团队内部使用原型)和dogfooding(只在公司内部使用原型)都有许多优点,但无论哪一种,开发者都应该首先确认这种方式是否符合性能要求。要避免使用一个明显不好的改变,同时,任何看起来合理的产品策略也应该进一步的测试,不管是通过让非专业人士来回答问题,还是通过一个对真实用户的线上实验。

Rule #24: Measure the delta between models.

法则24:测量模型间的差异

在将你的模型发布上线前,一个最简单,有时也是最有效的测试是比较你当前的模型和已经交付的模型生产的结果之间的差异。如果差异很小,那不再需要做实验,你也知道你这个模型不会带来什么改变。如果差异很大,那就要继续确定这种改变是不是好的。检查对等差分很大的查询能帮助理解改变的性质(是变好,还是变坏)。但是,使用不同模型进行比较前,需要确保该模型和它本身比较,这个差异很小(理想情况应该是无任何差异)。

Rule #25: When choosing models, utilitarian performance trumps predictive power.

法则 25: 选择模型时,性能表现比预测力更重要

虽然我们训练模型时 objective 一般都是 logloss,也就是说实在追求模型的预测能力。但是我们在上层应用中却可能有多种用途,例如可能会用来排序,那么这时具体的预测能力就不如排序能力重要;如果用来划定阈值然后跟根据阈值判断垃圾邮件,那么准确率就更重要。当然大多数情况下这几个指标是一致的。

Rule #26: Look for patterns in the measured errors, and create new features.

法则 26: 在错误中寻找规律,然后创建新特征

假设你的模型在某个样本中预测错误。在分类任务中,这可能是误报或漏报。在排名任务中,这可能是一个正向判断弱于逆向判断的组。但更重要的是,在这个样本中机器学习系统知道它错了,需要修正。如果你此时给模型一个允许它修复的特征,那么模型将尝试自行修复这个错误。

另一方面,如果你尝试基于未出错的样本创建特征,那么该特征将很可能被系统忽略。例如,假设在谷歌Play商店的应用搜索中,有人搜索“免费游戏”,但其中一个排名靠前的搜索结果却是一款其他App,所以你为其他App创建了一个特征。但如果你将其他App的安装数最大化,即人们在搜索免费游戏时安装了其他App,那么这个其他App的特征就不会产生其应有的效果。

所以,正确的做法是一旦出现样本错误,那么应该在当前的特征集之外寻找解决方案。例如,如果你的系统降低了内容较长的帖子的排名,那就应该普遍增加帖子的长度。而且也不要拘泥于太具体的细节。例如你要增加帖子的长度,就不要猜测长度的具体含义,而应该直接添加几个相关的特征,交给模型自行处理,这才是最简单有效的方法。

Rule #27: Try to quantify observed undesirable behavior.

法则 27:尝试量化观察到的异常行为

如果在系统中观察到了模型没有优化到的问题,典型的例如推荐系统逼格不够这种问题,这时应该努力将这种不满意转化为具体的数字,具体来讲可以通过人工标注等方法标注出不满意的物品,然后进行统计。如果问题可以被量化,后面就可以将其用作特征、objective或者metric。整体原则就是“先量化,再优化”。

Rule #28: Be aware that identical short-term behavior does not imply identical long-term behavior.

法则 28:短期行为相同并不代表长期行为也相同

假设你有一个新系统,它可以查看每个doc_id和exact_query,然后根据每个文档的每次查询行为计算其点击率。你发现它的行为几乎与当前系统的并行和A/B测试结果完全相同,而且它很简单,于是你启动了这个系统。却没有新的应用显示,为什么?由于你的系统只基于自己的历史查询记录显示文档,所以不知道应该显示一个新的文档。
要了解一个系统在长期行为中如何工作的唯一办法,就是让它只基于当前的模型数据展开训练。这一点非常困难。

训练偏差(Training-Serving Skew)

训练偏差是指训练时的表现和在生产环境中实际运行时的表现的差别。这种偏差可能由以下因素引起:

  1. 在训练时和在实际工作流中用不同的方式处理数据。
  2. 训练中的数据和在实际运行中的分布不同。
  3. 模型和算法之间存在反馈循环。

解决这类问题的核心是对系统和数据的变化进行监控,确保一切差异都在监控之内,不会悄悄进入系统。

Rule #29: The best way to make sure that you train like you serve is to save the set of features used at serving time, and then pipe those features to a log to use them at training time.

法则 29: 要让实际产品和训练时表现一样好,最好的方法是实际运行中保留特征集,并记录到日志中以便训练中使用

即使你不能对每个样例都这样做,做一小部分也比什么也不做好,这样你就可以验证服务和训练之间的一致性(见规则37)。在谷歌采取了这项措施的团队有时候会对其效果感到惊讶。比如YouTube主页在服务时会切换到日志记录特征,这不仅大大提高了服务质量,而且减少了代码复杂度。目前有许多团队都已经在其基础设施上采用了这种策略。

Rule #30: Importance-weight sampled data, don't arbitrarily drop it!

法则30:给抽样数据按重要性赋权重,不要随意丢弃它们

当我们有太多训练数据时,我们会只取其中的一部分。但这是错误的。正确的做法是,如果你给某条样本30%的采样权重,那么在训练时就给它10/3的训练权重。通过这样的重要性赋权(importance weight),整个训练结果的校准性(calibration)就还能够保证。

Rule #31: Beware that if you join data from a table at training and serving time, the data in the table may change.

法则 31:如果要从表格中组合数据,注意训练时和实际运行时表格可能发生改变

假设你要把文档 id 和包含文档特征的表格(比如评论或点击的数量)结合起来。从训练和实际运行,表格中的特征可能会改变(例如用户对物品的评论数),模型对同一文档做的预测也能不同。要避免这这类问题,最简单的办法就是记录所有实际运行时的特征。若表格只是缓慢的变化,你也可以按照每小时或每天的频率对其做出记录,得到足够相近的数据。注意这样不能完美的解决问题。

Rule #32: Re-use code between your training pipeline and your serving pipeline whenever possible.

法则 32: 尽量在训练流和实际运行流中使用重复代码

首先需要明确一点:批处理和在线处理并不一样。在线处理中,你必须及时处理每一个请求(比如,必须为每个查询单独查找),而批处理,你可以合并完成。服务时,你要做的是在线处理,而训练是批处理任务。尽管如此,还是有很多可以重用代码的地方。比如说,你可以创建特定于系统的对象,其中的所有联结和查询结果都以人类可读的方式存储,错误也可以被简单地测试。然后,一旦在服务或训练期间收集了所有信息,你就可以通过一种通用方法在这个特定对象和机器学习系统需要的格式之间形成互通,训练和服务的偏差也得以消除。因此,尽量不要在训练时和服务时使用不同的变成语言,毕竟这样会让你没法重用代码。

Rule #33: If you produce a model based on the data until January 5th, test the model on the data from January 6th and after.

法则 33: 如果训练数据是1月5日之前的,那么测试数据要从1月6日开始

测试模型时应当使用的比训练模型时更加新的数据,因为这更能反映你的系统实际运行表现。如果你用 1 月 5 日前的数据生成了一个模型,那就得用 1月 6 号之后的数据测试它。你会发现,在新的数据下模型表现得没那么好,但也不会差到哪里去。这个结果更加接近真实运行时的表现。

Rule #34: In binary classification for filtering (such as spam detection or determining interesting emails), make small short-term sacrifices in performance for very clean data.

法则 34:在过滤类的任务中,被标记为负的样本是不会展示给用户的,例如可能会把75%标记为负的样本阻拦住不展现给用户。但如果你只从展示给用户的结果中获取下次训练的样本,显然你的训练样本是有偏的。

更好的做法是使用一定比例的流量(例如1%)专门收集训练数据,在这部分流量中的用户会看到所有的样本。这样显然会影响线上的真实过滤效果,但是会收集到更好的数据,更有利于系统的长远发展。否则系统会越训练越偏,慢慢就不可用了。同时还能保证至少过滤掉74%的负样本,对系统的影响也不是很大。

但是如果你的系统会过滤掉95%或者更多的负样本,这种做法就不那么可行了。即使如此,为了准确衡量模型的效果,你仍然可以通过构造一个更小的数据集(0.1%或者更小)来测试。十万级别的样本足够给出准确的评价指标了。

Rule #35: Beware of the inherent skew in ranking problems.

法则 35: 注意排序问题存在固有偏差

当你对排序算法做出足够多的改动时,一方面会引起完全不同的排序结果,另一方面也可能在很大程度上改变算法未来可能要处理的数据。这会引入一些固有偏差,因此你必须事先充分认识到这一点。以下这些方法可以有效帮你优化训练数据。

  1. 对涵盖更多查询的特征进行更高的正则化,而不是那些只覆盖单一查询的特征。这种方式使得模型更偏好那些针对个别查询的特征,而不是那些能够泛化到全部查询的特征。这种方式能够帮助阻止非常流行的结果进入不相关查询。这点和更传统的建议不一样,传统建议应该对更独特的特征集进行更高的正则化。
  2. 只允许特征具有正向权重,这样一来就能保证任何好特征都会比未知特征合适。
  3. 不要有那些仅仅偏文档(document-only)的特征。这是法则1的极端版本。比如,不管搜索请求是什么,即使一个给定的应用程序是当前的热门下载,你也不会想在所有地方都显示它。没有仅仅偏文档类特征,这会很容易实现。

Rule #36: Avoid feedback loops with positional features.

法则 36:用位置特征来避免反馈回路

大家都知道排序位置本身就会影响用户是否会对物品产生互动,例如点击。所以如果模型中没有位置特征,本来由于位置导致的影响会被算到其他特征头上去,导致模型不够准。可以用加入位置特征的方法来避免这种问题,具体来讲,在训练时加入位置特征,预测时去掉位置特征,或者给所有样本一样的位置特征。这样会让模型更正确地分配特征的权重。

需要注意的是,位置特征要保持相对独立,不要与其他特征发生关联。可以将位置相关的特征用一个函数表达,然后将其他特征用另外的函数表达,然后组合起来。具体应用中,可以通过位置特征不与任何其他特征交叉来实现这个目的。

Rule #37: Measure Training/Serving Skew.

法则 37: 衡量训练和服务之间的差异

很多情况会引起偏差。大致上分为一些几种:

  1. 训练集和测试集之间的差异。这种差异会经常存在,而且不一定是坏事。
  2. 测试集和“第二天”数据间的差异。这种差异也会一直存在,而这个“第二天”数据上的表现是我们应该努力优化的,例如通过正则化。这两者之间差异如果过大,可能是因为用到了一些时间敏感的特征,导致模型效果变化明显。
  3. “第二天”数据和线上数据间的差异。如果同样一条样本,在训练时给出的结果和线上服务时给出的结果不一致,那么这意味着工程实现中出现了bug。

机器学习第三阶段:放慢速度、优化细化和复杂的模型

一般会有一些明确的信号来标识第二阶段的尾声。首先,每月的提升会逐步降低。你开始在不同指标之间做权衡,有的上升有的下降。

这将会变得越来越有趣。增长越来越难实现,必须要考虑更加复杂的机器学习。

警告:相对于前面两个阶段,这部分会有很多开放式的法则。第一阶段和第二阶段的机器学习总是快乐的。当到了第三阶段,每个团队就不能不去找到他们自己的途径了。

Rule #38: Don't waste time on new features if unaligned objectives have become the issue.

法则 38: 如果目标没有达成一致,就不要在新特征上浪费时间

当达到评估指标瓶颈,你的团队开始关注 ML 系统目标范围之外的问题。如同之前提到的,如果产品目标没有包括在算法目标之内,你就得修改其中一个。比如说,你也许优化的是点击数、点赞或者下载量,但发布决策还是依赖于人类评估者。

Rule #39: Launch decisions are a proxy for long-term product goals.

法则 39:模型发布决策是长期产品目标的代理

这个法则字面上有点难以理解,其实作者核心就是在讲一件事情:系统、产品甚至公司的长远发展需要通过多个指标来综合衡量,而新模型是否上线要综合考虑这些指标。所谓代理,指的就是优化这些综合指标就是在优化产品、公司的长远目标。

决策只有在所有指标都在变好的情况下才会变得简单。但常常事情没那么简单,尤其是当不同指标之间无法换算的时候,例如A系统有一百万日活和四百万日收入,B系统有两百万日活和两百万日收入,你会从A切换到B吗?或者反过来?答案是或许都不会,因为你不知道某个指标的提升是否会cover另外一个指标的下降。

关键是,没有任何一个指标能回答:“五年后我的产品在哪里”?

而每个个体,尤其是工程师们,显然更喜欢能够直接优化的目标,而这也是机器学习系统常见的场景 。现在也有一些多目标学习系统在试图解决这种问题。但仍然有很多目标无法建模为机器学习问题,比如用户为什么会来访问你的网站等等。作者说这是个AI-complete问题,也常被称为强AI问题,简单来说就是不能用某个单一算法解决的问题。

Rule #40: Keep ensembles simple.

法则 40: 保持模型集合(ensembles)的简单性

接收原始特征、直接对内容排序的统一模型,是最容易理解、最容易修补漏洞的模型。但是,一个集成模型(一个把其他模型得分组合在一起的“模型”)的效果会更好。为保持简洁,每个模型应该要么是一个只接收其他模型的输入的集成模型,要么是一个有多种特征的基础模型,但不能两者皆是。如果你有单独训练、基于其它模型的模型,把它们组合到一起会导致不好的行为。

只使用简单模型来集成那些仅仅把你的基础模型输出当做输入。你同样想要给这些集成模型加上属性。比如,基础模型生成得分的提高,不应该降低集成模型的分数。另外,如果连入模型在语义上可解释(比如校准了的)就最好了,这样其下层模型的改变不会影响集成模型。此外,强行让下层分类器预测的概率升高,不会降低集成模型的预测概率。

Rule #41: When performance plateaus, look for qualitatively new sources of information to add rather than refining existing signals.

法则 41:当效果进入瓶颈期,寻找本质上新的信息源,而不是优化已有的信号

你先是添加了一些用户的人口信息,又添加了一些文档词汇的信息,接着你又浏览了一遍模版,而后又调整了规则,但是最后,关键度量却只提升了不到 1%。现在怎么办?

这时候应该用完全不同的特征搭建基础架构,比如用户昨天/上周/去年访问的文档的历史记录。利用 wikidata 或对公司来说比较重要的东西(比如 google 的知识图)。你或许需要使用深度学习。开始调整你对投资回报的期望,并作出相应努力。如同所有工程项目,你需要平衡新增加的特征与提高的复杂度。

Rule #42: Don't expect diversity, personalization, or relevance to be as correlated with popularity as you think they are.

法则 42:不要期望多样性、个性化、相关性和受欢迎程度之间有紧密联系

一系列内容的多样性能意味着许多东西,内容来源的多样性最为普遍。个性化意味着每个用户都能获得它自己感兴趣的结果。相关性意味着一个特定的查询对于某个查询总比其他更合适。显然,这三个属性的定义和标准都不相同。

问题是标准很难打破。

注意:如果你的系统在统计点击量、耗费时间、浏览数、点赞数、分享数等等,你事实上在衡量内容的受欢迎程度。有团队试图学习具备多样性的个性化模型。为个性化,他们加入允许系统进行个性化的特征(有的特征代表用户兴趣),或者加入多样性(表示该文档与其它返回文档有相同特征的特征,比如作者和内容),然后发现这些特征比他们预想的得到更低的权重(有时是不同的信号)。

这不意味着多样性、个性化和相关性就不重要。就像之前的规则指出的,你可以通过后处理来增加多样性或者相关性。如果你看到更长远的目标增长了,那至少你可以声称,除了受欢迎度,多样性/相关性是有价值的。你可以继续使用后处理,或者你也可以基于多样性或相关性直接修改你的目标。

Rule #43: Your friends tend to be the same across different products. Your interests tend not to be.

法则 43: 在不同的产品中,你的朋友可能相同,但兴趣却不尽然

谷歌经常在不同产品上使用同样的好友关系预测模型,并且取得了很好的效果,这证明不同的产品上好友关系是可以迁移的,毕竟他们是固定的同一批人。但他们尝试将一个产品上的个性化特征使用到另外一个产品上时却常常得不到好结果。可行的做法是使用一个数据源上的原始数据来预测另外数据源上的行为,而不是使用加工后的特征。此外,用户在另一个数据源上的行为历史也会有用。

  • 个人微信号
  • 添加时请备注“脑洞大开读者”
  • weinxin
  • 微信公众号
  • 关注会有更多精彩内容!
  • weinxin

发表评论

您必须登录才能发表评论!