你实践中学到的最重要的机器学习经验是什么？
理解模型的基本假设，看自己的数据是否符合这种假设。任何模型都是有某种假设的，如果数据不符合这种假设，就不太可能学出有意义的模型并用于预测。 比如LDA（主题模型），假设是在同样一批文档中经常共现的词，语义上往往是相关的。这种特性不仅在自然语言中成立，在一些领域，比如每个人经常访问的网址集合，可能也是成立的，所以LDA也可以拿过去用。但如果数据不符合这个特性，套用LDA就是没有意义的，比如每个球队里的队员，可能并没有因为属于一个球队而具有什么相似性。 再举个例子，CNN（卷积神经网络），它的基本假设是特征的不同维度之间有局部相关性，卷积操作可以抓住这只局部相关性，形成新的特征。比如自然语言里，有重复出现的bigram，或者图像里代表性的局部像素块。不满足这种局部相关性的数据，比如收到的邮件序列，这种局部相关性很弱，那用CNN就不能抓到有用的特征。 最后，高斯copula，在量化金融里曾被广泛使用，把债券之间非高斯的相关性用copula转化成高斯然后拟合。然而这个模型隐含的假设是这种相关性符合瘦尾分布(thin tailed distribution)，即罕见事件发生的概率非常非常低。这个不合理假设导致对黑天鹅事件概率严重低估，曾被视为2008年金融危机的根源之一。
重视代码的工程质量, 做research的时候很喜欢写prototype code, 很多点子的源码是"糊"出来这样是不对的. 前期为了尽快的出一点结果看看往往会忘记抽象, 到了后面很多时候就是在对前面的很糟糕的代码修修补补, 又舍不得重写, 最后往往会因为代码过于扭曲不方便扩展(探索)反而阻碍了尝试更多的点子. 举几个例子, 最近我在做Deep RL方面的工作, 这方面相比于其他的Machine Learning task一个很不同的地方就在于整个系统的层次很多, 意思就是说为了解决一个RL问题会有许多个components interplay. 有兴趣的话可以看看这篇A Locally Linear Latent Dynamics Model for Control from Raw Images 和这个 Policy Learning with Deep Dynamical Models, 这两篇都是采用一些Optimal Control的思路来做RL, 比方说第一篇e2c就会比较麻烦, 因为整个模型包含了一个encoder, decoder (VAE), 还有一个dynamics network. 除此以外在evaluate模型的时候会需要用到iLQR, 又是一个分开的组件. 这种模型最大的问题在于如果说模型不fit的话你很难知道问题具体是出现在哪个部分. Loss写错了? VAE实现错了, 又或者超参没调好. 如果说你的整个系统耦合很紧的话尝试新的想法就会需要花很多时间. 机器学习系统最大的问题就是你的需求变化是很快很快的, 很多时候一份代码只是代表了当前的一个工作流, 有可能真的就只用一次. 我个人做项目的时候, 一般会把这几样东西的灵活性放在很前面, 写代码的时候会尽量考虑这些东西 1. 设置与超参, 是用一个单独的文件写死然后其他的文件引用吗? 还是从命令行读? 假设现在我要开始重点调超参了这两种方法是不是会很难自动调. 或者可以试试Hyperopt hyperopt/hyperopt? 2. 数据处理的组件是否和模型分离的, 这个对于一般的CV问题其实比较好解决, 因为数据集就是一个数据集, RL会复杂一点因为涉及到online sample的问题, 那么线上处理input的代码放在哪(downsample, grayscale, normalize). 如果用gym的话可以用一个Wrapper这个class怎么用. 3. 网络结构写死. 如果说我现在改模型结构是否会break很多的code. 比方说e2c里面其实有很多种方法来encode你的latent state, 如果说一开始你假设了一种方法可是你现在突然想尝试另一种, oh well... 说真的这是一个很tricky的问题, 因为如果说你用一个2D tensor的话你encoder 如果第一层是卷积就不行, owwww我听到你说你把这部分分到input pipeline里面了, 那你在哪里声明这个呢, training的driver script里面? model takes configuration? 4. checkpointing. 这个也很麻烦, 如果说模型结构都变了我如何读取之前的checkpoint来做分析 :D. 我个人是一个很强迫症的人, 所以我会在这些很纠结的小细节上面, 总希望设计出一套完美的接口实所有的可能性, 每次总是思前想后的去想办法"自动化"这些东西. 这样的话我只需要在命令行hit enter就可以把所有的训练做完, 超参调完, analysis 做完, 图画完, metrics算完. 后来我明白了, 永远都不会有这样的系统的, 研究这项工作本身就充满了太多的不确定性(开发也是), 永远都不会有完美的系统, 只会有不断变化的系统. 所以最重要的不是精心雕琢现在的这个借口(也没有时间), 而是在把借口设计的ok的情况下把变化所造成的各种作用控制到最小. 这其实也是built tools, 造当下最合适的工具. 这些工具不一定要很复杂, 但是确实是当下最好用的. 早一些小工具, 在需要的时候把它们变成大的. 同时希望这些工具能够最后陪伴你做出想要的结果. 未完待续..  