互联网公司和软件公司最大的不同在于,即使对于技术团队来说,开发工作也只是一小部分工作,如何使得整个系统运营起来,才是重头戏,这是过去一年感悟最深的一点;而对于像广告质量这样的技术团队来说,运营和开发可以说是完全不可分离的。过去一年,在这点上,走了很多弯路,犯了很多错误,有很多可以总结的地方。从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我们觉得由于团队小应该快点冲而省略掉的东西,现在看来也还是省略不掉的,而之前做对的部分也都是来自老大们的经验,希望今年少走弯路效果好啊。

20. March 2011 · 14 comments · Categories: Tech · Tags: , ,

这一阵为了工作上的关系,花了点时间学习了一下LDA算法,说实话,对于我这个学CS而非学数学的人来说,除了集体智慧编程这本书之外基本没怎么看过机器学习的人来说,一开始还真是摸不太到门道,前前后后快要四个月了,算是基本了解了这个算法的实现,记录一下,也供后来人快速入门做个参考。

一开始直接就下了Blei的原始的那篇论文来看,但是看了个开头就被Dirichlet分布和几个数学公式打倒,然后因为专心在写项目中的具体的代码,也就先放下了。但是因为发现完全忘记了本科学的概率和统计的内容,只好回头去看大学时候概率论的教材,发现早不知道借给谁了,于是上网买了本,花了几天时间大致回顾了一遍概率论的知识,什么贝叶斯全概率公式,正态分布,二项分布之类的。
后来晚上没事儿的时候,去水木的AI版转了转,了解到了Machine Learning的圣经PRML,考虑到反正也是要长期学习了,搞了电子版,同时上淘宝买了个打印胶装的版本。春节里每天晚上看一点儿,扫了一下前两章,再次回顾了一下基本数学知识,然后了解了下贝叶斯学派那种采用共轭先验来建模的方式。于是再次尝试回头去看Blei的那篇论文,发现还是看不太懂,于是又放下了。然后某天Tony让我准备准备给复旦的同学们share一下我们项目中LDA的使用,为了不露怯,又去翻论文,正好看到Science上这篇Topic Models Vs. Unstructured Data的科普性质的文章,翻了一遍之后,再去PRML里看了一遍Graphic Models那一张,觉得对于LDA想解决的问题和方法了解了更清楚了。之后从search engine里搜到这篇文章,然后根据推荐读了一部分的Gibbs Sampling for the Uninitiated。之后忘了怎么又搜到了Mark Steyvers和Tom Griffiths合著的Probabilistic Topic Models,在某个周末往返北京的飞机上读完了,觉得基本上模型训练过程也明白了。再之后就是读了一下这个最简版的LDA Gibbs Sampling的实现,再回过头读了一下PLDA的源码,基本上算是对LDA有了个相对清楚的了解。

这样前前后后,也过去了三个月,其实不少时间都是浪费掉的,比如Blei的论文在没有任何相关知识的情况下一开始读了好几次,都没读完而且得到到信息也很有限,如果重新总结一下,我觉得对于我们这些门外汉程序员来说,想了解LDA大概需要这些知识:

  • 有基本的概率论的知识,这个拿个大学的课本大概翻一下就好了
  • PRML的前两章和Graphic Model那部分需要浏览一下,了解一下所谓的贝叶斯学派的方法论,然后理解共轭先验的概念,以及Graphic Model的图形表达的意思。
  • 了解一下Gibbs Sampling的概念
  • 直接读Steyvers的Probabilistic Topic Models,没必要一定去读Blei的论文,开创性的论文不一定好读,最典型的例子就是Paxos了,30多页里多少都是希腊人名,对于英文不够精通,学术训练比较少的工程师来说,其实很痛苦,意义也不大。
  • 对照着Probabilistic Topic Models直接看LdaGibbsSampling.java的源码

基本上这样一圈下来,基本概念和算法实现都应该搞定了,当然,数学证明其实没那么容易就搞定,但是对于工程师来说,先把这些搞定就能干活了,这个步骤并不适合各位读博士发论文的同学们,但是这样先看看也比较容易对于这些数学问题的兴趣,不然,成天对这符号和数学公式,没有整块业余时间的我是觉得还是容易退缩放弃的。

发现作为工程师来说,还是看代码比较有感觉,看实际应用的实例比较有感觉,看来不能把大部分时间花在PRML上,还是要多对照着代码看。