编者按:此白皮书为谷歌总结的机器学习(ML)最优实践方法,浓缩了其多年技术积累与经验,尤其是 Youtube、Google Play 和 Google+ 等平台背后的 ML 算法开发、维护经历。谷歌于白皮书中总结了四十三条 ML 黄金法则,旨在帮助已经掌握了基础知识的开发者少走弯路。鉴于其珍贵程度与技术性,雷锋网逐条做了严格尊重原文的翻译。若你已学习过机器学习课程,抑或有开发 ML 模型的经验,那么应当具备足够的背景知识理解这篇文章。
以下是对文中反复出现的术语的解释。
实例( Instance):做预测的对象。比如说,实例可以是一个网页,你想要把它分类为“关于猫”或者“与猫不相关”。
标记(Label):预测任务的答案。它既可以是机器学习系统生成的答案,也可以是训练数据中提供的正确答案(雷锋网注:比如监督学习中的人工标记)。举例来说,一个网页的标记可以是“关于猫”。
特征(Feature):预测任务中实例的属性。比如说,某网页可能有“包含关键词‘猫’”的特征
特征栏 (Feature Column):这是谷歌自创的术语,意为关联特征的集合。比如说,用户的所有可能居住国家的集合。一个样例的特征栏可以有一个或多个特征。特征栏可被看作是 VW 系统(微软、雅虎所用)中的命名空间,或者场( field)。
样例(Example):有标记的实例(具备特征)。
模型(Model):对预测任务的统计表达。你用样例训练模型,然后用模型做预测。
指标(Metric):你在意的数字。可被直接优化过,也可没有。
目标(Objective):你的算法试图优化的指标。
流水线(Pipeline):机器学习算法的基础设施;包括从前端收集数据,把它放入训练数据文档,训练一个或多个模型,以及把模型输出、产品化。
为了开发出好产品:
做机器学习这一行首先要摆正心态,你是一名(优秀的)工程师,不要拿专家的标准来要求自己。
事实上,你将要面对的大多数难题是工程问题(engineering problems)。即便是一个杰出的ML 专家,坐拥该级别才有的资源,其大多数收获也来自于特征而不是 ML 算法。所以,ML 开发的基本路线是:
保证可靠的端到端流水线
从制定合理的目标着手
用简单的方式,加入符合常识的特征
确保流水线始终可靠
该方法能帮你赚钱养家,并且让很多人满意。只有当无路可走、简单的技巧无法再起作用时,你才需要偏离该路线。但注意,提高复杂度会拖慢将来的产品发布。另外,当你穷尽了简单技巧,或许就到了登堂入室、探索 ML 最前沿技术的时候了。具体请看本文机器学习第三阶。
本文分为四个部分:
第一部分“1.0 做机器学习之前”,会帮你搞清楚,你创建机器学习系统的时机是否已经成熟。
第二部分“2.0 机器学习第一阶”是关于设置你的第一个流水线。
第三部分“3.0 机器学习第二阶”,关乎启动和重复,同时向流水线加入新特征。
最后一部分“4.0 机器学习第三阶”是关于达到瓶颈后怎么办。
对发布一个不含 ML 技术的产品,不要有顾虑
首先要设计和贯彻指标
在机器学习和复杂启发算法之间,选择前者
第一个模型要简单,把基础设施弄好
测试基础设施要与 ML 测试分开
复制流水线时当心数据遗落
把启发式(heuristics)变为特征,不然就对它们做外部处理
了解系统的时效性
在输出模型之前发现问题
于无声处听惊雷:注意没表现出来的故障
注意特征栏的维护者和文件
选择直接优化哪个目标时,不需要想太多
选择一个简单、可观察并且可归属(attributable)的指标来作为第一个目标
用可解释的模型开头,修补漏洞会更简单
用 policy layer(规则层)把垃圾信息过滤和质量排序分来
做好模型被推倒和重建的准备
直接以观察到的或报告的特征开始训练,而不是经过学习的特征
从不同的上下文环境中提取特征
尽量选择更具体的特征
以合理的方式组合、修改现有特征
通过线性模型学到的特征权重的数目,大致与数据量成正比
清理不需要的特征
你并不是一个典型的用户
版本之间存在对等差分(symmetric difference)
选择模型时,性能胜过预测能力
从误差中查找新模式、创建新特征
尝试量化观察到的异常行为
注意短期行为和长期行为的差别
确保训练和服务一样好的最直接办法是:保存服务时使用的特征,然后将这些特征导入日志,以便在训练中使用。
重视采样数据
注意表格中的数据可能改变
尽量在训练和服务流水线中复用代码
训练和测试的数据不能相同
在二进制分类过滤的应用场景中(例如垃圾邮件检测),不要为了纯净的数据做太大的性能牺牲
注意排序问题的固有偏差
避免具有位置特征的反馈回路
测量训练/服务偏差
如果目标之间不搭,并成为问题,就不要在新特征上浪费时间
模型发布决策是长期产品目标的代理
保证集成模型(ensemble)的简洁
当性能达到瓶颈,相比精炼现存信号,不如寻找新性质的信息源
不要期望多样性、个性化、相关性和受欢迎程度之间有紧密联系
不同产品中,你的朋友总是那一个,你的兴趣不会如此
机器学习很酷,但要有数据。理论上,你可以把另一个相近课题的数据拿来用,调整下模型变成一个新产品。但这么做的实际效果,通常比简单的启发式算法(heuristics)还差。如果你认为机器学习能完成任务的 100%。那么启发式算法能帮你完成 50%。
比如说,若你为应用商店进行 app 排名,不妨直接利用下载率和装机量写个简单算法;若你在检测垃圾邮件,可以先把发送过垃圾邮件的地址过滤掉。也不要在人工编辑上有顾虑。如果机器学习对于你的产品不是必需的,那么在获得数据之前不要用它。
在定义你的 ML 系统要做什么之前,要尽可能多得追踪你当前的系统。这出于以下原因:
在早期,获得系统用户的许可相对容易。
如果你认为有些东西在将来需要考虑,最好从现在起就收集历史数据。
如果你设计系统时考虑了指标的工具化( metric instrumentation),会省下将来的许多力气。你绝对不想为了指标而查找日志字符串。
有些东西会改变,有些不会。比如说,假设你想要直接优化每日活跃用户。但是,在你对系统的早期操作中,你也许会发现用户体验的大幅变化并不会显著改变这个指标。
Google+ 团队会衡量每次阅读的扩展数(expands per read)、分享、点赞、评论,以及每用户评论数、分享等等。然后他们利用这些数据计算发布消息的质量。另外要注意,能通过试验把用户分组并整合数据的试验框架非常重要,参考第 12 条。
通过更灵活地收集指标,你能用更大的视角观察系统。发现一个问题?添加一个指标来追踪它!对上一个发布版本的量化变动很兴奋?添加指标来追踪!
一个简单的启发算法能帮助产品走向市场,而复杂启发算法难以维护。一旦你有了数据以及需要实现的目标的蓝图,就可以转去开发 ML。在大多数软件工程任务中,开发者需要不停更新开发方式,不管是启发式算法还是 ML 模型。你会发现后者更加容易更新维护(参考第 16 条)。
对于第一条流水线,关注你的系统基础设施。虽然,设想你将要做的种种 ML 应用很有趣;但如果你无法信任自己的流水线,你会很难搞清楚状况。
第一个模型为你的产品提供了最大的助力,所以它不需要花哨。而且你会遇到许多想象之外的基础设施问题。在你的新 ML 系统诞生之前,你需要决定:
如何获取学习算法的样例
对于你的系统,“好”、“坏”的定义是什么
如何把模型整合入应用。你可以实时应用模型,也可以在线下预计算模型,并把结果保存好。比如对网页预分类,然后在表格里保存结果。但有的任务可能需要对实时聊天信息进行分类。
选择简单的特征更容易保证:
这些特征正确应用于学习算法
模型学会合理的权重。
这些特征正确应用于服务器模型。
当你有了能可靠做到上述三点的系统,大部分的工作就已完成。简单模型提供给你基础的指标和行为,然后你可以用它们来测试更复杂的模型。有些团队把目标定为“中性”的首发——故意在首次发布不那么重视机器学习成果,以避免分心。
5. 测试基础设施要与 ML 测试分开
要确保基础设施可测试,而且系统的学习部分都被包含在内,使得你能够测试所有相关物。特别是:
测试把数据导入算法。检查可填充的特征栏是不是空的。若条件允许,手工检查训练算法的输入。若可能,把流水线数据与其他地方作比较,比如 RASTA。
测试把数据导出训练算法。确保训练环境的模型与服务环境(serving environment)的模型产生同样的得分(详见第 37 条)。
ML 有不可预测的因素。所以一定要对生成训练、服务样例的代码进行测试;这样你可以在服务中载入、使用固定模型。另外,理解你的数据也十分重要。
我们经常复制现成的流水线来创建新流水线(例如 cargo cult 编程),但有时旧流水线遗落了新流水线需要的数据。举个例子, Google Plus What’s Hot(雷锋网按:社交软件 Google+ 的热门新闻版块) 的流水线会遗落旧帖子(因为它试图为新帖子排名)。我们复制该流水线,用于 Google Plus Stream(Google+ 流)。对于后者,旧帖子仍然有意义,但新流水线仍然会丢掉数据。
另一个常见的模式是只记录用户看过的数据。因此,当你需要对为什么用户没有看到某个信息进行建模,该数据完全没用——因为所有反例已经被丢掉了。Google Play 发生过一个类似的问题:当我们开发 Google Play 应用商城主页时,创建出的新流水线包含另外两个登录页面(Play Games Home and Play Home Home,游戏主页和家庭主页)的样例。但是,并没有能够对“样例来自于哪个主页”加以区分的特征。
通常来讲,ML 试图解决的问题并不是什么新问题——一般有现成的排名、分类等各种系统。这意味着有一大堆规则和启发式算法可用。这些启发式能在你调整 ML 时起到帮助。你应该压榨出启发式算法的所有信息,这有两个原因:1. 到 ML 系统的过渡会更顺畅。2. 这些规则通常包含一大堆关于系统的直觉信息,你绝对不想把它们扔掉。有四种利用现成启发式算法的途径:
使用启发式算法预处理。如果该特征非常棒,那么这就是一个选择。举个垃圾邮件过滤器的例子,若发件人已经被加入黑名单,不要试图重新学习“加入黑名单”是啥意思。直接拦截该信息。该方法最适用于二分类任务。
创建特征。直接用启发式创建特征相当棒。比如说,如果你用启发式计算一个问题结果的相关度分值,你可以把该得分作为特征值。之后,你或许想用 ML 技术来操作数值(比如把数值转化为有限个独立值集合,或与其他特征合并),但却拿启发式生成的原始数值来开头。
挖掘启发式的原始输入。如果有面向 APP 的启发式把装机量、文字中字母数目和日期组合到一起,就得考虑把它们分开——把这些输入分开来学习。有些应用于整体的技巧可用在这里(详见第 40 条)。
修正标记。当你发现启发式抓取了标记中未包含的信息时,这是一个选择。举个例子,如果你试图最大化下载量,但却仍然想要高品质内容,那么或许最好的方案是把标记与 APP 的平均星星得分相乘。这里有很大的余地。请参考“2.3 你的第一个目标”部分。
请注意启发式为 ML 系统加入的复杂度。在新 ML 算法中加入旧启发式有助于平滑地过渡,但你需要考虑是否更简单的实现方式。
总的来讲,养成处理警告(alerts)的好习惯,比如对每个提醒付诸行动,并且建立一个仪表页面(dashboard page)。
当你的模型已经开发出来一天、一周、一季度了,它的效果分别会降低多少?该信息能帮助你理解维护任务的优先级。假设模型一天没更新,你就要损失 10% 的收入。那么你或许要考虑雇佣专人每天维护。许多广告服务系统每天都有需要处理的新广告,因此必须每日更新。再举一个例子,如果 Google Play 的搜索 ML 模型停止更新,一个月内就会造成很大的损失。Google+ What’s Hot(雷锋网注:热门推荐)的一些模型,并没有针对发布信息的身份确认机制,所以不需要频繁导出这些模型。但有身份确认机制的模型就需要非常频繁地更新。另外需注意,时效性会随时间而变化,尤其是为模型添加或移除特征栏的时候。
许多 ML 系统包含该步骤:输出模型到服务端。如果输出的模型有问题,会直接让用户们遇上。而这个环节之前的问题只是训练问题,不会影响用户体验。
在导出模型之前一定要检查,尤其要确保模型在给定数据上有合理的效果。另外,若你对数据有顾虑,不要输出该模型。许多开发团队会在模型输出前检查 ROC 曲线 (或 AUC) 下的区域。未输出的模型存在问题,可能只需要一封 email 提醒一下。但用户端模型出了问题,很可能需要你向上司、同事解释一整页。所以最好多花点时间,在影响到用户之前做到胸有成竹。
这是一个多见于机器学习、而少见于其他系统的问题。设想一个不再更新的特定表格:机器学习系统会调整,其行为仍会有合理表现,但逐渐退化。有时候开发者会发现过期几个月的表格——这时,一个简单的更新所提高的性能,比该季度的所有发布新版本都要高。举个例子,对一个特征的取舍会因为执行情况的变化而变化:覆盖 90% 样例的特征栏可能突然降低到只覆盖 60%。Google Play 曾经就有一个过期了六个月的表格,单单更新那个表格就带来了 2% 的安装率提升。如果你对统计数据进行跟踪,并偶尔人工检查,就能减少这类失误。
如果系统很大、有许多特征栏,你需要知道谁创立、维护了每一个特征栏。如果你发现懂得特征栏的那个人要跳槽了,一定要确保团队里有还有人知道这些信息。虽然许多特征栏有描述名称,你仍然需要更详细的解释,知道它是什么、从哪里来、起什么作用。
你有许多关心的系统指标或度量,但 ML 算法通常只需要一个目标——算法试图优化的某个数字。这里,我要区别目标(objectives)和指标(metrics):指标是系统报告的任何数字,或许重要,或许不重要。详见第二条。
你想要赚钱,让用户满意,并且让地球更美好。有许多你关心的指标,你应该全部都去测量(见第二条)。但在 ML 初期,你会注意到它们全都有提升,即便是那些没有直接优化的也是如此。举个例子,假设你关注点击数、浏览时间和每日活跃用户。如果你优化点击数,你会看到浏览时间也在上升。
所以简简单单就好。当你能轻易地提高所有指标,不需要在不同指标之间的平衡上想太多。但也不要误解这条建议:别把目标与系统最终的健康混为一谈(详见第 39 条)。另外,如果你增加了直接优化的指标,但决定不予发布,或许有必要重新修订目标。
很多情况下你不知道真正的目标是什么——你以为你知道。但当你仔细观察数据,以及对旧系统和新 ML 系统进行分析,你意识到自己其实想要对原定目标进行修改。团队不同成员也经常无法在真正的目标上取得一致意见。ML 目标应当易于测量,并可作为“真正”目标的代理。所以最好采用简单的 ML 目标训练,然后考虑在这之上设一个 "policy layer"(规则层),允许你加入额外的逻辑(但愿是简单的逻辑)来做最终排名。
最容易建模的是,能被直接观察到、并且可归属于系统中某个行动的用户行为:
这个排名链接被点击了吗?
这个排名对象被下载了吗?
这个排名对象被 转发/回复/发 email 了吗?
这个排名对象被打分了吗?
这个显示的对象被标记为垃圾邮件/色情信息/侮辱性信息了吗?
一开始要避免对间接作用建模:
用户在第二天访问了吗?
用户的访问时间是多长?
每日活跃用户都是谁?
其实,间接作用是非常不错的指标,并且可在 A/B 测试和发布决定中使用。
最后,不要试图让 ML 搞懂:
用户对使用该产品满意吗?
用户对体验满意吗?
产品提升了用户的福祉了吗?
这如何影响公司的整体健康?
这些都很重要,但是极度困难。你应该用代理来替代:如果用户感到开心,他们会在页面停留更长时间。如果用户满意,他明天会再次访问。目前,当涉及到福祉和公司健康状态,把 ML 目标与产品本质和商业计划之间做关联需要人的判断。
线性回归、逻辑回归、泊松回归(Poisson regression)直接被概率模型驱动,每个预测都可作为概率或期望值解释。这使得相比使用了目标、直接优化分类精度或排序效果的模型(zeroone 损失、各种 hinge 损失等等),它们修补漏洞更加简单。如果通过对比或检查产品系统,发现训练里的概率偏离了预测概率,就可能存在问题。
比如说,在线性回归、逻辑回归、泊松回归之中,有的数据子集里平均预期和平均标签相等(1-moment 校准,或者普通校准 )。对于一个值要么是 0 要么是 1 的特征,三个特征值为 1 的样例集就会被校准。同样地,若某特征下所有样例的特征值都是 1,它们都会被校准。
对于简单的模型,处理反馈回路( feedback loops )更加容易。我们经常用这些概率预期来做决定:比如以期望值(点击概率/下载量等)为标准对发布消息进行降序排列。但要记住,当决定采用那个模型的时候,你的决定比给定模型数据的可能性( the likelihood of the data given the model )更加重要(参考第 21 条)。
质量排序是一门高雅的艺术,而垃圾信息过滤是一场战争。对于使用你系统的人,你用来判断高质量消息的信号十分显而易见。然后,他们会据此调整他们的发布信息来获得这些属性。因此,你的质量排序应当专注于有信誉的内容——不应该让质量排序学习器退化到给垃圾信息高排名。同样的,重口味内容应当与质量排序分开。而垃圾信息过滤是另一回事了。你需要创建的特征会不断变化,对此要有心理准备。通常,你加入系统里的规则有些很显而易见(比如,若一个发布信息得到超过三个“垃圾信息”票数,不要恢复它)。任何学习到的模型需要至少每天更新。内容生产者的名誉会起到相当大的作用。
在某个层级,这两个系统的输出需要整合在一起。需要注意的是,在搜索结果里过滤垃圾信息,比过滤垃圾邮件要更加强力。 为了高质量的分类器而去除训练数据中的垃圾,已是行业标准。
未完待续,请见雷锋网“谷歌机器学习白皮书全解析 43 条黄金法则(二)”。谷歌白皮书原文地址:http://martin.zinkevich.org/rules_of_ml/rules_of_ml.pdf
相关文章: