论文地址: 机器学习:技术债务的高息信用卡 – Sculley et al. 2014
    今天的论文为生产中的机器学习系统的开发和维护人员提供了一些实用的建议。作者警告我们,匆忙推出1.0版很容易,但后续的改进可能会出人意料地困难。当你通读这篇文章时,你会感觉到其中所包含的教训是谷歌来之不易的经验的结果。有些课程属于“仅仅因为涉及到机器学习并不意味着你可以忘记良好的软件工程实践”的一般范畴,但其他课程,以及对我来说更有趣的课程,指出了机器学习系统特有的陷阱。考虑到创业公司都急于建立基于“X+AI”的业务,这似乎是非常及时的建议。

    本文概述的技术债务的主要类别是:信息隐藏和封装更改影响方面的挑战;隐藏回来的数据依赖关系;粘合代码和配置;以及在变化的外部世界和在某个模型中捕获的对该世界的理解之间的漂移。

    或许最重要的洞见是,技术债务是一个工程师和研究人员都需要注意的问题。以大幅度提高系统复杂度为代价而提供微小精度效益的研究解决方案很少是明智的做法。即使添加一两个看似无害的数据依赖项,也可能会减慢进一步的进度。偿还技术债务并不总是像证明一个新定理那样令人兴奋,但它是持续强劲创新的关键部分。为复杂的机器学习系统开发整体的、优雅的解决方案是非常有价值的工作。

    信息隐藏与变更封装
    机器学习模型是制造纠缠并使改进的隔离实际上不可能的机器。具体来说,假设我们有一个在模型中使用特性x1…xn的系统。如果我们改变x1中值的输入分布,那么不管模型是以批处理方式重新训练还是允许以在线方式进行调整,其余特性的重要性、权重或使用都可能改变这一点。添加新功能xn+1可能会导致类似的更改,删除任何功能xj也可能导致类似的更改。没有输入是真正独立的。这里我们称之为CACE原则:改变任何事情都会改变一切

    • 如果我们知道什么是重要的先验知识,我们就不需要使用机器学习来发现它!因此,一个模型有点像一个巨大的混合机,我们在其中输入大量的信息并得出结果,但是对输入的各种变化的敏感性很难预测,几乎不可能分离出来。你能做什么?这里没有银弹,但作者确实提供了三种可能有帮助的策略。

    • 你可以隔离模型,而不是提供合奏。当然,纠缠的问题仍然存在于任何一个模型中,此外,“在大规模的设置中,这样的策略可能被证明是不可伸缩的。”

    • 发展深入了解模型预测行为的方法。你需要投资让模型对你来说不再是一个黑匣子——例如通过可视化工具。更进一步说,我已经和一些公司谈过,他们的商业模式的一个重要组成部分是能够解释他们的ML模型所做的决定,在某些情况下甚至是一个监管要求。如果那可能是你,这是你需要非常仔细考虑的事情,就在前面。

    使用更复杂的正则化方法,以便在训练中使用的目标函数中反映性能预测成本的任何增加。“这种方法可能有用,但远不能保证,而且可能通过增加系统复杂性增加更多债务,而不是通过减少纠缠而减少债务。”

    另一个寻找偶发耦合的地方是隐藏的反馈回路,特别是与未声明的消费者相关的反馈回路。作者所说的未声明的消费者,仅仅是指系统在没有意识到他们正在这样做的情况下使用模型的输出。如果他们不根据影响模型输入参数之一的信息采取某些行动,则很容易产生隐藏的反馈回路:

    想象一下,在我们的新闻标题CTR(点击率)预测系统中,有另一个组件负责“智能地”确定用于标题的字体大小。如果此字体大小模块开始将CTR用作输入信号,并且字体大小对用户单击的倾向有影响,则在字体大小中包含CTR将添加新的隐藏反馈循环。很容易想象这样一个案例,这样一个系统将逐渐和无休止地增加所有头条的大小。

    数据依赖性
    虽然通过静态分析、链接图等可以相对容易地识别代码依赖项,但数据依赖项具有类似的分析工具的情况要少得多。因此,构建难以理清的大型数据依赖关系链可能不适当地容易。

    例如,一些输入信号会随时间改变行为。遵循CACE原则,这些变化,即使是作为改进的意图,也可能产生难以预测的后果。

    另一种数据依赖是在模型中建立特性,其中一些特性在精度方面提供的增量值很小。有很多方法会导致依赖性利用不足——早期很重要但现在不再重要的遗留功能,一次添加大量功能,而不是找出真正起作用的功能,或者是为了提高精度而增加的功能,但这些功能并不能真正证明其复杂性。定期修剪这样的特征是很重要的。

    例如,假设在团队合并之后,为了简化从旧产品编号方案到新产品编号方案的转换,这两个方案都保留在系统中作为特性。新产品只能得到一个新的号码,但旧产品可能两者都有。机器学习算法没有理由减少对旧数字的依赖。一年后,有人善意地清理了停止用旧数字填充数据库的代码。回归测试无法检测到这种变化,因为没有其他人再使用它们。对于机器学习系统的维护者来说,这不是一个好日子…
    能够理解数据依赖关系的工具可以极大地帮助特性修剪。谷歌的一个团队构建了一个自动化的功能管理工具:
    自从采用这一方法以来,谷歌的一个团队每季度都能安全地删除数千行与功能相关的代码,并自动验证版本和其他问题。该系统在许多情况下防止了在新模型中意外使用已弃用或损坏的功能。
    最后一个数据依赖气味是通过在现有模型上构建“修正”来重新调整其用途。这可以给一个快速的初步胜利,但使它显着更昂贵的分析改进模型在未来。

    其他95%(胶水代码和配置)
    让学术界感到惊讶的是,在许多机器学习系统中,只有一小部分代码实际上在做“机器学习”。当我们认识到一个成熟的系统最终可能(最多)是5%的机器学习代码和(至少)95%的粘合代码时,重新实现而不是重用笨拙的API看起来是一个更好的策略…
    这里要解决的问题是,许多机器学习库被打包为自包含的人工制品,这可能会导致大量的粘合代码(例如,在从Java到R或matlab的转换中)。如果你真的找不到适合你更广泛的系统架构的东西,你最好重新实现算法(5%),以避免更多粘合代码的痛苦。
    一个相关的症状是管道丛林——过于复杂的数据准备管道。

    只有从整体上考虑数据采集和特征提取,才能避免管道丛林。取消管道丛林和从头开始重新设计的全新方法确实是工程努力的一项重大投资,但可以大大降低持续成本,加快进一步创新。

    一旦一个系统开始僵化为胶水代码和管道丛林,诱惑就是执行额外的实验,只需在主要生产代码中调整和实验代码路径。当然,经常这样做,你只会把事情搞得更糟。

    作为一个现实世界的轶事,在谷歌一个重要的机器学习系统最近的清理工作中,人们发现有可能删除数万行未使用的实验代码路径。使用更紧密的API进行后续重写,可以在显著降低工作和生产风险以及最小化增量系统复杂性的情况下执行新算法的实验。

    最后,在本节中,“配置往往是真实世界的混乱侵入美丽算法的地方:”

    考虑下面的例子。功能A从9/14到9/17记录错误。功能B在10/7之前的数据上不可用。由于日志格式的更改,用于计算功能C的代码必须在11/1之前和之后更改数据。特征D不在生产中,因此在实时设置中查询模型时必须使用替代特征D′和D“。中频特性
    使用Z时,由于查找表的原因,必须为用于培训的作业提供额外的内存,否则它们将无法有效地进行培训。由于延迟限制,特性Q不允许使用特性R。所有这些混乱使得配置很难正确修改,也很难推理。然而,配置中的错误可能代价高昂,导致严重的时间损失、计算资源浪费或生产问题。

    配置更改应与代码更改同等小心,并由对等方仔细审查。(另见“Facebook的整体配置管理”)。

    当世界继续前进时会发生什么?
    经验表明,外部世界很少是稳定的。事实上,不断变化的世界是机器学习技术债务的来源之一。

    与手动设置决策阈值(例如,显示广告或不显示广告)不同,考虑通过对保留的验证数据进行评估来设置学习阈值。因果关系不明的相关特征也可能导致问题:

    这似乎不是一个大问题:如果两个特征总是相关的,但只有一个是真正的因果关系,那么将两者归因于并依赖于它们观察到的共同发生似乎仍然是可以的。然而,如果世界突然停止使这些特征同时出现,预测行为可能会发生显著变化。用于区分相关效应的各种ML策略超出了我们的范围;在[Bottou 2013]中给出了一些优秀的建议和参考。在本文中,我们注意到非因果关系是隐藏债务的另一个来源。

    最后,实时监控系统至关重要。建议测量预测偏差,并在系统正在采取的操作数超过某个阈值时发出警报。

    在按预期工作的系统中,通常情况下,预测标签的分布等于观察到的标签的分布。这决不是一个全面的测试,因为它可以通过一个空模型来满足,该模型只预测标签出现的平均值,而不考虑输入特性。然而,这是一个出人意料的有用的诊断方法,而像这样的指标的变化往往预示着一个需要注意的问题…