运营一个系统比开发一个系统更重要
by Xu Wenhao
互联网公司和软件公司最大的不同在于,即使对于技术团队来说,开发工作也只是一小部分工作,如何使得整个系统运营起来,才是重头戏,这是过去一年感悟最深的一点;而对于像广告质量这样的技术团队来说,运营和开发可以说是完全不可分离的。过去一年,在这点上,走了很多弯路,犯了很多错误,有很多可以总结的地方。从Quora上看到这样一个问题,“What are the keys to operationalizing a machine learning ranking system from an organization / engineering management point of view?”
觉得唯一的一个回答就很好,翻译一下以记之,虽然做不到信达雅,但是基本意思应该能描述对。
这个问题的大概内容是这样的:
如果从组织管理/工程管理的角度来看,什么是将一个机器学习的Ranking系统运营起来的关键点?
对于那些有基于机器学习或者其他方式有Ranking系统的组织,可以保证他们运行平稳,并且随着时间的推移慢慢进步?哪些监控是重要的?如何定义目标,目标由谁来定义?如何分辨效果的提升来自于Feature工程团队还是核心算法上的提升?哪些严重依赖于Ranking的组织如何为这些来构造他们的流程?
目前唯一可见的回答,来自前Google的工程师Brandon Ballinger:
我之前在Google做语音识别和广告,这两者都以机器学习作为他们的核心。下面是我从“野外”学到的如何运营一个机器学习系统的一些重要的经验和教训
- 将你的成功的指标定义为让用户高兴。传统的精确性的指标,比如precision, square error, ROC等等并不能捕捉到那些你真正关心的 — — 用户对于你的模型是如何反应的。例如,如果你运营一个广告系统,你的指标应该是每个PV的收入以及点击率。完全有可能,由于辛普森悖论,你有一个error rate减少了的模型,但是他带来的收入却降低了。
- 核心指标下降是很严重的问题。你需要把核心指标的大幅下降当成和一个服务器当机或者数据库中数据损坏一样严重的问题。Oncall的人需要尝试尽快诊断问题,并且必要时把别人拉进来一起解决问题
- 对每次Model的Launch做A/B测试。你应当始终并行运行两个模型,给不同的用于用不同的模型,然后比较用户行为。这是唯一可以确保你知道你在做正确的事情的办法。
- 小心丑小鸭效应。机器学习系统会在从自己的错误中学习的过程中变得更加准确。这意味着,新的模型有一个与生固来的缺陷:你的历史训练数据包含着过去模型中的错误,但不是你新训练的模型的错误。导致你的新模型一开始可能像一个丑小鸭,但是如果你用他来决策用户看到的内容,他最后会变成一个漂亮的天鹅。你可以通过将一小部分流量切给新模型,来部分抵消丑小鸭效应,然后慢慢随时间提高这个百分比。
- 使得算法对于噪声Feature健壮。类似于L1 regularization这样的技术可以使得你的机器学习算法对Feature进行剪枝,修剪掉那些对于预测的准确性贡献很小的Feature。这可以帮助你很好地拆分你的团队:一些人专注于算法,另一些人写Feature喂给算法。那些寻找Feature的人,可以直接“把东西扔进锅里”,然后让算法找出他们究竟好还是不好。(类似的,你应该通过确保合理的收敛性来选择一个算法)
- 你可以部分地将架构和算法团队解耦合。基本上,大部分机器学习算法都是在累计一个分布式的hash table的统计信息,然后将这些统计信息合并成一个分数。开发一个分布式的hash table是和开发一个用于累计的算法不同的任务,可以由不同的子Team完成。然后,让这些人一起工作仍然是很重要的。例如,一些算法在写入和写入可用之前延时的“最终一致”的系统中(例如Dynamo),会有所波动。所以这只是一个部分解耦合,你仍然需要团队中有连接架构和算法的“桥梁”人员。
- 在在线系统和批处理系统之间选择的时候要小心。一个在线系统可以实时学习,对于新的用户行为,可以在发生之后的几分钟内有所反应。但是这回带来巨大的开销,一个在线系统需要2–3倍的时间区开发和维护,而且他对瞬间的变化更加敏感。举个例子,如果你突然接收到了很多垃圾信息,这些噪声会立刻被吸收进你的系统并且开始降低用户的体验。类似的,一台机器如果没有可运行的内容了,如果网络连接中断了,或者一个特定的机器变慢了(导致Feature“歪了”),模型的某个输入开始生产垃圾,等等。
- 为所有东西打上版本。一个训练过的模型依赖于稳定的标识,如果你更改了某个标识,模型立刻就过时了。例如,如果你将用户的语言(“en-us”)作为一个feature。那么当有些人提交了一个一行的修改,用下划线替换了短横线(“en_us”)。这使得模型立刻“忘记”了所有从”en-us”中学到的,使得所有的语言看起来都是一样的。所以为所有会在你模型中生成标识的代码和数据的变更都打上版本。
- 你需要咬碎100–1000倍于实时的数据。如果你的训练数据来自于整整一年的历史数据,然后你的学习过程是10倍于实时,那他需要一个月来测试一个新Feature。把所有的东西都写成Map-Reduce或者Storm Topology使得你可以在数据变得足够大的时候仍然可以扩展。
看了一下,里面有不少错误我们都犯过,包括过去一个Q我们觉得由于团队小应该快点冲而省略掉的东西,现在看来也还是省略不掉的,而之前做对的部分也都是来自老大们的经验,希望今年少走弯路效果好啊。
tags: